From 9544a1cfb20e98f602611e334e278abee672c239 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 29 Jul 2014 17:23:05 +0200 Subject: [PATCH 001/269] New package: Tangential_complex --- Tangential_complex/dont_submit | 0 .../include/CGAL/Tangential_complex.h | 64 +++++++++++++++++++ .../package_info/Tangential_complex/copyright | 2 + .../Tangential_complex/copyright.txt | 0 .../Tangential_complex/description.txt | 3 + .../Tangential_complex/license.txt | 1 + .../Tangential_complex/maintainer | 1 + .../test/Tangential_complex/CMakeLists.txt | 37 +++++++++++ .../test_tangential_complex.cpp | 12 ++++ 9 files changed, 120 insertions(+) create mode 100644 Tangential_complex/dont_submit create mode 100644 Tangential_complex/include/CGAL/Tangential_complex.h create mode 100644 Tangential_complex/package_info/Tangential_complex/copyright create mode 100644 Tangential_complex/package_info/Tangential_complex/copyright.txt create mode 100644 Tangential_complex/package_info/Tangential_complex/description.txt create mode 100644 Tangential_complex/package_info/Tangential_complex/license.txt create mode 100644 Tangential_complex/package_info/Tangential_complex/maintainer create mode 100644 Tangential_complex/test/Tangential_complex/CMakeLists.txt create mode 100644 Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp diff --git a/Tangential_complex/dont_submit b/Tangential_complex/dont_submit new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h new file mode 100644 index 00000000000..fd0e5d1dc2b --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -0,0 +1,64 @@ +// 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 TANGENTIAL_COMPLEX_H +#define TANGENTIAL_COMPLEX_H + +#include + +#include +#include +#include + +#include + +namespace CGAL { + +/// The class Tangential_complex represents a tangential complex +template < + typename Kernel, + int Intrinsic_dimension, + typename Tr = Regular_triangulation > > > +> +class Tangential_complex +{ + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + typedef typename std::vector Tangent_space_base; + +public: + /// Constructor + Tangential_complex() {} + + /// Destructor + ~Tangential_complex() {} + +private: + std::vector m_points; + std::vector m_tangent_spaces; + std::vector m_triangulations; + +}; // /class Tangential_complex + +} // end namespace CGAL + +#endif // TANGENTIAL_COMPLEX_H diff --git a/Tangential_complex/package_info/Tangential_complex/copyright b/Tangential_complex/package_info/Tangential_complex/copyright new file mode 100644 index 00000000000..8932b3233d2 --- /dev/null +++ b/Tangential_complex/package_info/Tangential_complex/copyright @@ -0,0 +1,2 @@ +INRIA Sophia-Antipolis (France) + diff --git a/Tangential_complex/package_info/Tangential_complex/copyright.txt b/Tangential_complex/package_info/Tangential_complex/copyright.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tangential_complex/package_info/Tangential_complex/description.txt b/Tangential_complex/package_info/Tangential_complex/description.txt new file mode 100644 index 00000000000..b8969f7fc3e --- /dev/null +++ b/Tangential_complex/package_info/Tangential_complex/description.txt @@ -0,0 +1,3 @@ +Tangential complex + +This CGAL component provides an implementation of the tangential complex. diff --git a/Tangential_complex/package_info/Tangential_complex/license.txt b/Tangential_complex/package_info/Tangential_complex/license.txt new file mode 100644 index 00000000000..8bb8efcb72b --- /dev/null +++ b/Tangential_complex/package_info/Tangential_complex/license.txt @@ -0,0 +1 @@ +GPL (v3 or later) diff --git a/Tangential_complex/package_info/Tangential_complex/maintainer b/Tangential_complex/package_info/Tangential_complex/maintainer new file mode 100644 index 00000000000..769c1668e20 --- /dev/null +++ b/Tangential_complex/package_info/Tangential_complex/maintainer @@ -0,0 +1 @@ +ClĂ©ment Jamin \ No newline at end of file diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt new file mode 100644 index 00000000000..7ba896e34c7 --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -0,0 +1,37 @@ +# 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() + +find_package(CGAL QUIET COMPONENTS Core ) + +if ( CGAL_FOUND ) + include( ${CGAL_USE_FILE} ) + include( CGAL_CreateSingleSourceCGALProgram ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + include_directories (BEFORE "../../include") + include_directories (BEFORE "include") + + create_single_source_cgal_program( "test_tangential_complex.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() + diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp new file mode 100644 index 00000000000..7e912492798 --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -0,0 +1,12 @@ +#include +#include + +int main() +{ + typedef CGAL::Epick_d > Kernel; + const int INTRINSIC_DIMENSION = 2; + + CGAL::Tangential_complex tc; + + return 0; +} \ No newline at end of file From f466414a7529708cb971301a1c5f16e2e071cba5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 2 Sep 2014 18:33:04 +0200 Subject: [PATCH 002/269] Fix a bug in the copy-constructor of TDS When the dimension is -1, there is one vertex: the infinite vertex. --- Triangulation/include/CGAL/Triangulation_data_structure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 583f798446e..afd07eea7bb 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -195,7 +195,7 @@ public: cto = full_cells_begin(); while( cto != full_cells_end() ) { - for( int i = 0; i <= current_dimension(); ++i ) + for( int i = 0; i <= (std::max)(0, current_dimension()); ++i ) { associate_vertex_with_full_cell(cto, i, vmap[cto->vertex(i)]); cto->set_neighbor(i, cmap[cto->neighbor(i)]); From 07e40bd28cae7a479d9bc305d0b637d3cbf6e853 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 2 Sep 2014 18:43:43 +0200 Subject: [PATCH 003/269] Builds the local triangulations --- .../include/CGAL/Tangential_complex.h | 121 +++++++++++++++++- .../test_tangential_complex.cpp | 14 +- 2 files changed, 126 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fd0e5d1dc2b..c7528ba5ac0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -35,27 +35,134 @@ namespace CGAL { /// The class Tangential_complex represents a tangential complex template < typename Kernel, - int Intrinsic_dimension, + int Intrinsic_dimension, typename Tr = Regular_triangulation > > > > class Tangential_complex { - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Vector_d Vector; - typedef typename std::vector Tangent_space_base; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + + typedef Tr Triangulation; + typedef typename Triangulation::Point Tr_point; + typedef typename Triangulation::Bare_point Tr_bare_point; + typedef typename Triangulation::Vertex_handle Tr_vertex_handle; + + typedef typename std::vector Tangent_space_base; + + typedef typename std::vector Point_container; + typedef typename std::vector Tr_container; + typedef typename std::vector TS_container; + + // Stores the index of the original Point in the ambient space + struct Tr_point_with_index + : public Tr_point + { + Tr_point_with_index(const Tr_point &p, std::size_t i) + : Tr_point(p), index(i) {} + + std::size_t index; + }; public: /// Constructor Tangential_complex() {} + + /// Constructor for a range of points + template + Tangential_complex(InputIterator first, InputIterator last) + : m_points(first, last) {} /// Destructor ~Tangential_complex() {} + void compute_tangential_complex() + { + Point_container::const_iterator it_p = m_points.begin(); + Point_container::const_iterator it_p_end = m_points.end(); + // For each point p in ambient space + for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) + { + m_triangulations.push_back(Triangulation(Intrinsic_dimension)); + Triangulation &local_tr = m_triangulations.back(); + + // Estimate the tangent space + Tangent_space_base ts = compute_tangential_space(*it_p); + + // Insert p + Tr_point wp = project_point(*it_p, ts); + Tr_point_with_index tpwi(wp, i); + Tr_vertex_handle vh = local_tr.insert(tpwi); + + // Build a minimal triangulation in the tangent space + // (we only need the star of p) + Point_container::const_iterator it2_p = m_points.begin(); + for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) + { + // ith point = p, which is already inserted + if (j != i) + { + Tr_point wp = project_point(*it2_p, ts); + Tr_point_with_index tpwi(wp, j); + local_tr.insert_if_in_star(tpwi, vh); + } + } + } + } + private: - std::vector m_points; - std::vector m_tangent_spaces; - std::vector m_triangulations; + Tangent_space_base compute_tangential_space(const Point &p) const + { + Tangent_space_base ts; + ts.reserve(Intrinsic_dimension); + // CJTODO: this is only for a sphere in R^3 + Vector n = Kernel().point_to_vector_d_object()(p); // CJTODO: change that? + Vector t1(-p[1] - p[2], p[0], p[0]); + Vector t2(p[1] * t1[2] - p[2] * t1[1], + p[2] * t1[0] - p[0] * t1[2], + p[0] * t1[1] - p[1] * t1[0]); + + Kernel k; + Get_functor::type sqlen(k); + //Get_functor::type scale(k); + //ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); + //ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); + + FT t1_len = CGAL::sqrt(sqlen(t1)); + FT t2_len = CGAL::sqrt(sqlen(t2)); + for (int i = 0 ; i < Ambient_dimension::value ; ++i) + { + t1[i] /= t1_len; + t2[i] /= t2_len; + } + ts.push_back(t1); + ts.push_back(t2); + + return ts; + } + + Tr_point project_point(const Point &p, const Tangent_space_base &ts) const + { + std::vector coords; + coords.reserve(Intrinsic_dimension); + for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) + { + //coords[i] = Kernel().point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that + Kernel k; + Get_functor::type scp(k); + coords.push_back(scp(k.point_to_vector_d_object()(p), ts[i])); + } + + return Tr_point( + Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), 0); // CJTODO: poids + } + +private: + Point_container m_points; + TS_container m_tangent_spaces; + Tr_container m_triangulations; }; // /class Tangential_complex diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 7e912492798..0968583bf73 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -1,12 +1,22 @@ #include #include +#include int main() { - typedef CGAL::Epick_d > Kernel; + typedef CGAL::Epick_d > Kernel; + typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; - CGAL::Tangential_complex tc; + CGAL::Random_points_on_sphere_3 generator(3.0); + std::vector points; + points.reserve(50); + for (int i = 0; i != 50; ++i) + points.push_back(*generator++); + + CGAL::Tangential_complex tc( + points.begin(), points.end()); + tc.compute_tangential_complex(); return 0; } \ No newline at end of file From 589730219224ebdabde1bc81093362a7af1a0472 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 3 Sep 2014 19:05:13 +0200 Subject: [PATCH 004/269] One more step towards the Tangential complex --- .../include/CGAL/Tangential_complex.h | 210 ++++++++++++++++-- .../test_tangential_complex.cpp | 12 +- 2 files changed, 197 insertions(+), 25 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c7528ba5ac0..0b8dd2d851b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -28,7 +28,12 @@ #include #include +#include // CJTODO TEMP + #include +#include +#include +#include namespace CGAL { @@ -36,8 +41,21 @@ namespace CGAL { template < typename Kernel, int Intrinsic_dimension, - typename Tr = Regular_triangulation > > > + typename Tr = Regular_triangulation + < + Regular_triangulation_euclidean_traits< + Epick_d > >, + + Triangulation_data_structure + < + typename Regular_triangulation_euclidean_traits< + Epick_d > >::Dimension, + Triangulation_vertex > >, std::size_t >, + Triangulation_full_cell > > > + > + > > class Tangential_complex { @@ -46,25 +64,28 @@ class Tangential_complex typedef typename Kernel::Vector_d Vector; typedef Tr Triangulation; + typedef typename Triangulation::Geom_traits Tr_traits; typedef typename Triangulation::Point Tr_point; typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; + typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename std::vector Tangent_space_base; + typedef std::pair Tr_and_VH; typedef typename std::vector Point_container; - typedef typename std::vector Tr_container; + typedef typename std::vector Tr_container; typedef typename std::vector TS_container; // Stores the index of the original Point in the ambient space - struct Tr_point_with_index + /*struct Tr_point_with_index : public Tr_point { Tr_point_with_index(const Tr_point &p, std::size_t i) : Tr_point(p), index(i) {} std::size_t index; - }; + };*/ public: /// Constructor @@ -80,40 +101,165 @@ public: void compute_tangential_complex() { + Tr_traits traits; // CJTODO: use the Triangulation's traits instance + + // We need to do that because we don't want the container to copy the + // already-computed triangulations (while resizing) since it would + // invalidate the vertex handles stored beside the triangulations + m_triangulations.reserve(m_points.size()); + m_tangent_spaces.reserve(m_points.size()); + Point_container::const_iterator it_p = m_points.begin(); Point_container::const_iterator it_p_end = m_points.end(); // For each point p in ambient space for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) { - m_triangulations.push_back(Triangulation(Intrinsic_dimension)); - Triangulation &local_tr = m_triangulations.back(); + m_triangulations.push_back(std::make_pair( + Triangulation(Intrinsic_dimension), + Tr_vertex_handle())); + Triangulation &local_tr = m_triangulations.back().first; + Tr_vertex_handle ¢er_vertex = m_triangulations.back().second; // Estimate the tangent space - Tangent_space_base ts = compute_tangential_space(*it_p); + m_tangent_spaces.push_back(compute_tangent_space(*it_p)); - // Insert p - Tr_point wp = project_point(*it_p, ts); - Tr_point_with_index tpwi(wp, i); - Tr_vertex_handle vh = local_tr.insert(tpwi); - + //*************************************************** // Build a minimal triangulation in the tangent space // (we only need the star of p) + //*************************************************** + + // First, compute the projected points + std::vector projected_points; + FT max_squared_weight = 0; + projected_points.reserve(m_points.size() - 1); Point_container::const_iterator it2_p = m_points.begin(); for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) { // ith point = p, which is already inserted if (j != i) { - Tr_point wp = project_point(*it2_p, ts); - Tr_point_with_index tpwi(wp, j); - local_tr.insert_if_in_star(tpwi, vh); + Tr_point wp = project_point(*it2_p, *it_p, m_tangent_spaces.back()); + projected_points.push_back(wp); + FT w = traits.point_weight_d_object()(wp); + if (w > max_squared_weight) + max_squared_weight = w; } } + + // Now we can insert the points + + // Insert p + Tr_point wp = traits.construct_weighted_point_d_object()( + traits.construct_point_d_object()(0, 0), + CGAL::sqrt(max_squared_weight)); + center_vertex = local_tr.insert(wp); + center_vertex->data() = i; + + // Insert the other points + std::vector::const_iterator it_wp = projected_points.begin(); + it2_p = m_points.begin(); + for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) + { + // ith point = p, which is already inserted + if (j != i) + { + FT w = CGAL::sqrt(max_squared_weight - traits.point_weight_d_object()(*it_wp)); + std::cerr << w << std::endl; + Tr_point wp = traits.construct_weighted_point_d_object()( + traits.point_drop_weight_d_object()(*it_wp), + w); + /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); + Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ + + Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); + if (vh != Tr_vertex_handle()) + vh->data() = j; + ++it_wp; + } + } + + // CJTODO + std::cerr << "\nChecking topology and geometry..." + << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); + std::stringstream sstr; + sstr << "data/local_tri_" << i << ".off"; + std::ofstream off_stream_tr(sstr.str()); + CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } } + std::ostream &export_to_off(std::ostream & os) + { + const int ambient_dim = Ambient_dimension::value; + if (ambient_dim < 2 || ambient_dim > 3) + { + std::cerr << "Error: export_to_off => ambient dimension should be 2 or 3."; + os << "Error: export_to_off => ambient dimension should be 2 or 3."; + return os; + } + + if (Intrinsic_dimension < 1 || Intrinsic_dimension > 3) + { + std::cerr << "Error: export_to_off => intrinsic dimension should be between 1 and 3."; + os << "Error: export_to_off => intrinsic dimension should be between 1 and 3."; + return os; + } + + std::stringstream output; + + //******** VERTICES ************ + + Point_container::const_iterator it_p = m_points.begin(); + Point_container::const_iterator it_p_end = m_points.end(); + // For each point p + for ( ; it_p != it_p_end ; ++it_p) + { + int i = 0; + for ( ; i < ambient_dim ; ++i) + output << (*it_p)[i] << " "; + if (i == 2) + output << "0"; + output << std::endl; + } + + //******** CELLS ************ + + std::size_t num_cells = 0; + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + const Triangulation &tr = it_tr->first; + Tr_vertex_handle center_vh = it_tr->second; + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each triangulation + for ( ; it_c != it_c_end ; ++it_c) + { + output << Intrinsic_dimension + 1 << " "; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + output << (*it_c)->vertex(i)->data() << " "; + output << std::endl; + ++num_cells; + } + } + + os << "OFF \n" + << m_points.size() << " " + << num_cells << " " + << "0 \n" + << output.str(); + + return os; + } + private: - Tangent_space_base compute_tangential_space(const Point &p) const + Tangent_space_base compute_tangent_space(const Point &p) const { Tangent_space_base ts; ts.reserve(Intrinsic_dimension); @@ -143,26 +289,44 @@ private: return ts; } - Tr_point project_point(const Point &p, const Tangent_space_base &ts) const + // Project the point in the tangent space + // The weight will be the squared distance between p and the projection of p + Tr_point project_point(const Point &p, const Point &origin, + const Tangent_space_base &ts) const { + Kernel k; + Get_functor::type inner_pdct(k); + Get_functor::type diff_points(k); + std::vector coords; + // Ambiant-space coords of the projected point + std::vector p_proj(Ambient_dimension::value, 0); coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { //coords[i] = Kernel().point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that - Kernel k; - Get_functor::type scp(k); - coords.push_back(scp(k.point_to_vector_d_object()(p), ts[i])); + // Compute the inner product p * ts[i] + Vector v = diff_points(p, origin); + FT coord = inner_pdct(v, ts[i]); + coords.push_back(coord); + + // p_proj += coord * v; + for (int i = 0 ; i < Ambient_dimension::value ; ++i) + p_proj[i] += coord * v[i]; } + Point projected_pt(Ambient_dimension::value, + p_proj.begin(), p_proj.end()); return Tr_point( - Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), 0); // CJTODO: poids + Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), + k.squared_distance_d_object()(p, projected_pt)); } private: Point_container m_points; TS_container m_tangent_spaces; - Tr_container m_triangulations; + Tr_container m_triangulations; // Contains the triangulations + // and their center vertex }; // /class Tangential_complex diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 0968583bf73..eba3478a1bd 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -2,21 +2,29 @@ #include #include +#include + int main() { typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; + const int NUM_POINTS = 50; CGAL::Random_points_on_sphere_3 generator(3.0); std::vector points; - points.reserve(50); - for (int i = 0; i != 50; ++i) + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) points.push_back(*generator++); CGAL::Tangential_complex tc( points.begin(), points.end()); tc.compute_tangential_complex(); + + std::stringstream output_filename; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << ".off"; + std::ofstream off_stream(output_filename.str()); + tc.export_to_off(off_stream); return 0; } \ No newline at end of file From 855a475918bae9558b938094066b8f7a9742aa1e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 09:59:02 +0200 Subject: [PATCH 005/269] Fix a bug in the computation of the projected point + debugging output --- .../include/CGAL/Tangential_complex.h | 27 ++++++++++++++----- .../test_tangential_complex.cpp | 7 +++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 0b8dd2d851b..13f89f437a1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -154,6 +154,7 @@ public: CGAL::sqrt(max_squared_weight)); center_vertex = local_tr.insert(wp); center_vertex->data() = i; + std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; // Insert the other points std::vector::const_iterator it_wp = projected_points.begin(); @@ -163,17 +164,28 @@ public: // ith point = p, which is already inserted if (j != i) { - FT w = CGAL::sqrt(max_squared_weight - traits.point_weight_d_object()(*it_wp)); - std::cerr << w << std::endl; + FT squared_dist_to_tangent_plane = + traits.point_weight_d_object()(*it_wp); + FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); Tr_point wp = traits.construct_weighted_point_d_object()( traits.point_drop_weight_d_object()(*it_wp), w); /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ + // CJTODO TEMP + if (squared_dist_to_tangent_plane < 9) + { Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); if (vh != Tr_vertex_handle()) + { + std::cerr << "Inserted point of weight " << w + << "\t(dist to tangent plane = " + << CGAL::sqrt(squared_dist_to_tangent_plane) + << ")" << std::endl; vh->data() = j; + } + } ++it_wp; } } @@ -264,12 +276,15 @@ private: Tangent_space_base ts; ts.reserve(Intrinsic_dimension); // CJTODO: this is only for a sphere in R^3 - Vector n = Kernel().point_to_vector_d_object()(p); // CJTODO: change that? Vector t1(-p[1] - p[2], p[0], p[0]); Vector t2(p[1] * t1[2] - p[2] * t1[1], p[2] * t1[0] - p[0] * t1[2], p[0] * t1[1] - p[1] * t1[0]); + // CJTODO: this is for a plane (test) + //Vector t1(1, 0, 0); + //Vector t2(0, 1, 0); + // Normalize t1 and t2 Kernel k; Get_functor::type sqlen(k); //Get_functor::type scale(k); @@ -300,7 +315,7 @@ private: std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(Ambient_dimension::value, 0); + std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { @@ -311,8 +326,8 @@ private: coords.push_back(coord); // p_proj += coord * v; - for (int i = 0 ; i < Ambient_dimension::value ; ++i) - p_proj[i] += coord * v[i]; + for (int j = 0 ; j < Ambient_dimension::value ; ++j) + p_proj[i] += coord * ts[i][j]; } Point projected_pt(Ambient_dimension::value, diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index eba3478a1bd..d115652f41e 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -10,12 +10,19 @@ int main() typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; +#ifdef _DEBUG const int NUM_POINTS = 50; +#else + const int NUM_POINTS = 500; +#endif CGAL::Random_points_on_sphere_3 generator(3.0); std::vector points; points.reserve(NUM_POINTS); for (int i = 0 ; i != NUM_POINTS ; ++i) + { points.push_back(*generator++); + //points.push_back(Point((double)(rand()%10000)/5000, (double)(rand()%10000)/5000, 0.)); // CJTODO : plane + } CGAL::Tangential_complex tc( points.begin(), points.end()); From 0ab8ef78044c5dc647279654de0e596376246acb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 17:05:18 +0200 Subject: [PATCH 006/269] Do not insert hidden points Hidden points are not handled for now (cherry picked from commit dfb38ed1af52d9faaa113bf26435e7ac65711080) --- Triangulation/include/CGAL/Regular_triangulation.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 7700abd3ffb..0e5b9cd6f26 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -807,7 +807,11 @@ Regular_triangulation // cs.reserve(64); std::back_insert_iterator out(cs); Facet ft = compute_conflict_zone(p, s, out); - return insert_in_hole(p, cs.begin(), cs.end(), ft); + // The conflict zone is empty if the point is hidden + if (!cs.empty()) + return insert_in_hole(p, cs.begin(), cs.end(), ft); + else + return Vertex_handle(); } template< typename RTTraits, typename TDS > @@ -982,7 +986,12 @@ Regular_triangulation Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); Conflict_traversal_pred_in_fullspace tp(*this, c); - return tds().gather_full_cells(s, tp, out); + // If p is not in conflict with s, then p is hidden + // => we don't insert it (CJTODO: handle hidden points) + if (!c(s)) + return Facet(); + else + return tds().gather_full_cells(s, tp, out); } } From 4024f61c814ac968f177f52bd897a893af9245ca Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 17:33:02 +0200 Subject: [PATCH 007/269] Commented out some debug code --- .../include/CGAL/Tangential_complex.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 13f89f437a1..7534d643289 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -155,6 +155,10 @@ public: center_vertex = local_tr.insert(wp); center_vertex->data() = i; std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; + + /*std::cerr << 0 << " " + << 0 << " " + << CGAL::sqrt(max_squared_weight) << std::endl;*/ // Insert the other points std::vector::const_iterator it_wp = projected_points.begin(); @@ -173,16 +177,19 @@ public: /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ - // CJTODO TEMP - if (squared_dist_to_tangent_plane < 9) + // CJTODO TEMP: remove this if (but not the content!) + //if (squared_dist_to_tangent_plane < 9) { Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); if (vh != Tr_vertex_handle()) { - std::cerr << "Inserted point of weight " << w + /*std::cerr << "Inserted point of weight " << w << "\t(dist to tangent plane = " << CGAL::sqrt(squared_dist_to_tangent_plane) - << ")" << std::endl; + << ")" << std::endl;*/ + /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " + << traits.point_drop_weight_d_object()(*it_wp)[1] << " " + << w << std::endl;*/ vh->data() = j; } } @@ -193,10 +200,10 @@ public: // CJTODO std::cerr << "\nChecking topology and geometry..." << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); - std::stringstream sstr; + /*std::stringstream sstr; sstr << "data/local_tri_" << i << ".off"; std::ofstream off_stream_tr(sstr.str()); - CGAL::export_triangulation_to_off(off_stream_tr, local_tr); + CGAL::export_triangulation_to_off(off_stream_tr, local_tr);*/ } } From 41c4a174247ee94c4bb824dd5ed6d3b3e19773c9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 18:57:57 +0200 Subject: [PATCH 008/269] Fix the way we use the kernel and the traits --- .../include/CGAL/Tangential_complex.h | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7534d643289..234d2f99c89 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -64,7 +64,6 @@ class Tangential_complex typedef typename Kernel::Vector_d Vector; typedef Tr Triangulation; - typedef typename Triangulation::Geom_traits Tr_traits; typedef typename Triangulation::Point Tr_point; typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; @@ -89,20 +88,20 @@ class Tangential_complex public: /// Constructor - Tangential_complex() {} + Tangential_complex(const Kernel &k = Kernel()) + : m_k(k){} /// Constructor for a range of points template - Tangential_complex(InputIterator first, InputIterator last) - : m_points(first, last) {} + Tangential_complex(InputIterator first, InputIterator last, + const Kernel &k = Kernel()) + : m_k(k), m_points(first, last) {} /// Destructor ~Tangential_complex() {} void compute_tangential_complex() { - Tr_traits traits; // CJTODO: use the Triangulation's traits instance - // We need to do that because we don't want the container to copy the // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations @@ -118,6 +117,7 @@ public: Triangulation(Intrinsic_dimension), Tr_vertex_handle())); Triangulation &local_tr = m_triangulations.back().first; + const Geom_traits &local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations.back().second; // Estimate the tangent space @@ -140,7 +140,7 @@ public: { Tr_point wp = project_point(*it2_p, *it_p, m_tangent_spaces.back()); projected_points.push_back(wp); - FT w = traits.point_weight_d_object()(wp); + FT w = local_tr_traits.point_weight_d_object()(wp); if (w > max_squared_weight) max_squared_weight = w; } @@ -149,8 +149,8 @@ public: // Now we can insert the points // Insert p - Tr_point wp = traits.construct_weighted_point_d_object()( - traits.construct_point_d_object()(0, 0), + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(0, 0), CGAL::sqrt(max_squared_weight)); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -169,10 +169,10 @@ public: if (j != i) { FT squared_dist_to_tangent_plane = - traits.point_weight_d_object()(*it_wp); + local_tr_traits.point_weight_d_object()(*it_wp); FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); - Tr_point wp = traits.construct_weighted_point_d_object()( - traits.point_drop_weight_d_object()(*it_wp), + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.point_drop_weight_d_object()(*it_wp), w); /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ @@ -292,9 +292,8 @@ private: //Vector t2(0, 1, 0); // Normalize t1 and t2 - Kernel k; - Get_functor::type sqlen(k); - //Get_functor::type scale(k); + Get_functor::type sqlen(m_k); + //Get_functor::type scale(m_k); //ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); //ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); @@ -316,9 +315,8 @@ private: Tr_point project_point(const Point &p, const Point &origin, const Tangent_space_base &ts) const { - Kernel k; - Get_functor::type inner_pdct(k); - Get_functor::type diff_points(k); + Get_functor::type inner_pdct(m_k); + Get_functor::type diff_points(m_k); std::vector coords; // Ambiant-space coords of the projected point @@ -326,7 +324,7 @@ private: coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { - //coords[i] = Kernel().point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that + //coords[i] = m_k.point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that // Compute the inner product p * ts[i] Vector v = diff_points(p, origin); FT coord = inner_pdct(v, ts[i]); @@ -341,10 +339,11 @@ private: p_proj.begin(), p_proj.end()); return Tr_point( Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), - k.squared_distance_d_object()(p, projected_pt)); + m_k.squared_distance_d_object()(p, projected_pt)); } private: + const Kernel m_k; Point_container m_points; TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations From 7ca16e3aeae15d801fb856cf5a5d35c9820c1d1f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Sep 2014 19:24:29 +0200 Subject: [PATCH 009/269] Clean-up --- Tangential_complex/include/CGAL/Tangential_complex.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 234d2f99c89..a910a3aa933 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -177,9 +177,6 @@ public: /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ - // CJTODO TEMP: remove this if (but not the content!) - //if (squared_dist_to_tangent_plane < 9) - { Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); if (vh != Tr_vertex_handle()) { @@ -192,7 +189,6 @@ public: << w << std::endl;*/ vh->data() = j; } - } ++it_wp; } } From ce2ee270a0c64e6f13b73fe07bdce82a5d3a566a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 07:14:17 +0200 Subject: [PATCH 010/269] Code and comments clean-up --- .../include/CGAL/Tangential_complex.h | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index a910a3aa933..3acc9a1e857 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -180,10 +180,6 @@ public: Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); if (vh != Tr_vertex_handle()) { - /*std::cerr << "Inserted point of weight " << w - << "\t(dist to tangent plane = " - << CGAL::sqrt(squared_dist_to_tangent_plane) - << ")" << std::endl;*/ /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " << traits.point_drop_weight_d_object()(*it_wp)[1] << " " << w << std::endl;*/ @@ -193,13 +189,14 @@ public: } } - // CJTODO + // CJTODO DEBUG std::cerr << "\nChecking topology and geometry..." << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); - /*std::stringstream sstr; - sstr << "data/local_tri_" << i << ".off"; - std::ofstream off_stream_tr(sstr.str()); - CGAL::export_triangulation_to_off(off_stream_tr, local_tr);*/ + // DEBUG: output the local mesh into an OFF file + //std::stringstream sstr; + //sstr << "data/local_tri_" << i << ".off"; + //std::ofstream off_stream_tr(sstr.str()); + //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } } @@ -289,10 +286,13 @@ private: // Normalize t1 and t2 Get_functor::type sqlen(m_k); + + // CJTODO: use this when Scaled_vector is fixed //Get_functor::type scale(m_k); //ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); //ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); + // ****** Temporary code ******* FT t1_len = CGAL::sqrt(sqlen(t1)); FT t2_len = CGAL::sqrt(sqlen(t2)); for (int i = 0 ; i < Ambient_dimension::value ; ++i) @@ -302,6 +302,7 @@ private: } ts.push_back(t1); ts.push_back(t2); + // ****** /Temporary code ******* return ts; } @@ -320,7 +321,6 @@ private: coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { - //coords[i] = m_k.point_to_vector_d_object()(p) * ts[i]; // CJTODO: use that // Compute the inner product p * ts[i] Vector v = diff_points(p, origin); FT coord = inner_pdct(v, ts[i]); From b23f01ebf5f21d20f152ec41894a4a0f87ec73f7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 09:32:46 +0200 Subject: [PATCH 011/269] Oops: I removed a line that is still needed --- Tangential_complex/include/CGAL/Tangential_complex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3acc9a1e857..072482c53d2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -64,6 +64,7 @@ class Tangential_complex typedef typename Kernel::Vector_d Vector; typedef Tr Triangulation; + typedef typename Triangulation::Geom_traits Tr_traits; typedef typename Triangulation::Point Tr_point; typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; @@ -117,7 +118,7 @@ public: Triangulation(Intrinsic_dimension), Tr_vertex_handle())); Triangulation &local_tr = m_triangulations.back().first; - const Geom_traits &local_tr_traits = local_tr.geom_traits(); + const Tr_traits &local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations.back().second; // Estimate the tangent space From a8fce8b2fc0373ae33b825a4f8fde7ec7c19f27f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 12:43:47 +0200 Subject: [PATCH 012/269] Disable randomization + debugging code --- Tangential_complex/include/CGAL/Tangential_complex.h | 7 ++++--- .../test/Tangential_complex/test_tangential_complex.cpp | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 072482c53d2..432fda780b0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -148,14 +148,14 @@ public: } // Now we can insert the points - + // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(0, 0), CGAL::sqrt(max_squared_weight)); center_vertex = local_tr.insert(wp); center_vertex->data() = i; - std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; + //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; /*std::cerr << 0 << " " << 0 << " " @@ -179,6 +179,7 @@ public: Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); + //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) { /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " @@ -189,7 +190,7 @@ public: ++it_wp; } } - + // CJTODO DEBUG std::cerr << "\nChecking topology and geometry..." << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index d115652f41e..edc95702711 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -15,6 +15,7 @@ int main() #else const int NUM_POINTS = 500; #endif + CGAL::default_random = CGAL::Random(0); // NO RANDOM CGAL::Random_points_on_sphere_3 generator(3.0); std::vector points; points.reserve(NUM_POINTS); From a7082cd595c0a5e6b64aaed3c728ee46182ef7b3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Sep 2014 17:15:12 +0200 Subject: [PATCH 013/269] Parallel version --- .../include/CGAL/Tangential_complex.h | 264 +++++++++++------- .../test/Tangential_complex/CMakeLists.txt | 9 + .../test_tangential_complex.cpp | 23 +- 3 files changed, 186 insertions(+), 110 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 432fda780b0..ce7d5615f16 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,6 +23,7 @@ #define TANGENTIAL_COMPLEX_H #include +#include #include #include @@ -35,12 +36,17 @@ #include #include +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif + namespace CGAL { /// The class Tangential_complex represents a tangential complex template < typename Kernel, int Intrinsic_dimension, + typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Regular_triangulation < Regular_triangulation_euclidean_traits< @@ -59,23 +65,23 @@ template < > class Tangential_complex { - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Vector_d Vector; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; - typedef Tr Triangulation; - typedef typename Triangulation::Geom_traits Tr_traits; - typedef typename Triangulation::Point Tr_point; - typedef typename Triangulation::Bare_point Tr_bare_point; - typedef typename Triangulation::Vertex_handle Tr_vertex_handle; - typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; + typedef Tr Triangulation; + typedef typename Triangulation::Geom_traits Tr_traits; + typedef typename Triangulation::Point Tr_point; + typedef typename Triangulation::Bare_point Tr_bare_point; + typedef typename Triangulation::Vertex_handle Tr_vertex_handle; + typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; - typedef typename std::vector Tangent_space_base; + typedef typename std::vector Tangent_space_base; - typedef std::pair Tr_and_VH; - typedef typename std::vector Point_container; - typedef typename std::vector Tr_container; - typedef typename std::vector TS_container; + typedef std::pair Tr_and_VH; + typedef typename std::vector Point_container; + typedef typename std::vector Tr_container; + typedef typename std::vector TS_container; // Stores the index of the original Point in the ambient space /*struct Tr_point_with_index @@ -106,99 +112,26 @@ public: // We need to do that because we don't want the container to copy the // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations - m_triangulations.reserve(m_points.size()); - m_tangent_spaces.reserve(m_points.size()); - - Point_container::const_iterator it_p = m_points.begin(); - Point_container::const_iterator it_p_end = m_points.end(); - // For each point p in ambient space - for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) + m_triangulations.resize( + m_points.size(), + std::make_pair((Triangulation*)NULL, Tr_vertex_handle())); + m_tangent_spaces.resize(m_points.size()); + +#ifdef CGAL_LINKED_WITH_TBB + // Parallel + if (boost::is_convertible::value) { - m_triangulations.push_back(std::make_pair( - Triangulation(Intrinsic_dimension), - Tr_vertex_handle())); - Triangulation &local_tr = m_triangulations.back().first; - const Tr_traits &local_tr_traits = local_tr.geom_traits(); - Tr_vertex_handle ¢er_vertex = m_triangulations.back().second; - - // Estimate the tangent space - m_tangent_spaces.push_back(compute_tangent_space(*it_p)); - - //*************************************************** - // Build a minimal triangulation in the tangent space - // (we only need the star of p) - //*************************************************** - - // First, compute the projected points - std::vector projected_points; - FT max_squared_weight = 0; - projected_points.reserve(m_points.size() - 1); - Point_container::const_iterator it2_p = m_points.begin(); - for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) - { - // ith point = p, which is already inserted - if (j != i) - { - Tr_point wp = project_point(*it2_p, *it_p, m_tangent_spaces.back()); - projected_points.push_back(wp); - FT w = local_tr_traits.point_weight_d_object()(wp); - if (w > max_squared_weight) - max_squared_weight = w; - } - } - - // Now we can insert the points - - // Insert p - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(0, 0), - CGAL::sqrt(max_squared_weight)); - center_vertex = local_tr.insert(wp); - center_vertex->data() = i; - //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; - - /*std::cerr << 0 << " " - << 0 << " " - << CGAL::sqrt(max_squared_weight) << std::endl;*/ - - // Insert the other points - std::vector::const_iterator it_wp = projected_points.begin(); - it2_p = m_points.begin(); - for (std::size_t j = 0 ; it2_p != it_p_end ; ++it2_p, ++j) - { - // ith point = p, which is already inserted - if (j != i) - { - FT squared_dist_to_tangent_plane = - local_tr_traits.point_weight_d_object()(*it_wp); - FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.point_drop_weight_d_object()(*it_wp), - w); - /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); - Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ - - Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); - //Tr_vertex_handle vh = local_tr.insert(wp); - if (vh != Tr_vertex_handle()) - { - /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " - << traits.point_drop_weight_d_object()(*it_wp)[1] << " " - << w << std::endl;*/ - vh->data() = j; - } - ++it_wp; - } - } - - // CJTODO DEBUG - std::cerr << "\nChecking topology and geometry..." - << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); - // DEBUG: output the local mesh into an OFF file - //std::stringstream sstr; - //sstr << "data/local_tri_" << i << ".off"; - //std::ofstream off_stream_tr(sstr.str()); - //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); + // Apply moves in triangulation + tbb::parallel_for(tbb::blocked_range(0, m_points.size()), + Compute_tangent_triangulation(*this) + ); + } + // Sequential + else +#endif // CGAL_LINKED_WITH_TBB + { + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + compute_tangent_triangulation(i); } } @@ -244,7 +177,7 @@ public: // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { - const Triangulation &tr = it_tr->first; + const Triangulation &tr = *it_tr->first; Tr_vertex_handle center_vh = it_tr->second; std::vector incident_cells; @@ -273,6 +206,123 @@ public: } private: + +#ifdef CGAL_LINKED_WITH_TBB + // Functor for compute_tangential_complex function + class Compute_tangent_triangulation + { + Tangential_complex & m_tc; + + public: + // Constructor + Compute_tangent_triangulation(Tangential_complex &tc) + : m_tc(tc) + {} + + // Constructor + Compute_tangent_triangulation(const Compute_tangent_triangulation &ctt) + : m_tc(ctt.m_tc) + {} + + // operator() + void operator()( const tbb::blocked_range& r ) const + { + for( size_t i = r.begin() ; i != r.end() ; ++i) + m_tc.compute_tangent_triangulation(i); + } + }; +#endif // CGAL_LINKED_WITH_TBB + + void compute_tangent_triangulation(std::size_t i) + { + Triangulation *p_local_tr = + m_triangulations[i].first = + new Triangulation(Intrinsic_dimension); + const Tr_traits &local_tr_traits = p_local_tr->geom_traits(); + Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; + + // Estimate the tangent space + const Point ¢er_pt = m_points[i]; + m_tangent_spaces[i] = compute_tangent_space(center_pt); + + //*************************************************** + // Build a minimal triangulation in the tangent space + // (we only need the star of p) + //*************************************************** + + // First, compute the projected points + std::vector projected_points; + FT max_squared_weight = 0; + projected_points.reserve(m_points.size() - 1); + Point_container::const_iterator it_p = m_points.begin(); + Point_container::const_iterator it_p_end = m_points.end(); + for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) + { + // ith point = p, which is already inserted + if (j != i) + { + Tr_point wp = project_point(*it_p, center_pt, m_tangent_spaces[i]); + projected_points.push_back(wp); + FT w = local_tr_traits.point_weight_d_object()(wp); + if (w > max_squared_weight) + max_squared_weight = w; + } + } + + // Now we can insert the points + + // Insert p + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(0, 0), + CGAL::sqrt(max_squared_weight)); + center_vertex = p_local_tr->insert(wp); + center_vertex->data() = i; + //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; + + /*std::cerr << 0 << " " + << 0 << " " + << CGAL::sqrt(max_squared_weight) << std::endl;*/ + + // Insert the other points + std::vector::const_iterator it_wp = projected_points.begin(); + it_p = m_points.begin(); + for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) + { + // ith point = p, which is already inserted + if (j != i) + { + FT squared_dist_to_tangent_plane = + local_tr_traits.point_weight_d_object()(*it_wp); + FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.point_drop_weight_d_object()(*it_wp), + w); + /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); + Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ + + Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); + //Tr_vertex_handle vh = p_local_tr->insert(wp); + if (vh != Tr_vertex_handle()) + { + /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " + << traits.point_drop_weight_d_object()(*it_wp)[1] << " " + << w << std::endl;*/ + vh->data() = j; + } + ++it_wp; + } + } + + // CJTODO DEBUG + //std::cerr << "\nChecking topology and geometry..." + // << (p_local_tr->is_valid(true) ? "OK.\n" : "Error.\n"); + // DEBUG: output the local mesh into an OFF file + //std::stringstream sstr; + //sstr << "data/local_tri_" << i << ".off"; + //std::ofstream off_stream_tr(sstr.str()); + //CGAL::export_triangulation_to_off(off_stream_tr, *p_local_tr); + } + Tangent_space_base compute_tangent_space(const Point &p) const { Tangent_space_base ts; diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt index 7ba896e34c7..8d58f3631fe 100644 --- a/Tangential_complex/test/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -17,6 +17,15 @@ 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) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index edc95702711..2fd7fe8a1c1 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -1,19 +1,33 @@ +// 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 #include #include #include +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif + int main() { typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; + +#ifdef CGAL_LINKED_WITH_TBB + tbb::task_scheduler_init init(10); +#endif #ifdef _DEBUG const int NUM_POINTS = 50; #else - const int NUM_POINTS = 500; + const int NUM_POINTS = 5000; #endif CGAL::default_random = CGAL::Random(0); // NO RANDOM CGAL::Random_points_on_sphere_3 generator(3.0); @@ -25,8 +39,11 @@ int main() //points.push_back(Point((double)(rand()%10000)/5000, (double)(rand()%10000)/5000, 0.)); // CJTODO : plane } - CGAL::Tangential_complex tc( - points.begin(), points.end()); + CGAL::Tangential_complex< + Kernel, + INTRINSIC_DIMENSION, + CGAL::Parallel_tag> tc(points.begin(), points.end()); + tc.compute_tangential_complex(); std::stringstream output_filename; From a2e172c57eb9e2ef76164df111f34da3be42b9fd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 8 Sep 2014 06:47:17 +0200 Subject: [PATCH 014/269] Add a TODO --- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 9d54641ea32..4398424d330 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -1029,7 +1029,7 @@ Regular_triangulation } else { - Orientation_d ori = geom_traits().orientation_d_object(); + Orientation_d ori = geom_traits().orientation_d_object(); // CJTODO: create member variables for this? Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); return c(s); From 7b807794c9e72060686b860ac2f0d81d9b917c91 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 9 Sep 2014 10:24:46 +0200 Subject: [PATCH 015/269] Renamed "base" => "basis" --- Tangential_complex/include/CGAL/Tangential_complex.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ce7d5615f16..146f6990f17 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -76,12 +76,12 @@ class Tangential_complex typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; - typedef typename std::vector Tangent_space_base; + typedef typename std::vector Tangent_space_basis; typedef std::pair Tr_and_VH; typedef typename std::vector Point_container; typedef typename std::vector Tr_container; - typedef typename std::vector TS_container; + typedef typename std::vector TS_container; // Stores the index of the original Point in the ambient space /*struct Tr_point_with_index @@ -323,9 +323,9 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, *p_local_tr); } - Tangent_space_base compute_tangent_space(const Point &p) const + Tangent_space_basis compute_tangent_space(const Point &p) const { - Tangent_space_base ts; + Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); // CJTODO: this is only for a sphere in R^3 Vector t1(-p[1] - p[2], p[0], p[0]); @@ -362,7 +362,7 @@ private: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p Tr_point project_point(const Point &p, const Point &origin, - const Tangent_space_base &ts) const + const Tangent_space_basis &ts) const { Get_functor::type inner_pdct(m_k); Get_functor::type diff_points(m_k); From 2e80d4aa471e33d79ad4e2be521c624321adabcf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 9 Sep 2014 15:54:37 +0200 Subject: [PATCH 016/269] Add Gram-Schmidt algorithm + profiling + config file + simpler code thanks to new kernel features --- .../include/CGAL/Tangential_complex.h | 73 ++++++++++++------ .../include/CGAL/Tangential_complex/config.h | 28 +++++++ .../CGAL/Tangential_complex/utilities.h | 76 +++++++++++++++++++ 3 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/config.h create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/utilities.h diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 146f6990f17..667035a8940 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -22,12 +22,17 @@ #ifndef TANGENTIAL_COMPLEX_H #define TANGENTIAL_COMPLEX_H +#include + #include #include #include #include #include +#include + +#include #include // CJTODO TEMP @@ -41,6 +46,8 @@ #endif namespace CGAL { + +using namespace Tangential_complex_; /// The class Tangential_complex represents a tangential complex template < @@ -109,6 +116,10 @@ public: void compute_tangential_complex() { +#ifdef CGAL_TC_PROFILING + WallClockTimer t; +#endif + // We need to do that because we don't want the container to copy the // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations @@ -133,6 +144,11 @@ public: for (std::size_t i = 0 ; i < m_points.size() ; ++i) compute_tangent_triangulation(i); } + +#ifdef CGAL_TC_PROFILING + std::cerr << "Tangential complex computed in " << t.elapsed() + << " seconds." << std::endl; +#endif } std::ostream &export_to_off(std::ostream & os) @@ -291,6 +307,15 @@ private: // ith point = p, which is already inserted if (j != i) { + // CJTODO TEMP: for test only + /*if (local_tr_traits.squared_distance_d_object()( + local_tr_traits.point_drop_weight_d_object()(wp), + local_tr_traits.point_drop_weight_d_object()(*it_wp)) > 1) + { + ++it_wp; + continue; + }*/ + FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(*it_wp); FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); @@ -325,38 +350,40 @@ private: Tangent_space_basis compute_tangent_space(const Point &p) const { - Tangent_space_basis ts; - ts.reserve(Intrinsic_dimension); + + Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + //Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); + //Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); + Get_functor::type inner_pdct(m_k); // CJTODO TEMP + Get_functor::type diff_vec(m_k); + // CJTODO: this is only for a sphere in R^3 Vector t1(-p[1] - p[2], p[0], p[0]); Vector t2(p[1] * t1[2] - p[2] * t1[1], p[2] * t1[0] - p[0] * t1[2], p[0] * t1[1] - p[1] * t1[0]); - // CJTODO: this is for a plane (test) - //Vector t1(1, 0, 0); - //Vector t2(0, 1, 0); - + // Normalize t1 and t2 - Get_functor::type sqlen(m_k); + Get_functor::type scale(m_k); - // CJTODO: use this when Scaled_vector is fixed - //Get_functor::type scale(m_k); - //ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); - //ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); - - // ****** Temporary code ******* - FT t1_len = CGAL::sqrt(sqlen(t1)); - FT t2_len = CGAL::sqrt(sqlen(t2)); - for (int i = 0 ; i < Ambient_dimension::value ; ++i) - { - t1[i] /= t1_len; - t2[i] /= t2_len; - } - ts.push_back(t1); - ts.push_back(t2); - // ****** /Temporary code ******* + Tangent_space_basis ts; + ts.reserve(Intrinsic_dimension); + ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); + ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); return ts; + + // Alternative code (to be used later) + //Vector n = m_k.point_to_vector_d_object()(p); + //n = scaled_vec(n, 1./sqrt(sqlen(n))); + //Vector t1(12., 15., 65.); + //Vector t2(32., 5., 85.); + //Tangent_space_basis ts; + //ts.reserve(Intrinsic_dimension); + //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); + //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); + //return compute_gram_schmidt_basis(ts, m_k); } // Project the point in the tangent space diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h new file mode 100644 index 00000000000..1527b4ea3c8 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -0,0 +1,28 @@ +// 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 + +#define CGAL_TC_PROFILING + +#endif // CGAL_TC_CONFIG_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h new file mode 100644 index 00000000000..2ce238cc8c1 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -0,0 +1,76 @@ +// 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 +#include + +#include + +namespace CGAL { + +namespace Tangential_complex_ { + + template + std::vector + compute_gram_schmidt_basis( + std::vector const& input_basis, + K const& kernel) + { + typedef typename K::Vector_d Vector; + typedef std::vector Basis; + const int D = Ambient_dimension::value; + + // Kernel functors + K::Squared_length_d sqlen = kernel.squared_length_d_object(); + K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); + //K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); + //K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); + Get_functor::type inner_pdct(kernel); // CJTODO TEMP + Get_functor::type diff_vec(kernel); + + Basis output_basis; + + Basis::const_iterator inb_it = input_basis.begin(); + Basis::const_iterator inb_it_end = input_basis.end(); + for (int i = 0 ; inb_it != inb_it_end ; ++inb_it, ++i) + { + Vector u = *inb_it; + + Basis::iterator outb_it = output_basis.begin(); + for (int j = 0 ; j < i ; ++j) + { + Vector const& ej = *outb_it; + Vector u_proj = scaled_vec(ej, inner_pdct(u, ej)); + u = diff_vec(u, u_proj); + } + + output_basis.push_back(scaled_vec(u, 1./CGAL::sqrt(sqlen(u)))); + } + + return output_basis; + } + +}; // namespace Tangential_complex_ +} //namespace CGAL + +#endif // CGAL_TC_UTILITIES_H From 47a262697e9bc72d4683270b19e02081ef35fffb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 14:07:35 +0200 Subject: [PATCH 017/269] Eigen-based PCA to estimate tangent plane --- .../include/CGAL/Tangential_complex.h | 65 ++++++++++++++++++- .../include/CGAL/Tangential_complex/config.h | 2 + 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 667035a8940..f2f6735afd7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -36,6 +36,9 @@ #include // CJTODO TEMP +#include +#include + #include #include #include @@ -223,6 +226,23 @@ public: private: + class Compare_distance_to_ref_point + { + public: + Compare_distance_to_ref_point(Point const& ref, Kernel const& k) + : m_ref(ref), m_k(k) {} + + bool operator()(Point const& p1, Point const& p2) + { + Kernel::Squared_distance_d sqdist = m_k.squared_distance_d_object(); + return sqdist(p1, m_ref) < sqdist(p2, m_ref); + } + + private: + Point const& m_ref; + Kernel const& m_k; + }; + #ifdef CGAL_LINKED_WITH_TBB // Functor for compute_tangential_complex function class Compute_tangent_triangulation @@ -350,7 +370,8 @@ private: Tangent_space_basis compute_tangent_space(const Point &p) const { - + // Kernel functors + Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); //Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); @@ -358,6 +379,47 @@ private: Get_functor::type inner_pdct(m_k); // CJTODO TEMP Get_functor::type diff_vec(m_k); + // CJTODO: do better than that (ANN?) + typedef std::set Sorted_points; + Sorted_points sorted_points( + Compare_distance_to_ref_point(p, m_k)); + sorted_points.insert(m_points.begin(), m_points.end()); + + //******************************* PCA ************************************* + + const int amb_dim = Ambient_dimension::value; + Eigen::MatrixXd mat(NUM_POINTS_FOR_PCA, amb_dim); + int j = 0; + for (Sorted_points::const_iterator it = sorted_points.begin() ; + j < NUM_POINTS_FOR_PCA ; ++it, ++j) + { + for (int i = 0 ; i < amb_dim ; ++i) + mat(j, i) = (*it)[i]; + } + Eigen::MatrixXd centered = mat.rowwise() - mat.colwise().mean(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver eig(cov); + + // The eigenvectors are sorted in increasing order of their corresponding + // eigenvalues + Tangent_space_basis ts; + for (int i = amb_dim - 1 ; i >= amb_dim - Intrinsic_dimension ; --i) + { + ts.push_back(constr_vec( + amb_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + amb_dim)); + } + + //************************************************************************* + + //Vector n = m_k.point_to_vector_d_object()(p); + //n = scaled_vec(n, 1./sqrt(sqlen(n))); + //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; + + return compute_gram_schmidt_basis(ts, m_k); + + /* // CJTODO: this is only for a sphere in R^3 Vector t1(-p[1] - p[2], p[0], p[0]); Vector t2(p[1] * t1[2] - p[2] * t1[1], @@ -384,6 +446,7 @@ private: //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); //return compute_gram_schmidt_basis(ts, m_k); + */ } // Project the point in the tangent space diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 1527b4ea3c8..a05abf81622 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -25,4 +25,6 @@ #define CGAL_TC_PROFILING +const std::size_t NUM_POINTS_FOR_PCA = 30; + #endif // CGAL_TC_CONFIG_H From d37b81a25e66f6680bbc374e0fd645f46d8e33c8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 14:29:34 +0200 Subject: [PATCH 018/269] Comments clean-up --- .../include/CGAL/Tangential_complex.h | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f2f6735afd7..7572d4b19d8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -315,10 +315,6 @@ private: center_vertex->data() = i; //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; - /*std::cerr << 0 << " " - << 0 << " " - << CGAL::sqrt(max_squared_weight) << std::endl;*/ - // Insert the other points std::vector::const_iterator it_wp = projected_points.begin(); it_p = m_points.begin(); @@ -342,16 +338,11 @@ private: Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.point_drop_weight_d_object()(*it_wp), w); - /*Tr_bare_point bp = traits.point_drop_weight_d_object()(*it_wp); - Tr_point wp(traits.point_drop_weight_d_object()(*it_wp), w);*/ Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); //Tr_vertex_handle vh = p_local_tr->insert(wp); if (vh != Tr_vertex_handle()) { - /*std::cerr << traits.point_drop_weight_d_object()(*it_wp)[0] << " " - << traits.point_drop_weight_d_object()(*it_wp)[1] << " " - << w << std::endl;*/ vh->data() = j; } ++it_wp; @@ -388,15 +379,16 @@ private: //******************************* PCA ************************************* const int amb_dim = Ambient_dimension::value; - Eigen::MatrixXd mat(NUM_POINTS_FOR_PCA, amb_dim); + // One row = one point + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); int j = 0; for (Sorted_points::const_iterator it = sorted_points.begin() ; j < NUM_POINTS_FOR_PCA ; ++it, ++j) { for (int i = 0 ; i < amb_dim ; ++i) - mat(j, i) = (*it)[i]; + mat_points(j, i) = (*it)[i]; } - Eigen::MatrixXd centered = mat.rowwise() - mat.colwise().mean(); + Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; Eigen::SelfAdjointEigenSolver eig(cov); From 4015d0e1700e38fa0f779c6fccac69f6306f2301 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:00:09 +0200 Subject: [PATCH 019/269] Optimization to reduce the number of vertices we insert in the local triang While building the local triangulation, we keep the radius of the sphere centered at "center_vertex" and which contains all the circumspheres of the star of "center_vertex" For now, we use non-weighted circumspheres but it could be optimized by using weighted circumspheres (which are smaller) --- .../include/CGAL/Tangential_complex.h | 83 ++++++++++++++++++- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7572d4b19d8..f7324d2fb22 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -39,10 +39,13 @@ #include #include +#include + #include #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB # include @@ -243,6 +246,26 @@ private: Kernel const& m_k; }; + + struct Tr_vertex_to_bare_point + { + typedef typename Tr_vertex_handle argument_type; + typedef typename Tr_bare_point result_type; + + Tr_vertex_to_bare_point(Tr_traits const& traits) + : m_traits(traits) {} + + result_type operator()(argument_type const& vh) const + { + typename Tr_traits::Point_drop_weight_d pdw = + m_traits.point_drop_weight_d_object(); + return pdw(vh->point()); + } + + private: + Tr_traits const& m_traits; + }; + #ifdef CGAL_LINKED_WITH_TBB // Functor for compute_tangential_complex function class Compute_tangent_triangulation @@ -271,12 +294,21 @@ private: void compute_tangent_triangulation(std::size_t i) { + //std::cerr << "***********************************************" << std::endl; Triangulation *p_local_tr = m_triangulations[i].first = new Triangulation(Intrinsic_dimension); const Tr_traits &local_tr_traits = p_local_tr->geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; + // Traits functor & objects + Tr_traits::Center_of_sphere_d center_of_sphere = + local_tr_traits.center_of_sphere_d_object(); + Tr_traits::Squared_distance_d sqdist = + local_tr_traits.squared_distance_d_object(); + Tr_traits::Point_drop_weight_d drop_w = + local_tr_traits.point_drop_weight_d_object(); + // Estimate the tangent space const Point ¢er_pt = m_points[i]; m_tangent_spaces[i] = compute_tangent_space(center_pt); @@ -314,7 +346,13 @@ private: center_vertex = p_local_tr->insert(wp); center_vertex->data() = i; //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; - + + // While building the local triangulation, we keep the radius + // of the sphere centered at "center_vertex" and which contains all the + // circumspheres of the star of "center_vertex" + // For now, we use non-weighted circumspheres but it could be + // optimized by using weighted circumspheres (which are smaller) + FT star_sphere_squared_radius = std::numeric_limits::max(); // Insert the other points std::vector::const_iterator it_wp = projected_points.begin(); it_p = m_points.begin(); @@ -325,18 +363,25 @@ private: { // CJTODO TEMP: for test only /*if (local_tr_traits.squared_distance_d_object()( - local_tr_traits.point_drop_weight_d_object()(wp), - local_tr_traits.point_drop_weight_d_object()(*it_wp)) > 1) + drop_w(wp), + drop_w(*it_wp)) > 1) { ++it_wp; continue; }*/ + if (local_tr_traits.squared_distance_d_object()( + drop_w(wp), drop_w(*it_wp)) + > star_sphere_squared_radius) + { + ++it_wp; + continue; + } FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(*it_wp); FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.point_drop_weight_d_object()(*it_wp), + drop_w(*it_wp), w); Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); @@ -344,7 +389,37 @@ private: if (vh != Tr_vertex_handle()) { vh->data() = j; + + // Let's recompute star_sphere_squared_radius + if (p_local_tr->current_dimension() >= Intrinsic_dimension) + { + star_sphere_squared_radius = 0.; + // Get the incident cells and look for the biggest circumsphere + std::vector incident_cells; + p_local_tr->incident_full_cells( + center_vertex, + std::back_inserter(incident_cells)); + for (auto cell : incident_cells) // CJTODO C++11 + { + if (p_local_tr->is_infinite(cell)) + { + star_sphere_squared_radius = std::numeric_limits::max(); + break; + } + else + { + Tr_vertex_to_bare_point v2p(local_tr_traits); + Tr_bare_point c = center_of_sphere( + boost::make_transform_iterator(cell->vertices_begin(), v2p), + boost::make_transform_iterator(cell->vertices_end(), v2p)); + FT sq_circumdiam = 4.*sqdist(c, drop_w(center_vertex->point())); + if (sq_circumdiam > star_sphere_squared_radius) + star_sphere_squared_radius = sq_circumdiam; + } + } + } } + //std::cerr << star_sphere_squared_radius << std::endl; ++it_wp; } } From 38dc351ad3b567e71af252d8f547c77aa9a0680b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:07:32 +0200 Subject: [PATCH 020/269] Minor changes to the test (number of threads, random points...) --- .../test/Tangential_complex/test_tangential_complex.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 2fd7fe8a1c1..367a4b7b4e4 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -21,7 +21,11 @@ int main() const int INTRINSIC_DIMENSION = 2; #ifdef CGAL_LINKED_WITH_TBB +# ifdef _DEBUG + tbb::task_scheduler_init init(1); +# else tbb::task_scheduler_init init(10); +# endif #endif #ifdef _DEBUG @@ -29,7 +33,7 @@ int main() #else const int NUM_POINTS = 5000; #endif - CGAL::default_random = CGAL::Random(0); // NO RANDOM + //CGAL::default_random = CGAL::Random(0); // NO RANDOM CGAL::Random_points_on_sphere_3 generator(3.0); std::vector points; points.reserve(NUM_POINTS); From 9e4e2d255b27f065cd420e9ce4fca4b2a337ec1d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:17:31 +0200 Subject: [PATCH 021/269] Remove some "Get_functor" --- Tangential_complex/include/CGAL/Tangential_complex.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f7324d2fb22..7c7df9495d1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -440,10 +440,8 @@ private: Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - //Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - //Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - Get_functor::type inner_pdct(m_k); // CJTODO TEMP - Get_functor::type diff_vec(m_k); + Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); + Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); // CJTODO: do better than that (ANN?) typedef std::set Sorted_points; @@ -494,7 +492,7 @@ private: p[0] * t1[1] - p[1] * t1[0]); // Normalize t1 and t2 - Get_functor::type scale(m_k); + Kernel::Scaled_vector_d scale = m_k.scaled_vector_d_object(); Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); @@ -521,7 +519,8 @@ private: Tr_point project_point(const Point &p, const Point &origin, const Tangent_space_basis &ts) const { - Get_functor::type inner_pdct(m_k); + Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); + //Kernel::Difference_of_points_d diff_points= m_k.difference_of_points_d_object(); // CJTODO: use that Get_functor::type diff_points(m_k); std::vector coords; From 0138db9500d4325bf2f39581fdccf7889ab0e023 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:40:08 +0200 Subject: [PATCH 022/269] Restructure the test --- .../test_tangential_complex.cpp | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 367a4b7b4e4..d81a5c0af10 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -14,12 +14,31 @@ # include #endif +#ifdef _DEBUG + const int NUM_POINTS = 50; +#else + const int NUM_POINTS = 5000; +#endif + +template +std::vector generate_points_on_sphere(double radius) +{ + CGAL::Random_points_on_sphere_3 generator(radius); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + points.push_back(*generator++); + return points; +} + int main() { typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; - + + //CGAL::default_random = CGAL::Random(0); // NO RANDOM + #ifdef CGAL_LINKED_WITH_TBB # ifdef _DEBUG tbb::task_scheduler_init init(1); @@ -28,20 +47,7 @@ int main() # endif #endif -#ifdef _DEBUG - const int NUM_POINTS = 50; -#else - const int NUM_POINTS = 5000; -#endif - //CGAL::default_random = CGAL::Random(0); // NO RANDOM - CGAL::Random_points_on_sphere_3 generator(3.0); - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - { - points.push_back(*generator++); - //points.push_back(Point((double)(rand()%10000)/5000, (double)(rand()%10000)/5000, 0.)); // CJTODO : plane - } + std::vector points = generate_points_on_sphere(3.0); CGAL::Tangential_complex< Kernel, From 87c0716689e012e4319d33c53e823d72869c7629 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 16:40:32 +0200 Subject: [PATCH 023/269] Clean-up --- Tangential_complex/include/CGAL/Tangential_complex.h | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7c7df9495d1..91bda16a752 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -350,7 +350,7 @@ private: // While building the local triangulation, we keep the radius // of the sphere centered at "center_vertex" and which contains all the // circumspheres of the star of "center_vertex" - // For now, we use non-weighted circumspheres but it could be + // [TODO?] For now, we use non-weighted circumspheres but it could be // optimized by using weighted circumspheres (which are smaller) FT star_sphere_squared_radius = std::numeric_limits::max(); // Insert the other points @@ -361,14 +361,6 @@ private: // ith point = p, which is already inserted if (j != i) { - // CJTODO TEMP: for test only - /*if (local_tr_traits.squared_distance_d_object()( - drop_w(wp), - drop_w(*it_wp)) > 1) - { - ++it_wp; - continue; - }*/ if (local_tr_traits.squared_distance_d_object()( drop_w(wp), drop_w(*it_wp)) > star_sphere_squared_radius) @@ -522,7 +514,7 @@ private: Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); //Kernel::Difference_of_points_d diff_points= m_k.difference_of_points_d_object(); // CJTODO: use that Get_functor::type diff_points(m_k); - + std::vector coords; // Ambiant-space coords of the projected point std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); From 819c46a3d2fb5b830804859c9c9b3f908c736b52 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 17:14:29 +0200 Subject: [PATCH 024/269] Enable export_to_off when ambient dim > 3 (truncated points) --- .../include/CGAL/Tangential_complex.h | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 91bda16a752..f4caaddc5de 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -160,17 +160,31 @@ public: std::ostream &export_to_off(std::ostream & os) { const int ambient_dim = Ambient_dimension::value; - if (ambient_dim < 2 || ambient_dim > 3) + if (ambient_dim < 2) { - std::cerr << "Error: export_to_off => ambient dimension should be 2 or 3."; - os << "Error: export_to_off => ambient dimension should be 2 or 3."; + std::cerr << "Error: export_to_off => ambient dimension should be >= 2." + << std::endl; + os << "Error: export_to_off => ambient dimension should be >= 2." + << std::endl; return os; } + if (ambient_dim > 3) + { + std::cerr << "Warning: export_to_off => ambient dimension should be " + "<= 3. Only the first 3 coordinates will be exported." + << std::endl; + } + + int num_coords = min(ambient_dim, 3); if (Intrinsic_dimension < 1 || Intrinsic_dimension > 3) { - std::cerr << "Error: export_to_off => intrinsic dimension should be between 1 and 3."; - os << "Error: export_to_off => intrinsic dimension should be between 1 and 3."; + std::cerr << "Error: export_to_off => intrinsic dimension should be " + "between 1 and 3." + << std::endl; + os << "Error: export_to_off => intrinsic dimension should be " + "between 1 and 3." + << std::endl; return os; } @@ -184,7 +198,7 @@ public: for ( ; it_p != it_p_end ; ++it_p) { int i = 0; - for ( ; i < ambient_dim ; ++i) + for ( ; i < num_coords ; ++i) output << (*it_p)[i] << " "; if (i == 2) output << "0"; From 2f1c84e171a16985747e20a10cba20980e702eb9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 17:18:31 +0200 Subject: [PATCH 025/269] Let's give the Klein Bottle a try... --- .../test_tangential_complex.cpp | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index d81a5c0af10..e608e0159e7 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -7,8 +7,13 @@ #include #include #include +#include +#include #include +#include + +#include #ifdef CGAL_LINKED_WITH_TBB # include @@ -31,11 +36,36 @@ std::vector generate_points_on_sphere(double radius) return points; } +// a = big radius, b = small radius +template +std::vector generate_points_on_klein_bottle(double a, double b) +{ + typedef CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u = rng.get_double(0, 6.2832); + FT v = rng.get_double(0, 6.2832); + points.push_back(Kernel().construct_point_d_object()( + (a + b*cos(v))*cos(u), + (a + b*cos(v))*sin(u), + b*sin(v)*cos(u/2), + b*sin(v)*sin(u/2))); + } + return points; +} + int main() { - typedef CGAL::Epick_d > Kernel; - typedef Kernel::Point_d Point; const int INTRINSIC_DIMENSION = 2; + const int AMBIENT_DIMENSION = 4; + + typedef CGAL::Epick_d > Kernel; + typedef Kernel::Point_d Point; //CGAL::default_random = CGAL::Random(0); // NO RANDOM @@ -47,7 +77,8 @@ int main() # endif #endif - std::vector points = generate_points_on_sphere(3.0); + //std::vector points = generate_points_on_sphere(3.0); + std::vector points = generate_points_on_klein_bottle(4., 3.); CGAL::Tangential_complex< Kernel, From 43ad54314384ba61351865ed987819071fb04a9b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Sep 2014 17:30:27 +0200 Subject: [PATCH 026/269] Improve test --- .../test/Tangential_complex/test_tangential_complex.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index e608e0159e7..51f77c0814b 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -64,8 +64,8 @@ int main() const int INTRINSIC_DIMENSION = 2; const int AMBIENT_DIMENSION = 4; - typedef CGAL::Epick_d > Kernel; - typedef Kernel::Point_d Point; + typedef CGAL::Epick_d > Kernel; + typedef Kernel::Point_d Point; //CGAL::default_random = CGAL::Random(0); // NO RANDOM @@ -88,7 +88,8 @@ int main() tc.compute_tangential_complex(); std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << ".off"; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << + << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); tc.export_to_off(off_stream); From ea61acdb4c1d8a04e2bf4bcd96c0799a381a1e73 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 11 Sep 2014 09:54:57 +0200 Subject: [PATCH 027/269] Remove useless header + compilation fix --- .../test/Tangential_complex/test_tangential_complex.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 51f77c0814b..a44ed2fe252 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -13,8 +13,6 @@ #include #include -#include - #ifdef CGAL_LINKED_WITH_TBB # include #endif @@ -40,7 +38,7 @@ std::vector generate_points_on_sphere(double radius) template std::vector generate_points_on_klein_bottle(double a, double b) { - typedef CGAL::Kernel_traits::type Kernel; + typedef typename CGAL::Kernel_traits::type Kernel; typedef typename Kernel::FT FT; CGAL::Random rng; @@ -88,7 +86,7 @@ int main() tc.compute_tangential_complex(); std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); tc.export_to_off(off_stream); From a84f6908d0eab93e4d9a77734b3a01bc075eb405 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 11 Sep 2014 13:10:50 +0200 Subject: [PATCH 028/269] Use Nanoflann to help computing the tangent plane (using PCA) --- .../include/CGAL/Tangential_complex.h | 56 +- .../CGAL/Tangential_complex/Point_cloud.h | 349 ++++ .../CGAL/Tangential_complex/nanoflann.hpp | 1449 +++++++++++++++++ .../CGAL/Tangential_complex/utilities.h | 4 +- 4 files changed, 1837 insertions(+), 21 deletions(-) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/nanoflann.hpp diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f4caaddc5de..f2ee98ccef8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -26,11 +26,13 @@ #include #include +#include #include #include #include #include +#include #include @@ -90,11 +92,13 @@ class Tangential_complex typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename std::vector Tangent_space_basis; + + typedef Point_cloud Points; + typedef Point_cloud_data_structure Points_ds; typedef std::pair Tr_and_VH; - typedef typename std::vector Point_container; typedef typename std::vector Tr_container; - typedef typename std::vector TS_container; + typedef typename std::vector TS_container; // Stores the index of the original Point in the ambient space /*struct Tr_point_with_index @@ -115,7 +119,7 @@ public: template Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), m_points(first, last) {} + : m_k(k), m_points(first, last, k), m_points_ds(m_points, k) {} /// Destructor ~Tangential_complex() {} @@ -192,8 +196,8 @@ public: //******** VERTICES ************ - Point_container::const_iterator it_p = m_points.begin(); - Point_container::const_iterator it_p_end = m_points.end(); + Points::const_iterator it_p = m_points.begin(); + Points::const_iterator it_p_end = m_points.end(); // For each point p for ( ; it_p != it_p_end ; ++it_p) { @@ -260,7 +264,23 @@ private: Kernel const& m_k; }; - + struct Tr_vertex_to_global_point + { + typedef typename Tr_vertex_handle argument_type; + typedef typename Point result_type; + + Tr_vertex_to_global_point(Points const& points) + : m_points(points) {} + + result_type operator()(argument_type const& vh) const + { + return m_points[vh->data()]; + } + + private: + Points const& m_points; + }; + struct Tr_vertex_to_bare_point { typedef typename Tr_vertex_handle argument_type; @@ -336,8 +356,8 @@ private: std::vector projected_points; FT max_squared_weight = 0; projected_points.reserve(m_points.size() - 1); - Point_container::const_iterator it_p = m_points.begin(); - Point_container::const_iterator it_p_end = m_points.end(); + Points::const_iterator it_p = m_points.begin(); + Points::const_iterator it_p_end = m_points.end(); for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) { // ith point = p, which is already inserted @@ -449,23 +469,20 @@ private: Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - // CJTODO: do better than that (ANN?) - typedef std::set Sorted_points; - Sorted_points sorted_points( - Compare_distance_to_ref_point(p, m_k)); - sorted_points.insert(m_points.begin(), m_points.end()); + std::size_t neighbor_indices[NUM_POINTS_FOR_PCA]; + FT squared_distance[NUM_POINTS_FOR_PCA]; + m_points_ds.query_ANN( + p, NUM_POINTS_FOR_PCA, neighbor_indices, squared_distance); //******************************* PCA ************************************* const int amb_dim = Ambient_dimension::value; // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); - int j = 0; - for (Sorted_points::const_iterator it = sorted_points.begin() ; - j < NUM_POINTS_FOR_PCA ; ++it, ++j) + for (int j = 0 ; j < NUM_POINTS_FOR_PCA ; ++j) { for (int i = 0 ; i < amb_dim ; ++i) - mat_points(j, i) = (*it)[i]; + mat_points(j, i) = m_points[neighbor_indices[j]][i]; // CJTODO: Use kernel functor } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -531,7 +548,7 @@ private: std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); + std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); // CJTODO: use kernel functors? coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { @@ -554,7 +571,8 @@ private: private: const Kernel m_k; - Point_container m_points; + Points m_points; + Points_ds m_points_ds; TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations // and their center vertex diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h new file mode 100644 index 00000000000..1a130113f7e --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -0,0 +1,349 @@ +// 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 +#include +#include +#include + +#include "nanoflann.hpp" + +#include +#include +#include + +namespace CGAL { +namespace Tangential_complex_ { + +template +class Point_cloud +: public std::vector +{ +public: + typedef std::vector Base; + typedef Base Raw_container; + typedef Point_ Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + + //typedef typename Base::iterator iterator; + //typedef typename Base::const_iterator const_iterator; + + static const int AMB_DIM = Ambient_dimension::value; + + Point_cloud(Kernel const& k) + : m_k(k) + { + m_mins.fill(std::numeric_limits::max()); + m_maxs.fill(std::numeric_limits::min()); + } + + template + Point_cloud(InputIterator first, InputIterator last, Kernel const& k) + : Base(first, last), m_k(k) + { + m_mins.fill(std::numeric_limits::max()); + m_maxs.fill(std::numeric_limits::min()); + } + + void push_back(const Point &point, bool update_bbox = false) + { + Base::push_back(point); + + // Adjust bbox? + if (update_bbox) + { + for (int i = 0 ; i < AMB_DIM ; ++i) + { + if (point.get_param(i) < m_mins[i]) + m_mins[i] = point.get_param(i); + + if (point.get_param(i) > m_maxs[i]) + m_maxs[i] = point.get_param(i); + } + } + } + + void compute_bbox(bool only_if_not_already_done = false) + { + if (only_if_not_already_done && m_mins[0] != std::numeric_limits::max()) + return; + + // Reset + m_mins.fill(std::numeric_limits::max()); + m_maxs.fill(std::numeric_limits::min()); + + // Adjust bbox + for (const auto &point : *this) + { + typedef typename Kernel::Compute_coordinate_d Ccd; + const Ccd ccd = m_k.compute_coordinate_d_object(); + for (int i = 0 ; i < AMB_DIM ; ++i) + { + if (ccd(point, i) < m_mins[i]) + m_mins[i] =ccd(point, i); + + if (ccd(point, i) > m_maxs[i]) + m_maxs[i] = ccd(point, i); + } + } + } + + FT get_min(int dim) const + { + return m_mins[dim]; + } + + FT get_max(int dim) const + { + return m_maxs[dim]; + } + + FT bbox_diagonal() const + { + FT sqdiag = 0; + for (std::size_t i = 0 ; i < AMB_DIM ; ++i) + { + FT d = m_maxs[i] - m_mins[i]; + sqdiag += d*d; + } + return CGAL::sqrt(sqdiag); + } + + void recenter_points_around_origin( + bool compute_bbox_if_not_already_done = true) + { + // If the bounding box has not been computed already + if (m_mins[0] == std::numeric_limits::max()) + if (compute_bbox_if_not_already_done) + compute_bbox(); + else + return; + + // Compute centre of bbox + std::array transl_array; + for (std::size_t i = 0 ; i < AMB_DIM ; ++i) + transl_array[i] = -0.5*(m_maxs[i] + m_mins[i]); + + Point transl(transl_array); + +#ifdef CGAL_LINKED_WITH_TBB + tbb::parallel_for(tbb::blocked_range(0, size()), + [&]( const tbb::blocked_range& r ) + { + for (auto i = r.begin(); i != r.end(); ++i) +#else + for (auto i = 0; i != size(); ++i) +#endif + { + (*this)[i] += transl; + } +#ifdef CGAL_LINKED_WITH_TBB + }); +#endif + + } + +protected: + Kernel const& m_k; //!< A const ref to the kernel + // Bounding box + std::array m_mins; + std::array m_maxs; +}; + + +// And this is the "dataset to kd-tree" adaptor class: +template +class Point_cloud_adaptator +{ +public: + typedef typename Point_cloud_::Kernel Kernel; + typedef typename Point_cloud_::Point Point; + typedef typename Point_cloud_::FT FT; + + /// The constructor that sets the data set source + Point_cloud_adaptator(Point_cloud_ &point_cloud, Kernel const& k) + : m_points(point_cloud), m_k(k) + {} + + /// CRTP helper method + inline Point_cloud_ const& point_cloud() const + { + return m_points; + } + inline Point_cloud_& point_cloud() + { + return m_points; + } + + // Must return the number of data points + inline size_t kdtree_get_point_count() const + { + return point_cloud().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, point_cloud()[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()(point_cloud()[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 + bool kdtree_get_bbox(Bbox &bb) const + { + for (int i = 0 ; i < bb.size() ; ++i) + { + bb[i].low = m_points.get_min(i); + bb[i].high = m_points.get_max(i); + } + + return true; + } + + Kernel const& kernel() const + { + return m_k; + } + +protected: + Point_cloud_& m_points; //!< A ref to the data set origin + Kernel const& m_k; //!< A const ref to the kernel + +}; // end of PointCloudAdaptor + +template +class Point_cloud_data_structure +{ +public: + typedef typename Point_cloud_::Kernel Kernel; + typedef typename Point_cloud_::Point Point; + typedef typename Point_cloud_::FT FT; + + static const int AMB_DIM = Ambient_dimension::value; + + /// Constructor + Point_cloud_data_structure(Point_cloud_ &cloud, Kernel const& k) + : m_adaptor(cloud, k), + m_kd_tree(AMB_DIM, + m_adaptor, + nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) + { + cloud.compute_bbox(true); + //cloud.recenter_points_around_origin(); + m_kd_tree.buildIndex(); + } + + Point_cloud_ &point_cloud() + { + return m_adaptor.point_cloud(); + } + + const Point_cloud_ &point_cloud() const + { + return m_adaptor.point_cloud(); + } + + void query_ANN(const Point &sp, + std::size_t k, + size_t *neighbor_indices, + FT *squared_distance) const + { + /*std::vector sp_vec( + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));*/ // CJTODO remettre + std::vector sp_vec; + for (int i = 0 ; i < 4 ; ++i) + sp_vec.push_back(sp[i]); + nanoflann::KNNResultSet 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 > &neighbors, + bool sort_output = true) + { + /*std::vector sp_vec( + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));*/ // CJTODO remettre + std::vector sp_vec; + for (int i = 0 ; i < 4 ; ++i) + sp_vec.push_back(sp[i]); + 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 Adaptor; + typedef nanoflann::KDTreeSingleIndexAdaptor< + nanoflann::L2_Simple_Adaptor , + Adaptor, + AMB_DIM // dim + > Kd_tree; + + Adaptor m_adaptor; + Kd_tree m_kd_tree; +}; + +} // namespace Tangential_complex_ +} //namespace CGAL + +#endif // POINT_CLOUD_H \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/nanoflann.hpp b/Tangential_complex/include/CGAL/Tangential_complex/nanoflann.hpp new file mode 100644 index 00000000000..8bedc45a2d3 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/nanoflann.hpp @@ -0,0 +1,1449 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * Copyright 2011-2013 Jose Luis Blanco (joseluisblancoc@gmail.com). + * All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef NANOFLANN_HPP_ +#define NANOFLANN_HPP_ + +#include +#include +#include +#include +#include // for fwrite() +#include // for fabs(),... +#include + +// Avoid conflicting declaration of min/max macros in windows headers +#if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64)) +# define NOMINMAX +# ifdef max +# undef max +# undef min +# endif +#endif + +namespace nanoflann +{ +/** @addtogroup nanoflann_grp nanoflann C++ library for ANN + * @{ */ + + /** Library version: 0xMmP (M=Major,m=minor,P=path) */ + #define NANOFLANN_VERSION 0x117 + + /** @addtogroup result_sets_grp Result set classes + * @{ */ + template + class KNNResultSet + { + IndexType * indices; + DistanceType* dists; + CountType capacity; + CountType count; + + public: + inline KNNResultSet(CountType capacity_) : capacity(capacity_), count(0) + { + } + + inline void init(IndexType* indices_, DistanceType* dists_) + { + indices = indices_; + dists = dists_; + count = 0; + dists[capacity-1] = (std::numeric_limits::max)(); + } + + inline CountType size() const + { + return count; + } + + inline bool full() const + { + return count == capacity; + } + + + inline void addPoint(DistanceType dist, IndexType index) + { + CountType i; + for (i=count; i>0; --i) { +#ifdef NANOFLANN_FIRST_MATCH // If defined and two poins have the same distance, the one with the lowest-index will be returned first. + if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) ) { +#else + if (dists[i-1]>dist) { +#endif + if (i + class RadiusResultSet + { + public: + const DistanceType radius; + + std::vector >& m_indices_dists; + + inline RadiusResultSet(DistanceType radius_, std::vector >& indices_dists) : radius(radius_), m_indices_dists(indices_dists) + { + init(); + } + + inline ~RadiusResultSet() { } + + inline void init() { clear(); } + inline void clear() { m_indices_dists.clear(); } + + inline size_t size() const { return m_indices_dists.size(); } + + inline bool full() const { return true; } + + inline void addPoint(DistanceType dist, IndexType index) + { + if (dist 0 + */ + std::pair worst_item() const + { + if (m_indices_dists.empty()) throw std::runtime_error("Cannot invoke RadiusResultSet::worst_item() on an empty list of results."); + typedef typename std::vector >::const_iterator DistIt; + DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end()); + return *it; + } + }; + + /** operator "<" for std::sort() */ + struct IndexDist_Sorter + { + /** PairType will be typically: std::pair */ + template + inline bool operator()(const PairType &p1, const PairType &p2) const { + return p1.second < p2.second; + } + }; + + /** @} */ + + + /** @addtogroup loadsave_grp Load/save auxiliary functions + * @{ */ + template + void save_value(FILE* stream, const T& value, size_t count = 1) + { + fwrite(&value, sizeof(value),count, stream); + } + + template + void save_value(FILE* stream, const std::vector& value) + { + size_t size = value.size(); + fwrite(&size, sizeof(size_t), 1, stream); + fwrite(&value[0], sizeof(T), size, stream); + } + + template + void load_value(FILE* stream, T& value, size_t count = 1) + { + size_t read_cnt = fread(&value, sizeof(value), count, stream); + if (read_cnt != count) { + throw std::runtime_error("Cannot read from file"); + } + } + + + template + void load_value(FILE* stream, std::vector& value) + { + size_t size; + size_t read_cnt = fread(&size, sizeof(size_t), 1, stream); + if (read_cnt!=1) { + throw std::runtime_error("Cannot read from file"); + } + value.resize(size); + read_cnt = fread(&value[0], sizeof(T), size, stream); + if (read_cnt!=size) { + throw std::runtime_error("Cannot read from file"); + } + } + /** @} */ + + + /** @addtogroup metric_grp Metric (distance) classes + * @{ */ + + template inline T abs(T x) { return (x<0) ? -x : x; } + template<> inline int abs(int x) { return ::abs(x); } + template<> inline float abs(float x) { return fabsf(x); } + template<> inline double abs(double x) { return fabs(x); } + template<> inline long double abs(long double x) { return fabsl(x); } + + /** Manhattan distance functor (generic version, optimized for high-dimensionality data sets). + * Corresponding distance traits: nanoflann::metric_L1 + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t) + */ + template + struct L1_Adaptor + { + typedef T ElementType; + typedef _DistanceType DistanceType; + + const DataSource &data_source; + + L1_Adaptor(const DataSource &_data_source) : data_source(_data_source) { } + + inline DistanceType operator()(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const + { + DistanceType result = DistanceType(); + const T* last = a + size; + const T* lastgroup = last - 3; + size_t d = 0; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + const DistanceType diff0 = nanoflann::abs(a[0] - data_source.kdtree_get_pt(b_idx,d++)); + const DistanceType diff1 = nanoflann::abs(a[1] - data_source.kdtree_get_pt(b_idx,d++)); + const DistanceType diff2 = nanoflann::abs(a[2] - data_source.kdtree_get_pt(b_idx,d++)); + const DistanceType diff3 = nanoflann::abs(a[3] - data_source.kdtree_get_pt(b_idx,d++)); + result += diff0 + diff1 + diff2 + diff3; + a += 4; + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + /* Process last 0-3 components. Not needed for standard vector lengths. */ + while (a < last) { + result += nanoflann::abs( *a++ - data_source.kdtree_get_pt(b_idx,d++) ); + } + return result; + } + + template + inline DistanceType accum_dist(const U a, const V b, int ) const + { + return nanoflann::abs(a-b); + } + }; + + /** Squared Euclidean distance functor (generic version, optimized for high-dimensionality data sets). + * Corresponding distance traits: nanoflann::metric_L2 + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t) + */ + template + struct L2_Adaptor + { + typedef T ElementType; + typedef _DistanceType DistanceType; + + const DataSource &data_source; + + L2_Adaptor(const DataSource &_data_source) : data_source(_data_source) { } + + inline DistanceType operator()(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const + { + DistanceType result = DistanceType(); + const T* last = a + size; + const T* lastgroup = last - 3; + size_t d = 0; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx,d++); + const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx,d++); + const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx,d++); + const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx,d++); + result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3; + a += 4; + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + /* Process last 0-3 components. Not needed for standard vector lengths. */ + while (a < last) { + const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx,d++); + result += diff0 * diff0; + } + return result; + } + + template + inline DistanceType accum_dist(const U a, const V b, int ) const + { + return (a-b)*(a-b); + } + }; + + /** Squared Euclidean distance functor (suitable for low-dimensionality datasets, like 2D or 3D point clouds) + * Corresponding distance traits: nanoflann::metric_L2_Simple + * \tparam T Type of the elements (e.g. double, float, uint8_t) + * \tparam DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t) + */ + template + struct L2_Simple_Adaptor + { + typedef T ElementType; + typedef _DistanceType DistanceType; + + const DataSource &data_source; + + L2_Simple_Adaptor(const DataSource &_data_source) : data_source(_data_source) { } + + inline DistanceType operator()(const T* a, const size_t b_idx, size_t size) const { + return data_source.kdtree_distance(a,b_idx,size); + } + + template + inline DistanceType accum_dist(const U a, const V b, int ) const + { + return (a-b)*(a-b); + } + }; + + /** Metaprogramming helper traits class for the L1 (Manhattan) metric */ + struct metric_L1 { + template + struct traits { + typedef L1_Adaptor distance_t; + }; + }; + /** Metaprogramming helper traits class for the L2 (Euclidean) metric */ + struct metric_L2 { + template + struct traits { + typedef L2_Adaptor distance_t; + }; + }; + /** Metaprogramming helper traits class for the L2_simple (Euclidean) metric */ + struct metric_L2_Simple { + template + struct traits { + typedef L2_Simple_Adaptor distance_t; + }; + }; + + /** @} */ + + + + /** @addtogroup param_grp Parameter structs + * @{ */ + + /** Parameters (see http://code.google.com/p/nanoflann/ for help choosing the parameters) + */ + struct KDTreeSingleIndexAdaptorParams + { + KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size = 10, int dim_ = -1) : + leaf_max_size(_leaf_max_size), dim(dim_) + {} + + size_t leaf_max_size; + int dim; + }; + + /** Search options for KDTreeSingleIndexAdaptor::findNeighbors() */ + struct SearchParams + { + /** Note: The first argument (checks_IGNORED_) is ignored, but kept for compatibility with the FLANN interface */ + SearchParams(int checks_IGNORED_ = 32, float eps_ = 0, bool sorted_ = true ) : + checks(checks_IGNORED_), eps(eps_), sorted(sorted_) {} + + int checks; //!< Ignored parameter (Kept for compatibility with the FLANN interface). + float eps; //!< search for eps-approximate neighbours (default: 0) + bool sorted; //!< only for radius search, require neighbours sorted by distance (default: true) + }; + /** @} */ + + + /** @addtogroup memalloc_grp Memory allocation + * @{ */ + + /** + * Allocates (using C's malloc) a generic type T. + * + * Params: + * count = number of instances to allocate. + * Returns: pointer (of type T*) to memory buffer + */ + template + inline T* allocate(size_t count = 1) + { + T* mem = (T*) ::malloc(sizeof(T)*count); + return mem; + } + + + /** + * Pooled storage allocator + * + * The following routines allow for the efficient allocation of storage in + * small chunks from a specified pool. Rather than allowing each structure + * to be freed individually, an entire pool of storage is freed at once. + * This method has two advantages over just using malloc() and free(). First, + * it is far more efficient for allocating small objects, as there is + * no overhead for remembering all the information needed to free each + * object or consolidating fragmented memory. Second, the decision about + * how long to keep an object is made at the time of allocation, and there + * is no need to track down all the objects to free them. + * + */ + + const size_t WORDSIZE=16; + const size_t BLOCKSIZE=8192; + + class PooledAllocator + { + /* We maintain memory alignment to word boundaries by requiring that all + allocations be in multiples of the machine wordsize. */ + /* Size of machine word in bytes. Must be power of 2. */ + /* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */ + + + size_t remaining; /* Number of bytes left in current block of storage. */ + void* base; /* Pointer to base of current block of storage. */ + void* loc; /* Current location in block to next allocate memory. */ + size_t blocksize; + + void internal_init() + { + remaining = 0; + base = NULL; + usedMemory = 0; + wastedMemory = 0; + } + + public: + size_t usedMemory; + size_t wastedMemory; + + /** + Default constructor. Initializes a new pool. + */ + PooledAllocator(const size_t blocksize_ = BLOCKSIZE) : blocksize(blocksize_) { + internal_init(); + } + + /** + * Destructor. Frees all the memory allocated in this pool. + */ + ~PooledAllocator() { + free_all(); + } + + /** Frees all allocated memory chunks */ + void free_all() + { + while (base != NULL) { + void *prev = *((void**) base); /* Get pointer to prev block. */ + ::free(base); + base = prev; + } + internal_init(); + } + + /** + * Returns a pointer to a piece of new memory of the given size in bytes + * allocated from the pool. + */ + void* malloc(const size_t req_size) + { + /* Round size up to a multiple of wordsize. The following expression + only works for WORDSIZE that is a power of 2, by masking last bits of + incremented size to zero. + */ + const size_t size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1); + + /* Check whether a new block must be allocated. Note that the first word + of a block is reserved for a pointer to the previous block. + */ + if (size > remaining) { + + wastedMemory += remaining; + + /* Allocate new storage. */ + const size_t blocksize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ? + size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE; + + // use the standard C malloc to allocate memory + void* m = ::malloc(blocksize); + if (!m) { + fprintf(stderr,"Failed to allocate memory.\n"); + return NULL; + } + + /* Fill first word of new block with pointer to previous block. */ + ((void**) m)[0] = base; + base = m; + + size_t shift = 0; + //int size_t = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1); + + remaining = blocksize - sizeof(void*) - shift; + loc = ((char*)m + sizeof(void*) + shift); + } + void* rloc = loc; + loc = (char*)loc + size; + remaining -= size; + + usedMemory += size; + + return rloc; + } + + /** + * Allocates (using this pool) a generic type T. + * + * Params: + * count = number of instances to allocate. + * Returns: pointer (of type T*) to memory buffer + */ + template + T* allocate(const size_t count = 1) + { + T* mem = (T*) this->malloc(sizeof(T)*count); + return mem; + } + + }; + /** @} */ + + /** @addtogroup nanoflann_metaprog_grp Auxiliary metaprogramming stuff + * @{ */ + + // ---------------- CArray ------------------------- + /** A STL container (as wrapper) for arrays of constant size defined at compile time (class imported from the MRPT project) + * This code is an adapted version from Boost, modifed for its integration + * within MRPT (JLBC, Dec/2009) (Renamed array -> CArray to avoid possible potential conflicts). + * See + * http://www.josuttis.com/cppcode + * for details and the latest version. + * See + * http://www.boost.org/libs/array for Documentation. + * for documentation. + * + * (C) Copyright Nicolai M. Josuttis 2001. + * Permission to copy, use, modify, sell and distribute this software + * is granted provided this copyright notice appears in all copies. + * This software is provided "as is" without express or implied + * warranty, and with no claim as to its suitability for any purpose. + * + * 29 Jan 2004 - minor fixes (Nico Josuttis) + * 04 Dec 2003 - update to synch with library TR1 (Alisdair Meredith) + * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries. + * 05 Aug 2001 - minor update (Nico Josuttis) + * 20 Jan 2001 - STLport fix (Beman Dawes) + * 29 Sep 2000 - Initial Revision (Nico Josuttis) + * + * Jan 30, 2004 + */ + template + class CArray { + public: + T elems[N]; // fixed-size array of elements of type T + + public: + // type definitions + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // iterator support + inline iterator begin() { return elems; } + inline const_iterator begin() const { return elems; } + inline iterator end() { return elems+N; } + inline const_iterator end() const { return elems+N; } + + // reverse iterator support +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) + // workaround for broken reverse_iterator in VC7 + typedef std::reverse_iterator > reverse_iterator; + typedef std::reverse_iterator > const_reverse_iterator; +#else + // workaround for broken reverse_iterator implementations + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#endif + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + // operator[] + inline reference operator[](size_type i) { return elems[i]; } + inline const_reference operator[](size_type i) const { return elems[i]; } + // at() with range check + reference at(size_type i) { rangecheck(i); return elems[i]; } + const_reference at(size_type i) const { rangecheck(i); return elems[i]; } + // front() and back() + reference front() { return elems[0]; } + const_reference front() const { return elems[0]; } + reference back() { return elems[N-1]; } + const_reference back() const { return elems[N-1]; } + // size is constant + static inline size_type size() { return N; } + static bool empty() { return false; } + static size_type max_size() { return N; } + enum { static_size = N }; + /** This method has no effects in this class, but raises an exception if the expected size does not match */ + inline void resize(const size_t nElements) { if (nElements!=N) throw std::logic_error("Try to change the size of a CArray."); } + // swap (note: linear complexity in N, constant for given instantiation) + void swap (CArray& y) { std::swap_ranges(begin(),end(),y.begin()); } + // direct access to data (read-only) + const T* data() const { return elems; } + // use array as C array (direct read/write access to data) + T* data() { return elems; } + // assignment with type conversion + template CArray& operator= (const CArray& rhs) { + std::copy(rhs.begin(),rhs.end(), begin()); + return *this; + } + // assign one value to all elements + inline void assign (const T& value) { for (size_t i=0;i= size()) { throw std::out_of_range("CArray<>: index out of range"); } } + }; // end of CArray + + /** Used to declare fixed-size arrays when DIM>0, dynamically-allocated vectors when DIM=-1. + * Fixed size version for a generic DIM: + */ + template + struct array_or_vector_selector + { + typedef CArray container_t; + }; + /** Dynamic size version */ + template + struct array_or_vector_selector<-1,T> { + typedef std::vector container_t; + }; + /** @} */ + + /** @addtogroup kdtrees_grp KD-tree classes and adaptors + * @{ */ + + /** kd-tree index + * + * Contains the k-d trees and other information for indexing a set of points + * for nearest-neighbor matching. + * + * The class "DatasetAdaptor" must provide the following interface (can be non-virtual, inlined methods): + * + * \code + * // Must return the number of data points + * inline size_t kdtree_get_point_count() const { ... } + * + * // Must return the Euclidean (L2) distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class: + * inline DistanceType kdtree_distance(const T *p1, const size_t idx_p2,size_t size) const { ... } + * + * // Must return the dim'th component of the idx'th point in the class: + * inline T kdtree_get_pt(const size_t idx, int dim) const { ... } + * + * // 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 + * bool kdtree_get_bbox(BBOX &bb) const + * { + * bb[0].low = ...; bb[0].high = ...; // 0th dimension limits + * bb[1].low = ...; bb[1].high = ...; // 1st dimension limits + * ... + * return true; + * } + * + * \endcode + * + * \tparam IndexType Will be typically size_t or int + */ + template + class KDTreeSingleIndexAdaptor + { + public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::DistanceType DistanceType; + protected: + + /** + * Array of indices to vectors in the dataset. + */ + std::vector vind; + + size_t m_leaf_max_size; + + + /** + * The dataset used by this index + */ + const DatasetAdaptor &dataset; //!< The source of our data + + const KDTreeSingleIndexAdaptorParams index_params; + + size_t m_size; + int dim; //!< Dimensionality of each data point + + + /*--------------------- Internal Data Structures --------------------------*/ + struct Node + { + union { + struct + { + /** + * Indices of points in leaf node + */ + IndexType left, right; + } lr; + struct + { + /** + * Dimension used for subdivision. + */ + int divfeat; + /** + * The values used for subdivision. + */ + DistanceType divlow, divhigh; + } sub; + }; + /** + * The child nodes. + */ + Node* child1, * child2; + }; + typedef Node* NodePtr; + + + struct Interval + { + ElementType low, high; + }; + + /** Define "BoundingBox" as a fixed-size or variable-size container depending on "DIM" */ + typedef typename array_or_vector_selector::container_t BoundingBox; + + /** Define "distance_vector_t" as a fixed-size or variable-size container depending on "DIM" */ + typedef typename array_or_vector_selector::container_t distance_vector_t; + + /** This record represents a branch point when finding neighbors in + the tree. It contains a record of the minimum distance to the query + point, as well as the node at which the search resumes. + */ + template + struct BranchStruct + { + T node; /* Tree node at which search resumes */ + DistanceType mindist; /* Minimum distance to query for all nodes below. */ + + BranchStruct() {} + BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {} + + inline bool operator<(const BranchStruct& rhs) const + { + return mindist BranchSt; + typedef BranchSt* Branch; + + BoundingBox root_bbox; + + /** + * Pooled memory allocator. + * + * Using a pooled memory allocator is more efficient + * than allocating memory directly when there is a large + * number small of memory allocations. + */ + PooledAllocator pool; + + public: + + Distance distance; + + /** + * KDTree constructor + * + * Params: + * inputData = dataset with the input features + * params = parameters passed to the kdtree algorithm (see http://code.google.com/p/nanoflann/ for help choosing the parameters) + */ + KDTreeSingleIndexAdaptor(const int dimensionality, const DatasetAdaptor& inputData, const KDTreeSingleIndexAdaptorParams& params = KDTreeSingleIndexAdaptorParams() ) : + dataset(inputData), index_params(params), root_node(NULL), distance(inputData) + { + m_size = dataset.kdtree_get_point_count(); + dim = dimensionality; + if (DIM>0) dim=DIM; + else { + if (params.dim>0) dim = params.dim; + } + m_leaf_max_size = params.leaf_max_size; + + // Create a permutable array of indices to the input vectors. + init_vind(); + } + + /** + * Standard destructor + */ + ~KDTreeSingleIndexAdaptor() + { + } + + /** Frees the previously-built index. Automatically called within buildIndex(). */ + void freeIndex() + { + pool.free_all(); + root_node=NULL; + } + + /** + * Builds the index + */ + void buildIndex() + { + init_vind(); + computeBoundingBox(root_bbox); + freeIndex(); + root_node = divideTree(0, m_size, root_bbox ); // construct the tree + } + + /** + * Returns size of index. + */ + size_t size() const + { + return m_size; + } + + /** + * Returns the length of an index feature. + */ + size_t veclen() const + { + return static_cast(DIM>0 ? DIM : dim); + } + + /** + * Computes the inde memory usage + * Returns: memory used by the index + */ + size_t usedMemory() const + { + return pool.usedMemory+pool.wastedMemory+dataset.kdtree_get_point_count()*sizeof(IndexType); // pool memory and vind array memory + } + + /** \name Query methods + * @{ */ + + /** + * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored inside + * the result object. + * + * Params: + * result = the result object in which the indices of the nearest-neighbors are stored + * vec = the vector for which to search the nearest neighbors + * + * \tparam RESULTSET Should be any ResultSet + * \sa knnSearch, radiusSearch + */ + template + void findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParams& searchParams) const + { + assert(vec); + if (!root_node) throw std::runtime_error("[nanoflann] findNeighbors() called before building the index."); + float epsError = 1+searchParams.eps; + + distance_vector_t dists; // fixed or variable-sized container (depending on DIM) + dists.assign((DIM>0 ? DIM : dim) ,0); // Fill it with zeros. + DistanceType distsq = computeInitialDistances(vec, dists); + searchLevel(result, vec, root_node, distsq, dists, epsError); // "count_leaf" parameter removed since was neither used nor returned to the user. + } + + /** + * Find the "num_closest" nearest neighbors to the \a query_point[0:dim-1]. Their indices are stored inside + * the result object. + * \sa radiusSearch, findNeighbors + * \note nChecks_IGNORED is ignored but kept for compatibility with the original FLANN interface. + */ + inline void knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int nChecks_IGNORED = 10) const + { + nanoflann::KNNResultSet resultSet(num_closest); + resultSet.init(out_indices, out_distances_sq); + this->findNeighbors(resultSet, query_point, nanoflann::SearchParams()); + } + + /** + * Find all the neighbors to \a query_point[0:dim-1] within a maximum radius. + * The output is given as a vector of pairs, of which the first element is a point index and the second the corresponding distance. + * Previous contents of \a IndicesDists are cleared. + * + * If searchParams.sorted==true, the output list is sorted by ascending distances. + * + * For a better performance, it is advisable to do a .reserve() on the vector if you have any wild guess about the number of expected matches. + * + * \sa knnSearch, findNeighbors + * \return The number of points within the given radius (i.e. indices.size() or dists.size() ) + */ + size_t radiusSearch(const ElementType *query_point,const DistanceType radius, std::vector >& IndicesDists, const SearchParams& searchParams) const + { + RadiusResultSet resultSet(radius,IndicesDists); + this->findNeighbors(resultSet, query_point, searchParams); + + if (searchParams.sorted) + std::sort(IndicesDists.begin(),IndicesDists.end(), IndexDist_Sorter() ); + + return resultSet.size(); + } + + /** @} */ + + private: + /** Make sure the auxiliary list \a vind has the same size than the current dataset, and re-generate if size has changed. */ + void init_vind() + { + // Create a permutable array of indices to the input vectors. + m_size = dataset.kdtree_get_point_count(); + if (vind.size()!=m_size) vind.resize(m_size); + for (size_t i = 0; i < m_size; i++) vind[i] = i; + } + + /// Helper accessor to the dataset points: + inline ElementType dataset_get(size_t idx, int component) const { + return dataset.kdtree_get_pt(idx,component); + } + + + void save_tree(FILE* stream, NodePtr tree) + { + save_value(stream, *tree); + if (tree->child1!=NULL) { + save_tree(stream, tree->child1); + } + if (tree->child2!=NULL) { + save_tree(stream, tree->child2); + } + } + + + void load_tree(FILE* stream, NodePtr& tree) + { + tree = pool.allocate(); + load_value(stream, *tree); + if (tree->child1!=NULL) { + load_tree(stream, tree->child1); + } + if (tree->child2!=NULL) { + load_tree(stream, tree->child2); + } + } + + + void computeBoundingBox(BoundingBox& bbox) + { + bbox.resize((DIM>0 ? DIM : dim)); + if (dataset.kdtree_get_bbox(bbox)) + { + // Done! It was implemented in derived class + } + else + { + for (int i=0; i<(DIM>0 ? DIM : dim); ++i) { + bbox[i].low = + bbox[i].high = dataset_get(0,i); + } + const size_t N = dataset.kdtree_get_point_count(); + for (size_t k=1; k0 ? DIM : dim); ++i) { + if (dataset_get(k,i)bbox[i].high) bbox[i].high = dataset_get(k,i); + } + } + } + } + + + /** + * Create a tree node that subdivides the list of vecs from vind[first] + * to vind[last]. The routine is called recursively on each sublist. + * Place a pointer to this new tree node in the location pTree. + * + * Params: pTree = the new node to create + * first = index of the first vector + * last = index of the last vector + */ + NodePtr divideTree(const IndexType left, const IndexType right, BoundingBox& bbox) + { + NodePtr node = pool.allocate(); // allocate memory + + /* If too few exemplars remain, then make this a leaf node. */ + if ( (right-left) <= m_leaf_max_size) { + node->child1 = node->child2 = NULL; /* Mark as leaf node. */ + node->lr.left = left; + node->lr.right = right; + + // compute bounding-box of leaf points + for (int i=0; i<(DIM>0 ? DIM : dim); ++i) { + bbox[i].low = dataset_get(vind[left],i); + bbox[i].high = dataset_get(vind[left],i); + } + for (IndexType k=left+1; k0 ? DIM : dim); ++i) { + if (bbox[i].low>dataset_get(vind[k],i)) bbox[i].low=dataset_get(vind[k],i); + if (bbox[i].highsub.divfeat = cutfeat; + + BoundingBox left_bbox(bbox); + left_bbox[cutfeat].high = cutval; + node->child1 = divideTree(left, left+idx, left_bbox); + + BoundingBox right_bbox(bbox); + right_bbox[cutfeat].low = cutval; + node->child2 = divideTree(left+idx, right, right_bbox); + + node->sub.divlow = left_bbox[cutfeat].high; + node->sub.divhigh = right_bbox[cutfeat].low; + + for (int i=0; i<(DIM>0 ? DIM : dim); ++i) { + bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low); + bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high); + } + } + + return node; + } + + void computeMinMax(IndexType* ind, IndexType count, int element, ElementType& min_elem, ElementType& max_elem) + { + min_elem = dataset_get(ind[0],element); + max_elem = dataset_get(ind[0],element); + for (IndexType i=1; imax_elem) max_elem = val; + } + } + + void middleSplit(IndexType* ind, IndexType count, IndexType& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox) + { + // find the largest span from the approximate bounding box + ElementType max_span = bbox[0].high-bbox[0].low; + cutfeat = 0; + cutval = (bbox[0].high+bbox[0].low)/2; + for (int i=1; i<(DIM>0 ? DIM : dim); ++i) { + ElementType span = bbox[i].low-bbox[i].low; + if (span>max_span) { + max_span = span; + cutfeat = i; + cutval = (bbox[i].high+bbox[i].low)/2; + } + } + + // compute exact span on the found dimension + ElementType min_elem, max_elem; + computeMinMax(ind, count, cutfeat, min_elem, max_elem); + cutval = (min_elem+max_elem)/2; + max_span = max_elem - min_elem; + + // check if a dimension of a largest span exists + size_t k = cutfeat; + for (size_t i=0; i<(DIM>0 ? DIM : dim); ++i) { + if (i==k) continue; + ElementType span = bbox[i].high-bbox[i].low; + if (span>max_span) { + computeMinMax(ind, count, i, min_elem, max_elem); + span = max_elem - min_elem; + if (span>max_span) { + max_span = span; + cutfeat = i; + cutval = (min_elem+max_elem)/2; + } + } + } + IndexType lim1, lim2; + planeSplit(ind, count, cutfeat, cutval, lim1, lim2); + + if (lim1>count/2) index = lim1; + else if (lim2(0.00001); + ElementType max_span = bbox[0].high-bbox[0].low; + for (int i=1; i<(DIM>0 ? DIM : dim); ++i) { + ElementType span = bbox[i].high-bbox[i].low; + if (span>max_span) { + max_span = span; + } + } + ElementType max_spread = -1; + cutfeat = 0; + for (int i=0; i<(DIM>0 ? DIM : dim); ++i) { + ElementType span = bbox[i].high-bbox[i].low; + if (span>(1-EPS)*max_span) { + ElementType min_elem, max_elem; + computeMinMax(ind, count, cutfeat, min_elem, max_elem); + ElementType spread = max_elem-min_elem;; + if (spread>max_spread) { + cutfeat = i; + max_spread = spread; + } + } + } + // split in the middle + DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2; + ElementType min_elem, max_elem; + computeMinMax(ind, count, cutfeat, min_elem, max_elem); + + if (split_valmax_elem) cutval = max_elem; + else cutval = split_val; + + IndexType lim1, lim2; + planeSplit(ind, count, cutfeat, cutval, lim1, lim2); + + if (lim1>count/2) index = lim1; + else if (lim2cutval + */ + void planeSplit(IndexType* ind, const IndexType count, int cutfeat, DistanceType cutval, IndexType& lim1, IndexType& lim2) + { + /* Move vector indices for left subtree to front of list. */ + IndexType left = 0; + IndexType right = count-1; + for (;; ) { + while (left<=right && dataset_get(ind[left],cutfeat)=cutval) --right; + if (left>right || !right) break; // "!right" was added to support unsigned Index types + std::swap(ind[left], ind[right]); + ++left; + --right; + } + /* If either list is empty, it means that all remaining features + * are identical. Split in the middle to maintain a balanced tree. + */ + lim1 = left; + right = count-1; + for (;; ) { + while (left<=right && dataset_get(ind[left],cutfeat)<=cutval) ++left; + while (right && left<=right && dataset_get(ind[right],cutfeat)>cutval) --right; + if (left>right || !right) break; // "!right" was added to support unsigned Index types + std::swap(ind[left], ind[right]); + ++left; + --right; + } + lim2 = left; + } + + DistanceType computeInitialDistances(const ElementType* vec, distance_vector_t& dists) const + { + assert(vec); + DistanceType distsq = 0.0; + + for (int i = 0; i < (DIM>0 ? DIM : dim); ++i) { + if (vec[i] < root_bbox[i].low) { + dists[i] = distance.accum_dist(vec[i], root_bbox[i].low, i); + distsq += dists[i]; + } + if (vec[i] > root_bbox[i].high) { + dists[i] = distance.accum_dist(vec[i], root_bbox[i].high, i); + distsq += dists[i]; + } + } + + return distsq; + } + + /** + * Performs an exact search in the tree starting from a node. + * \tparam RESULTSET Should be any ResultSet + */ + template + void searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindistsq, + distance_vector_t& dists, const float epsError) const + { + /* If this is a leaf node, then do check and return. */ + if ((node->child1 == NULL)&&(node->child2 == NULL)) { + //count_leaf += (node->lr.right-node->lr.left); // Removed since was neither used nor returned to the user. + DistanceType worst_dist = result_set.worstDist(); + for (IndexType i=node->lr.left; ilr.right; ++i) { + const IndexType index = vind[i];// reorder... : i; + DistanceType dist = distance(vec, index, (DIM>0 ? DIM : dim)); + if (distsub.divfeat; + ElementType val = vec[idx]; + DistanceType diff1 = val - node->sub.divlow; + DistanceType diff2 = val - node->sub.divhigh; + + NodePtr bestChild; + NodePtr otherChild; + DistanceType cut_dist; + if ((diff1+diff2)<0) { + bestChild = node->child1; + otherChild = node->child2; + cut_dist = distance.accum_dist(val, node->sub.divhigh, idx); + } + else { + bestChild = node->child2; + otherChild = node->child1; + cut_dist = distance.accum_dist( val, node->sub.divlow, idx); + } + + /* Call recursively to search next level down. */ + searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError); + + DistanceType dst = dists[idx]; + mindistsq = mindistsq + cut_dist - dst; + dists[idx] = cut_dist; + if (mindistsq*epsError<=result_set.worstDist()) { + searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError); + } + dists[idx] = dst; + } + + public: + /** Stores the index in a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so when loading the index object it must be constructed associated to the same source of data points used while building it. + * See the example: examples/saveload_example.cpp + * \sa loadIndex */ + void saveIndex(FILE* stream) + { + save_value(stream, m_size); + save_value(stream, dim); + save_value(stream, root_bbox); + save_value(stream, m_leaf_max_size); + save_value(stream, vind); + save_tree(stream, root_node); + } + + /** Loads a previous index from a binary file. + * IMPORTANT NOTE: The set of data points is NOT stored in the file, so the index object must be constructed associated to the same source of data points used while building the index. + * See the example: examples/saveload_example.cpp + * \sa loadIndex */ + void loadIndex(FILE* stream) + { + load_value(stream, m_size); + load_value(stream, dim); + load_value(stream, root_bbox); + load_value(stream, m_leaf_max_size); + load_value(stream, vind); + load_tree(stream, root_node); + } + + }; // class KDTree + + + /** A simple KD-tree adaptor for working with data directly stored in an Eigen Matrix, without duplicating the data storage. + * Each row in the matrix represents a point in the state space. + * + * Example of usage: + * \code + * Eigen::Matrix mat; + * // Fill out "mat"... + * + * typedef KDTreeEigenMatrixAdaptor< Eigen::Matrix > my_kd_tree_t; + * const int max_leaf = 10; + * my_kd_tree_t mat_index(dimdim, mat, max_leaf ); + * mat_index.index->buildIndex(); + * mat_index.index->... + * \endcode + * + * \tparam DIM If set to >0, it specifies a compile-time fixed dimensionality for the points in the data set, allowing more compiler optimizations. + * \tparam Distance The distance metric to use: nanoflann::metric_L1, nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. + * \tparam IndexType The type for indices in the KD-tree index (typically, size_t of int) + */ + template + struct KDTreeEigenMatrixAdaptor + { + typedef KDTreeEigenMatrixAdaptor self_t; + typedef typename MatrixType::Scalar num_t; + typedef typename Distance::template traits::distance_t metric_t; + typedef KDTreeSingleIndexAdaptor< metric_t,self_t,DIM,IndexType> index_t; + + index_t* index; //! The kd-tree index for the user to call its methods as usual with any other FLANN index. + + /// Constructor: takes a const ref to the matrix object with the data points + KDTreeEigenMatrixAdaptor(const int dimensionality, const MatrixType &mat, const int leaf_max_size = 10) : m_data_matrix(mat) + { + const size_t dims = mat.cols(); + if (DIM>0 && static_cast(dims)!=DIM) + throw std::runtime_error("Data set dimensionality does not match the 'DIM' template argument"); + index = new index_t( dims, *this /* adaptor */, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size, dims ) ); + index->buildIndex(); + } + + ~KDTreeEigenMatrixAdaptor() { + delete index; + } + + const MatrixType &m_data_matrix; + + /** Query for the \a num_closest closest points to a given point (entered as query_point[0:dim-1]). + * Note that this is a short-cut method for index->findNeighbors(). + * The user can also call index->... methods as desired. + * \note nChecks_IGNORED is ignored but kept for compatibility with the original FLANN interface. + */ + inline void query(const num_t *query_point, const size_t num_closest, IndexType *out_indices, num_t *out_distances_sq, const int nChecks_IGNORED = 10) const + { + nanoflann::KNNResultSet resultSet(num_closest); + resultSet.init(out_indices, out_distances_sq); + index->findNeighbors(resultSet, query_point, nanoflann::SearchParams()); + } + + /** @name Interface expected by KDTreeSingleIndexAdaptor + * @{ */ + + const self_t & derived() const { + return *this; + } + self_t & derived() { + return *this; + } + + // Must return the number of data points + inline size_t kdtree_get_point_count() const { + return m_data_matrix.rows(); + } + + // Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class: + inline num_t kdtree_distance(const num_t *p1, const size_t idx_p2,size_t size) const + { + num_t s=0; + for (size_t i=0; i + bool kdtree_get_bbox(BBOX &bb) const { + return false; + } + + /** @} */ + + }; // end of KDTreeEigenMatrixAdaptor + /** @} */ + +/** @} */ // end of grouping +} // end of NS + + +#endif /* NANOFLANN_HPP_ */ diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 2ce238cc8c1..f58ace643b3 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -23,11 +23,11 @@ #include #include +#include #include namespace CGAL { - namespace Tangential_complex_ { template @@ -70,7 +70,7 @@ namespace Tangential_complex_ { return output_basis; } -}; // namespace Tangential_complex_ +} // namespace Tangential_complex_ } //namespace CGAL #endif // CGAL_TC_UTILITIES_H From 92873230e16305997356c5acd29e377e9bdcdd94 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 11:08:47 +0200 Subject: [PATCH 029/269] Remove the using and call the base's operator() explicitly --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index 1526c084885..cec297a9550 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -89,16 +89,15 @@ 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); } }; struct Construct_iso_box_d: public Base::Construct_iso_box_d{ From e41c06324b09fd96e850c2b922b451bcfe0573cd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 11:15:22 +0200 Subject: [PATCH 030/269] Use CGAL's spatial searching + change the computation of the "star sphere" (Waiting for a patch in Cartesian_wrap so that it works correctly) --- .../include/CGAL/Tangential_complex.h | 101 ++++-- .../CGAL/Tangential_complex/Point_cloud.h | 292 +++++++----------- .../include/CGAL/Tangential_complex/config.h | 7 +- 3 files changed, 196 insertions(+), 204 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f2ee98ccef8..2cdb28ee3c4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -91,9 +91,9 @@ class Tangential_complex typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; - typedef typename std::vector Tangent_space_basis; - - typedef Point_cloud Points; + typedef std::vector Tangent_space_basis; + + typedef std::vector Points; typedef Point_cloud_data_structure Points_ds; typedef std::pair Tr_and_VH; @@ -119,7 +119,7 @@ public: template Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), m_points(first, last, k), m_points_ds(m_points, k) {} + : m_k(k), m_points(first, last), m_points_ds(m_points, k) {} /// Destructor ~Tangential_complex() {} @@ -335,13 +335,17 @@ private: const Tr_traits &local_tr_traits = p_local_tr->geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; - // Traits functor & objects - Tr_traits::Center_of_sphere_d center_of_sphere = - local_tr_traits.center_of_sphere_d_object(); + // Kernel functor & objects + //Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); // CJTODO: use that + Get_functor::type k_diff_pts(m_k); + + // Triangulation's traits functor & objects Tr_traits::Squared_distance_d sqdist = local_tr_traits.squared_distance_d_object(); Tr_traits::Point_drop_weight_d drop_w = local_tr_traits.point_drop_weight_d_object(); + Tr_traits::Center_of_sphere_d center_of_sphere = + local_tr_traits.center_of_sphere_d_object(); // Estimate the tangent space const Point ¢er_pt = m_points[i]; @@ -352,18 +356,27 @@ private: // (we only need the star of p) //*************************************************** + const int NUM_NEIGHBORS = 150; + std::size_t nearest_nb[NUM_NEIGHBORS]; + FT squared_distance[NUM_NEIGHBORS]; + m_points_ds.query_ANN( + center_pt, NUM_NEIGHBORS, nearest_nb, squared_distance); + /*const int NUM_NEIGHBORS = 150; + std::size_t nearest_nb[NUM_NEIGHBORS]; + for (int ii = 0 ; ii < NUM_NEIGHBORS ; ++ii) + nearest_nb[ii] = ii;*/ + // First, compute the projected points std::vector projected_points; FT max_squared_weight = 0; - projected_points.reserve(m_points.size() - 1); - Points::const_iterator it_p = m_points.begin(); - Points::const_iterator it_p_end = m_points.end(); - for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) + projected_points.reserve(NUM_NEIGHBORS); + for (std::size_t j = 0 ; j < NUM_NEIGHBORS ; ++j) { // ith point = p, which is already inserted - if (j != i) + std::size_t idx = nearest_nb[j]; + //if (idx != i) // CJTODO optim? { - Tr_point wp = project_point(*it_p, center_pt, m_tangent_spaces[i]); + Tr_point wp = project_point(m_points[idx], center_pt, m_tangent_spaces[i]); projected_points.push_back(wp); FT w = local_tr_traits.point_weight_d_object()(wp); if (w > max_squared_weight) @@ -384,41 +397,39 @@ private: // While building the local triangulation, we keep the radius // of the sphere centered at "center_vertex" and which contains all the // circumspheres of the star of "center_vertex" - // [TODO?] For now, we use non-weighted circumspheres but it could be - // optimized by using weighted circumspheres (which are smaller) FT star_sphere_squared_radius = std::numeric_limits::max(); // Insert the other points - std::vector::const_iterator it_wp = projected_points.begin(); - it_p = m_points.begin(); - for (std::size_t j = 0 ; it_p != it_p_end ; ++it_p, ++j) + for (std::size_t j = 0 ; j < NUM_NEIGHBORS ; ++j) { + std::size_t point_idx = nearest_nb[j]; + Tr_point const& proj_pt = projected_points[j]; + // ith point = p, which is already inserted - if (j != i) + if (point_idx != i) { - if (local_tr_traits.squared_distance_d_object()( - drop_w(wp), drop_w(*it_wp)) + if (m_k.squared_distance_d_object()( + center_pt, m_points[point_idx]) > star_sphere_squared_radius) { - ++it_wp; continue; } FT squared_dist_to_tangent_plane = - local_tr_traits.point_weight_d_object()(*it_wp); + local_tr_traits.point_weight_d_object()(proj_pt); FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - drop_w(*it_wp), + drop_w(proj_pt), w); Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); //Tr_vertex_handle vh = p_local_tr->insert(wp); if (vh != Tr_vertex_handle()) { - vh->data() = j; + vh->data() = point_idx; // Let's recompute star_sphere_squared_radius if (p_local_tr->current_dimension() >= Intrinsic_dimension) - { + { star_sphere_squared_radius = 0.; // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; @@ -434,11 +445,40 @@ private: } else { - Tr_vertex_to_bare_point v2p(local_tr_traits); + //********************************* + Tangent_space_basis tsb; + tsb.reserve(Intrinsic_dimension); + Point const& orig = m_points[cell->vertex(0)->data()]; + for (int ii = 1 ; ii <= Intrinsic_dimension ; ++ii) + { + tsb.push_back(k_diff_pts( + m_points[cell->vertex(ii)->data()], orig)); + } + tsb = compute_gram_schmidt_basis(tsb, m_k); + + // CJTODO: write a project_point which returns a Tr_bare_point + // and use it here + std::vector proj_pts; + std::vector::const_iterator it_p = proj_pts.begin(); + std::vector::const_iterator it_p_end = proj_pts.end(); + // For each point p + for (int ii = 0 ; ii <= Intrinsic_dimension ; ++ii) + { + proj_pts.push_back(project_point( + m_points[cell->vertex(ii)->data()], orig, tsb)); + } + Tr_bare_point c = center_of_sphere( - boost::make_transform_iterator(cell->vertices_begin(), v2p), - boost::make_transform_iterator(cell->vertices_end(), v2p)); - FT sq_circumdiam = 4.*sqdist(c, drop_w(center_vertex->point())); + boost::make_transform_iterator(proj_pts.begin(), drop_w), + boost::make_transform_iterator(proj_pts.end(), drop_w)); + + //********************************* + //Tr_vertex_to_global_point v2gp(m_points); + //Point c = k_center_of_sphere( + // boost::make_transform_iterator(cell->vertices_begin(), v2gp), + // boost::make_transform_iterator(cell->vertices_end(), v2gp)); + //********************************* + FT sq_circumdiam = 4.*sqdist(c, drop_w(proj_pts[0])); if (sq_circumdiam > star_sphere_squared_radius) star_sphere_squared_radius = sq_circumdiam; } @@ -446,7 +486,6 @@ private: } } //std::cerr << star_sphere_squared_radius << std::endl; - ++it_wp; } } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 1a130113f7e..6cd815f7e65 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -26,6 +26,8 @@ #include #include +#ifdef CGAL_TC_USE_NANOFLANN + #include "nanoflann.hpp" #include @@ -35,163 +37,26 @@ namespace CGAL { namespace Tangential_complex_ { -template -class Point_cloud -: public std::vector -{ -public: - typedef std::vector Base; - typedef Base Raw_container; - typedef Point_ Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - - //typedef typename Base::iterator iterator; - //typedef typename Base::const_iterator const_iterator; - - static const int AMB_DIM = Ambient_dimension::value; - - Point_cloud(Kernel const& k) - : m_k(k) - { - m_mins.fill(std::numeric_limits::max()); - m_maxs.fill(std::numeric_limits::min()); - } - - template - Point_cloud(InputIterator first, InputIterator last, Kernel const& k) - : Base(first, last), m_k(k) - { - m_mins.fill(std::numeric_limits::max()); - m_maxs.fill(std::numeric_limits::min()); - } - - void push_back(const Point &point, bool update_bbox = false) - { - Base::push_back(point); - - // Adjust bbox? - if (update_bbox) - { - for (int i = 0 ; i < AMB_DIM ; ++i) - { - if (point.get_param(i) < m_mins[i]) - m_mins[i] = point.get_param(i); - - if (point.get_param(i) > m_maxs[i]) - m_maxs[i] = point.get_param(i); - } - } - } - - void compute_bbox(bool only_if_not_already_done = false) - { - if (only_if_not_already_done && m_mins[0] != std::numeric_limits::max()) - return; - - // Reset - m_mins.fill(std::numeric_limits::max()); - m_maxs.fill(std::numeric_limits::min()); - - // Adjust bbox - for (const auto &point : *this) - { - typedef typename Kernel::Compute_coordinate_d Ccd; - const Ccd ccd = m_k.compute_coordinate_d_object(); - for (int i = 0 ; i < AMB_DIM ; ++i) - { - if (ccd(point, i) < m_mins[i]) - m_mins[i] =ccd(point, i); - - if (ccd(point, i) > m_maxs[i]) - m_maxs[i] = ccd(point, i); - } - } - } - - FT get_min(int dim) const - { - return m_mins[dim]; - } - - FT get_max(int dim) const - { - return m_maxs[dim]; - } - - FT bbox_diagonal() const - { - FT sqdiag = 0; - for (std::size_t i = 0 ; i < AMB_DIM ; ++i) - { - FT d = m_maxs[i] - m_mins[i]; - sqdiag += d*d; - } - return CGAL::sqrt(sqdiag); - } - - void recenter_points_around_origin( - bool compute_bbox_if_not_already_done = true) - { - // If the bounding box has not been computed already - if (m_mins[0] == std::numeric_limits::max()) - if (compute_bbox_if_not_already_done) - compute_bbox(); - else - return; - - // Compute centre of bbox - std::array transl_array; - for (std::size_t i = 0 ; i < AMB_DIM ; ++i) - transl_array[i] = -0.5*(m_maxs[i] + m_mins[i]); - - Point transl(transl_array); - -#ifdef CGAL_LINKED_WITH_TBB - tbb::parallel_for(tbb::blocked_range(0, size()), - [&]( const tbb::blocked_range& r ) - { - for (auto i = r.begin(); i != r.end(); ++i) -#else - for (auto i = 0; i != size(); ++i) -#endif - { - (*this)[i] += transl; - } -#ifdef CGAL_LINKED_WITH_TBB - }); -#endif - - } - -protected: - Kernel const& m_k; //!< A const ref to the kernel - // Bounding box - std::array m_mins; - std::array m_maxs; -}; - - -// And this is the "dataset to kd-tree" adaptor class: -template +// "dataset to kd-tree" adaptor class +template class Point_cloud_adaptator { public: - typedef typename Point_cloud_::Kernel Kernel; - typedef typename Point_cloud_::Point Point; - typedef typename Point_cloud_::FT FT; + typedef typename Point_container_::value_type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; /// The constructor that sets the data set source - Point_cloud_adaptator(Point_cloud_ &point_cloud, Kernel const& k) - : m_points(point_cloud), m_k(k) + Point_cloud_adaptator(Point_container_ &points, Kernel const& k) + : m_points(points), m_k(k) {} /// CRTP helper method - inline Point_cloud_ const& point_cloud() const + inline Point_container_ const& points() const { return m_points; } - inline Point_cloud_& point_cloud() + inline Point_container_& points() { return m_points; } @@ -199,7 +64,7 @@ public: // Must return the number of data points inline size_t kdtree_get_point_count() const { - return point_cloud().size(); + return m_points.size(); } // Returns the distance between the vector "p1[0:size-1]" @@ -208,7 +73,7 @@ public: 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, point_cloud()[idx_p2]); + return m_k.squared_distance_d_object()(sp, points()[idx_p2]); } // Returns the dim'th component of the idx'th point in the class: @@ -216,7 +81,7 @@ public: // 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()(point_cloud()[idx], dim); + return m_k.compute_coordinate_d_object()(points()[idx], dim); } // Optional bounding-box computation: return false to default to a standard @@ -228,13 +93,7 @@ public: template bool kdtree_get_bbox(Bbox &bb) const { - for (int i = 0 ; i < bb.size() ; ++i) - { - bb[i].low = m_points.get_min(i); - bb[i].high = m_points.get_max(i); - } - - return true; + return false; } Kernel const& kernel() const @@ -243,42 +102,40 @@ public: } protected: - Point_cloud_& m_points; //!< A ref to the data set origin + Point_container_& m_points; //!< A ref to the data set origin Kernel const& m_k; //!< A const ref to the kernel -}; // end of PointCloudAdaptor +}; -template +template class Point_cloud_data_structure { public: - typedef typename Point_cloud_::Kernel Kernel; - typedef typename Point_cloud_::Point Point; - typedef typename Point_cloud_::FT FT; + typedef typename Point_container_::value_type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; static const int AMB_DIM = Ambient_dimension::value; /// Constructor - Point_cloud_data_structure(Point_cloud_ &cloud, Kernel const& k) - : m_adaptor(cloud, k), + Point_cloud_data_structure(Point_container_ &points, Kernel const& k) + : m_adaptor(points, k), m_kd_tree(AMB_DIM, m_adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) { - cloud.compute_bbox(true); - //cloud.recenter_points_around_origin(); m_kd_tree.buildIndex(); } - Point_cloud_ &point_cloud() + /*Point_container_ &points() { - return m_adaptor.point_cloud(); + return m_adaptor.points(); } - const Point_cloud_ &point_cloud() const + const Point_container_ &points() const { - return m_adaptor.point_cloud(); - } + return m_adaptor.points(); + }*/ void query_ANN(const Point &sp, std::size_t k, @@ -332,7 +189,7 @@ public: } protected: - typedef Point_cloud_adaptator Adaptor; + typedef Point_cloud_adaptator Adaptor; typedef nanoflann::KDTreeSingleIndexAdaptor< nanoflann::L2_Simple_Adaptor , Adaptor, @@ -346,4 +203,95 @@ protected: } // namespace Tangential_complex_ } //namespace CGAL +#else // !CGAL_TC_USE_NANOFLANN => use CGAL Spatial searching + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace CGAL { +namespace Tangential_complex_ { + +template +class Point_cloud_data_structure +{ +public: + typedef typename Point_container_::value_type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + + typedef boost::tuple Point_and_idx; + typedef CGAL::Search_traits< + FT, Point, + typename Kernel::Cartesian_const_iterator_d, + typename Kernel::Construct_cartesian_const_iterator_d> Traits_base; + typedef CGAL::Search_traits_adapter, + Traits_base> STraits; + + typedef CGAL::Orthogonal_k_neighbor_search K_neighbor_search; + typedef typename K_neighbor_search::Tree Tree; + typedef typename K_neighbor_search::Distance Distance; + + static const int AMB_DIM = Ambient_dimension::value; + + /// Constructor + Point_cloud_data_structure(Point_container_ &points, Kernel const& k) + : m_points(points), + m_tree( + boost::make_zip_iterator(boost::make_tuple( + points.begin(), + boost::counting_iterator(0))), + boost::make_zip_iterator(boost::make_tuple( + points.end(), + boost::counting_iterator(points.size()))) ) + { + } + + /*Point_container_ &points() + { + return m_points; + } + + const Point_container_ &points() const + { + return m_points; + }*/ + + void query_ANN(const Point &sp, + unsigned int k, + size_t *neighbor_indices, + FT *squared_distance) const + { + // Initialize the search structure, and search all N points + K_neighbor_search search(m_tree, sp, k); + // report the N nearest neighbors and their distance + // This should sort all N points by increasing distance from origin + int i = 0; + for(K_neighbor_search::iterator it = search.begin(); + it != search.end(); ++it, ++i) + { + neighbor_indices[i] = boost::get<1>(it->first); + squared_distance[i] = it->second; + } + } + +protected: + Point_container_ const& m_points; + Tree m_tree; +}; + +} // namespace Tangential_complex_ +} //namespace CGAL + +#endif // CGAL_TC_USE_NANOFLANN + #endif // POINT_CLOUD_H \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index a05abf81622..004c5d7c309 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -23,8 +23,13 @@ #include +//========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING -const std::size_t NUM_POINTS_FOR_PCA = 30; +//========================= Strategy ========================================== +//#define CGAL_TC_USE_NANOFLANN + +//========================= Parameters ======================================== +const std::size_t NUM_POINTS_FOR_PCA = 50; #endif // CGAL_TC_CONFIG_H From 7ae85ffac3797048482ea208127f868019461819 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 11:16:05 +0200 Subject: [PATCH 031/269] More points! --- .../test/Tangential_complex/test_tangential_complex.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index a44ed2fe252..82626f91dde 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -1,3 +1,5 @@ +//#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 @@ -18,9 +20,9 @@ #endif #ifdef _DEBUG - const int NUM_POINTS = 50; + const int NUM_POINTS = 150; #else - const int NUM_POINTS = 5000; + const int NUM_POINTS = 50000; #endif template From 144856e4aec1cb87f0df8761a7035e239c67fa3f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 15:47:59 +0200 Subject: [PATCH 032/269] Add explicit forwarder to the Base_traits --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index cec297a9550..ce0e10e24fb 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -89,7 +89,7 @@ public: struct Construct_cartesian_const_iterator_d: public Base_traits::Construct_cartesian_const_iterator_d{ PointPropertyMap ppmap; - + Construct_cartesian_const_iterator_d(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_) :Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){} @@ -98,6 +98,12 @@ public: typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const { return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p),0); } + + 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{ From 6037445c5074609eca601fa0c13b8fd023ea02ab Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 16:30:46 +0200 Subject: [PATCH 033/269] Add a comment about the two new operators --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index ce0e10e24fb..c5d629a0358 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -99,6 +99,11 @@ public: typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const { 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); } From 43c8a1d0ba10cd5ad1d9828cbb6f294577bf9b6a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Sep 2014 17:00:00 +0200 Subject: [PATCH 034/269] Just stores indices in the search tree --- .../include/CGAL/Tangential_complex.h | 6 +- .../CGAL/Tangential_complex/Point_cloud.h | 67 +++++++++++++------ 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2cdb28ee3c4..00ade4c9b65 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -358,9 +358,8 @@ private: const int NUM_NEIGHBORS = 150; std::size_t nearest_nb[NUM_NEIGHBORS]; - FT squared_distance[NUM_NEIGHBORS]; m_points_ds.query_ANN( - center_pt, NUM_NEIGHBORS, nearest_nb, squared_distance); + center_pt, NUM_NEIGHBORS, nearest_nb); /*const int NUM_NEIGHBORS = 150; std::size_t nearest_nb[NUM_NEIGHBORS]; for (int ii = 0 ; ii < NUM_NEIGHBORS ; ++ii) @@ -509,9 +508,8 @@ private: Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); std::size_t neighbor_indices[NUM_POINTS_FOR_PCA]; - FT squared_distance[NUM_POINTS_FOR_PCA]; m_points_ds.query_ANN( - p, NUM_POINTS_FOR_PCA, neighbor_indices, squared_distance); + p, NUM_POINTS_FOR_PCA, neighbor_indices); //******************************* PCA ************************************* diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 6cd815f7e65..7452028d9c3 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -225,17 +225,16 @@ class Point_cloud_data_structure { public: typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; - typedef boost::tuple Point_and_idx; typedef CGAL::Search_traits< - FT, Point, + FT, Point, typename Kernel::Cartesian_const_iterator_d, typename Kernel::Construct_cartesian_const_iterator_d> Traits_base; - typedef CGAL::Search_traits_adapter, - Traits_base> STraits; + // 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 K_neighbor_search; typedef typename K_neighbor_search::Tree Tree; @@ -244,15 +243,13 @@ public: static const int AMB_DIM = Ambient_dimension::value; /// Constructor - Point_cloud_data_structure(Point_container_ &points, Kernel const& k) + Point_cloud_data_structure(Point_container_ const& points, Kernel const& k) : m_points(points), m_tree( - boost::make_zip_iterator(boost::make_tuple( - points.begin(), - boost::counting_iterator(0))), - boost::make_zip_iterator(boost::make_tuple( - points.end(), - boost::counting_iterator(points.size()))) ) + boost::counting_iterator(0), + boost::counting_iterator(points.size()), + Tree::Splitter(), + STraits((Point*)&(points[0])) ) { } @@ -265,22 +262,48 @@ public: { return m_points; }*/ - + + template void query_ANN(const Point &sp, unsigned int k, - size_t *neighbor_indices, - FT *squared_distance) const + IndexOutputIt indices_out) const { // Initialize the search structure, and search all N points - K_neighbor_search search(m_tree, sp, k); + // 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.1), true, + Distance_adapter >( + (Point*)&(m_points[0])) ); + // report the N nearest neighbors and their distance // This should sort all N points by increasing distance from origin - int i = 0; for(K_neighbor_search::iterator it = search.begin(); - it != search.end(); ++it, ++i) + it != search.end(); ++it) { - neighbor_indices[i] = boost::get<1>(it->first); - squared_distance[i] = it->second; + *indices_out++ = it->first; + } + } + + template + void query_ANN(const Point &sp, + unsigned int k, + IndexOutputIt indices_out, + DistanceOutputIt distances_out) 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.1), true, + Distance_adapter >( + (Point*)&(m_points[0])) ); + + // report the N nearest neighbors and their distance + // This should sort all N points by increasing distance from origin + for(K_neighbor_search::iterator it = search.begin(); + it != search.end(); ++it) + { + *indices_out++ = it->first; + *distances_out++ = it->second; } } From 7682e0265fc6586ab485675d0faa521087adcc92 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Sep 2014 10:40:35 +0200 Subject: [PATCH 035/269] Change Point_cloud interface + add incremental ANN --- .../include/CGAL/Tangential_complex.h | 39 +++++++---- .../CGAL/Tangential_complex/Point_cloud.h | 67 ++++++++++--------- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 00ade4c9b65..8d8f93f0a80 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -95,6 +95,10 @@ class Tangential_complex typedef std::vector Points; typedef Point_cloud_data_structure Points_ds; + typedef typename Points_ds::KNS_range KNS_range; + typedef typename Points_ds::KNS_iterator KNS_iterator; + typedef typename Points_ds::INS_range INS_range; + typedef typename Points_ds::INS_iterator INS_iterator; typedef std::pair Tr_and_VH; typedef typename std::vector Tr_container; @@ -336,8 +340,8 @@ private: Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; // Kernel functor & objects - //Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); // CJTODO: use that - Get_functor::type k_diff_pts(m_k); + Kernel::Difference_of_points_d k_diff_pts = + m_k.difference_of_points_d_object(); // Triangulation's traits functor & objects Tr_traits::Squared_distance_d sqdist = @@ -357,9 +361,8 @@ private: //*************************************************** const int NUM_NEIGHBORS = 150; - std::size_t nearest_nb[NUM_NEIGHBORS]; - m_points_ds.query_ANN( - center_pt, NUM_NEIGHBORS, nearest_nb); + KNS_range const& ins_range = + m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); /*const int NUM_NEIGHBORS = 150; std::size_t nearest_nb[NUM_NEIGHBORS]; for (int ii = 0 ; ii < NUM_NEIGHBORS ; ++ii) @@ -367,12 +370,18 @@ private: // First, compute the projected points std::vector projected_points; + std::vector nearest_nb; + nearest_nb.reserve(NUM_NEIGHBORS); FT max_squared_weight = 0; projected_points.reserve(NUM_NEIGHBORS); - for (std::size_t j = 0 ; j < NUM_NEIGHBORS ; ++j) + KNS_iterator nn_it = ins_range.begin(); + for (std::size_t j = 0 ; + j < NUM_NEIGHBORS && nn_it != ins_range.end() ; + ++j, ++nn_it) { // ith point = p, which is already inserted - std::size_t idx = nearest_nb[j]; + std::size_t idx = nn_it->first; + nearest_nb.push_back(idx); //if (idx != i) // CJTODO optim? { Tr_point wp = project_point(m_points[idx], center_pt, m_tangent_spaces[i]); @@ -507,19 +516,21 @@ private: Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - std::size_t neighbor_indices[NUM_POINTS_FOR_PCA]; - m_points_ds.query_ANN( - p, NUM_POINTS_FOR_PCA, neighbor_indices); + KNS_range kns_range = m_points_ds.query_ANN( + p, NUM_POINTS_FOR_PCA, false); //******************************* PCA ************************************* const int amb_dim = Ambient_dimension::value; // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); - for (int j = 0 ; j < NUM_POINTS_FOR_PCA ; ++j) + KNS_iterator nn_it = kns_range.begin(); + for (int j = 0 ; + j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + ++j, ++nn_it) { for (int i = 0 ; i < amb_dim ; ++i) - mat_points(j, i) = m_points[neighbor_indices[j]][i]; // CJTODO: Use kernel functor + mat_points(j, i) = m_points[nn_it->first][i]; // CJTODO: Use kernel functor } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -580,8 +591,8 @@ private: const Tangent_space_basis &ts) const { Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - //Kernel::Difference_of_points_d diff_points= m_k.difference_of_points_d_object(); // CJTODO: use that - Get_functor::type diff_points(m_k); + Kernel::Difference_of_points_d diff_points = + m_k.difference_of_points_d_object(); std::vector coords; // Ambiant-space coords of the projected point diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 7452028d9c3..8cc5e68fe19 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -206,6 +206,7 @@ protected: #else // !CGAL_TC_USE_NANOFLANN => use CGAL Spatial searching #include +#include #include #include #include @@ -213,6 +214,7 @@ protected: #include #include #include +#include #include #include @@ -239,6 +241,14 @@ public: typedef CGAL::Orthogonal_k_neighbor_search 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, Tree> + Incremental_neighbor_search; + typedef typename Incremental_neighbor_search::iterator INS_iterator; + typedef Incremental_neighbor_search INS_range; static const int AMB_DIM = Ambient_dimension::value; @@ -262,49 +272,42 @@ public: { return m_points; }*/ - - template - void query_ANN(const Point &sp, + + KNS_range query_ANN(const + Point &sp, unsigned int k, - IndexOutputIt indices_out) const + 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.1), true, - Distance_adapter >( - (Point*)&(m_points[0])) ); - - // report the N nearest neighbors and their distance - // This should sort all N points by increasing distance from origin - for(K_neighbor_search::iterator it = search.begin(); - it != search.end(); ++it) - { - *indices_out++ = it->first; - } + K_neighbor_search search( + m_tree, + sp, + k, + FT(0.0), + true, + Distance_adapter >( + (Point*)&(m_points[0])), + sorted); + + return search; } - - template - void query_ANN(const Point &sp, - unsigned int k, - IndexOutputIt indices_out, - DistanceOutputIt distances_out) const + + 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 - K_neighbor_search search(m_tree, sp, k, FT(0.1), true, - Distance_adapter >( + Incremental_neighbor_search search( + m_tree, + sp, + FT(0.0), + true, + Distance_adapter >( (Point*)&(m_points[0])) ); - - // report the N nearest neighbors and their distance - // This should sort all N points by increasing distance from origin - for(K_neighbor_search::iterator it = search.begin(); - it != search.end(); ++it) - { - *indices_out++ = it->first; - *distances_out++ = it->second; - } + + return search; } protected: From 4c2dbee682260251e99776545adeb1f3d29e362c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Sep 2014 10:43:35 +0200 Subject: [PATCH 036/269] Clean-up --- Tangential_complex/include/CGAL/Tangential_complex.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8d8f93f0a80..8fe02476d54 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -361,12 +361,8 @@ private: //*************************************************** const int NUM_NEIGHBORS = 150; - KNS_range const& ins_range = + KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); - /*const int NUM_NEIGHBORS = 150; - std::size_t nearest_nb[NUM_NEIGHBORS]; - for (int ii = 0 ; ii < NUM_NEIGHBORS ; ++ii) - nearest_nb[ii] = ii;*/ // First, compute the projected points std::vector projected_points; From 6b1658000b89da2d739b443a1a2f8182f30cd6d3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Sep 2014 15:56:55 +0200 Subject: [PATCH 037/269] Do not compute max_squared_weight, just use a big value instead + bugfix This needs to be improved (what big value should we use?). Bugfix: the weight stored inside the points are squared weights, but the computations were done like it was non-squared weights. --- .../include/CGAL/Tangential_complex.h | 138 +++++++++--------- 1 file changed, 68 insertions(+), 70 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8fe02476d54..aabd14c23da 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -100,20 +100,38 @@ class Tangential_complex typedef typename Points_ds::INS_range INS_range; typedef typename Points_ds::INS_iterator INS_iterator; - typedef std::pair Tr_and_VH; + // Store a local triangulation and a handle to its center vertex + struct Tr_and_VH + { + public: + Tr_and_VH() + : m_tr(NULL) {} + Tr_and_VH(int dim) + : m_tr(new Triangulation(dim)) {} + + ~Tr_and_VH() { delete m_tr; } + + Triangulation & construct_triangulation(int dim) + { + m_tr = new Triangulation(dim); + return tr(); + } + + Triangulation & tr() { return *m_tr; } + Triangulation const& tr() const { return *m_tr; } + + + Tr_vertex_handle const& center_vertex() const { return m_center_vertex; } + Tr_vertex_handle & center_vertex() { return m_center_vertex; } + + private: + Triangulation* m_tr; + Tr_vertex_handle m_center_vertex; + }; + typedef typename std::vector Tr_container; typedef typename std::vector TS_container; - // Stores the index of the original Point in the ambient space - /*struct Tr_point_with_index - : public Tr_point - { - Tr_point_with_index(const Tr_point &p, std::size_t i) - : Tr_point(p), index(i) {} - - std::size_t index; - };*/ - public: /// Constructor Tangential_complex(const Kernel &k = Kernel()) @@ -137,9 +155,7 @@ public: // We need to do that because we don't want the container to copy the // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations - m_triangulations.resize( - m_points.size(), - std::make_pair((Triangulation*)NULL, Tr_vertex_handle())); + m_triangulations.resize(m_points.size()); m_tangent_spaces.resize(m_points.size()); #ifdef CGAL_LINKED_WITH_TBB @@ -221,15 +237,15 @@ public: // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { - const Triangulation &tr = *it_tr->first; - Tr_vertex_handle center_vh = it_tr->second; + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); std::vector::const_iterator it_c = incident_cells.begin(); std::vector::const_iterator it_c_end= incident_cells.end(); - // For each triangulation + // For each cell for ( ; it_c != it_c_end ; ++it_c) { output << Intrinsic_dimension + 1 << " "; @@ -333,11 +349,10 @@ private: void compute_tangent_triangulation(std::size_t i) { //std::cerr << "***********************************************" << std::endl; - Triangulation *p_local_tr = - m_triangulations[i].first = - new Triangulation(Intrinsic_dimension); - const Tr_traits &local_tr_traits = p_local_tr->geom_traits(); - Tr_vertex_handle ¢er_vertex = m_triangulations[i].second; + Triangulation &local_tr = + m_triangulations[i].construct_triangulation(Intrinsic_dimension); + const Tr_traits &local_tr_traits = local_tr.geom_traits(); + Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects Kernel::Difference_of_points_d k_diff_pts = @@ -359,58 +374,40 @@ private: // Build a minimal triangulation in the tangent space // (we only need the star of p) //*************************************************** + + // CJTODO: replace 1000000 with something better + + // Insert p + Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(0, 0), + 1000000); + center_vertex = local_tr.insert(wp); + center_vertex->data() = i; const int NUM_NEIGHBORS = 150; - KNS_range ins_range = - m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); + //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); + INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); + + // While building the local triangulation, we keep the radius + // of the sphere centered at "center_vertex" and which contains all the + // circumspheres of the star of "center_vertex" + FT star_sphere_squared_radius = std::numeric_limits::max(); - // First, compute the projected points - std::vector projected_points; - std::vector nearest_nb; - nearest_nb.reserve(NUM_NEIGHBORS); - FT max_squared_weight = 0; - projected_points.reserve(NUM_NEIGHBORS); - KNS_iterator nn_it = ins_range.begin(); + INS_iterator nn_it = ins_range.begin(); for (std::size_t j = 0 ; j < NUM_NEIGHBORS && nn_it != ins_range.end() ; ++j, ++nn_it) { // ith point = p, which is already inserted - std::size_t idx = nn_it->first; - nearest_nb.push_back(idx); - //if (idx != i) // CJTODO optim? - { - Tr_point wp = project_point(m_points[idx], center_pt, m_tangent_spaces[i]); - projected_points.push_back(wp); - FT w = local_tr_traits.point_weight_d_object()(wp); - if (w > max_squared_weight) - max_squared_weight = w; - } - } - - // Now we can insert the points - - // Insert p - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(0, 0), - CGAL::sqrt(max_squared_weight)); - center_vertex = p_local_tr->insert(wp); - center_vertex->data() = i; - //std::cerr << "Inserted CENTER POINT of weight " << CGAL::sqrt(max_squared_weight) << std::endl; - - // While building the local triangulation, we keep the radius - // of the sphere centered at "center_vertex" and which contains all the - // circumspheres of the star of "center_vertex" - FT star_sphere_squared_radius = std::numeric_limits::max(); - // Insert the other points - for (std::size_t j = 0 ; j < NUM_NEIGHBORS ; ++j) - { - std::size_t point_idx = nearest_nb[j]; - Tr_point const& proj_pt = projected_points[j]; + std::size_t point_idx = nn_it->first; // ith point = p, which is already inserted if (point_idx != i) { + Tr_point proj_pt = project_point( + m_points[point_idx], center_pt, m_tangent_spaces[i]); + + // CJTODO: ŕ voir if (m_k.squared_distance_d_object()( center_pt, m_points[point_idx]) > star_sphere_squared_radius) @@ -420,29 +417,29 @@ private: FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); - FT w = CGAL::sqrt(max_squared_weight - squared_dist_to_tangent_plane); + FT w = 1000000 - squared_dist_to_tangent_plane; Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( drop_w(proj_pt), w); - Tr_vertex_handle vh = p_local_tr->insert_if_in_star(wp, center_vertex); - //Tr_vertex_handle vh = p_local_tr->insert(wp); + Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); + //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) { vh->data() = point_idx; // Let's recompute star_sphere_squared_radius - if (p_local_tr->current_dimension() >= Intrinsic_dimension) + if (local_tr.current_dimension() >= Intrinsic_dimension) { star_sphere_squared_radius = 0.; // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; - p_local_tr->incident_full_cells( + local_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); for (auto cell : incident_cells) // CJTODO C++11 { - if (p_local_tr->is_infinite(cell)) + if (local_tr.is_infinite(cell)) { star_sphere_squared_radius = std::numeric_limits::max(); break; @@ -493,14 +490,15 @@ private: } } + // CJTODO DEBUG //std::cerr << "\nChecking topology and geometry..." - // << (p_local_tr->is_valid(true) ? "OK.\n" : "Error.\n"); + // << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); // DEBUG: output the local mesh into an OFF file //std::stringstream sstr; //sstr << "data/local_tri_" << i << ".off"; //std::ofstream off_stream_tr(sstr.str()); - //CGAL::export_triangulation_to_off(off_stream_tr, *p_local_tr); + //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } Tangent_space_basis compute_tangent_space(const Point &p) const From e23ac137ce6d265541d745b9be65b983974b6828 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 16:04:24 +0200 Subject: [PATCH 038/269] No fixed NUM_NEIGHBORS anymore + improved code for projection Insert points until we find a point which is outside the sphere centered the "center vertex" and which contains all the circumspheres of the star of this "center vertex" --- .../include/CGAL/Tangential_complex.h | 90 +++++++++++-------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index aabd14c23da..aad9f85681d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -357,6 +357,8 @@ private: // Kernel functor & objects Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); + Kernel::Squared_distance_d k_sqdist = + m_k.squared_distance_d_object(); // Triangulation's traits functor & objects Tr_traits::Squared_distance_d sqdist = @@ -384,36 +386,33 @@ private: center_vertex = local_tr.insert(wp); center_vertex->data() = i; - const int NUM_NEIGHBORS = 150; + //const int NUM_NEIGHBORS = 150; //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); // While building the local triangulation, we keep the radius - // of the sphere centered at "center_vertex" and which contains all the + // of the sphere "star sphere" centered at "center_vertex" + // and which contains all the // circumspheres of the star of "center_vertex" FT star_sphere_squared_radius = std::numeric_limits::max(); - INS_iterator nn_it = ins_range.begin(); - for (std::size_t j = 0 ; - j < NUM_NEIGHBORS && nn_it != ins_range.end() ; - ++j, ++nn_it) + // Insert points until we find a point which is outside "star shere" + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) { - // ith point = p, which is already inserted - std::size_t point_idx = nn_it->first; + std::size_t neighbor_point_idx = nn_it->first; // ith point = p, which is already inserted - if (point_idx != i) + if (neighbor_point_idx != i) { - Tr_point proj_pt = project_point( - m_points[point_idx], center_pt, m_tangent_spaces[i]); + const Point &neighbor_pt = m_points[neighbor_point_idx]; - // CJTODO: ŕ voir - if (m_k.squared_distance_d_object()( - center_pt, m_points[point_idx]) - > star_sphere_squared_radius) - { - continue; - } + if (k_sqdist(center_pt, neighbor_pt) > star_sphere_squared_radius) + break; + + Tr_point proj_pt = project_point_and_compute_weight( + neighbor_pt, center_pt, m_tangent_spaces[i]); FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); @@ -426,7 +425,7 @@ private: //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) { - vh->data() = point_idx; + vh->data() = neighbor_point_idx; // Let's recompute star_sphere_squared_radius if (local_tr.current_dimension() >= Intrinsic_dimension) @@ -447,6 +446,14 @@ private: else { //********************************* + // We don't compute the circumsphere of the simplex in the + // local tangent plane since it would involve to take the + // weights of the points into account later + // (which is a problem since the ANN is performed on the + // points in the ambient dimension) + // Instead, we compute the subspace defined by the simplex + // and we compute the circumsphere in this subspace + // and we extract the diameter Tangent_space_basis tsb; tsb.reserve(Intrinsic_dimension); Point const& orig = m_points[cell->vertex(0)->data()]; @@ -457,11 +464,8 @@ private: } tsb = compute_gram_schmidt_basis(tsb, m_k); - // CJTODO: write a project_point which returns a Tr_bare_point - // and use it here - std::vector proj_pts; - std::vector::const_iterator it_p = proj_pts.begin(); - std::vector::const_iterator it_p_end = proj_pts.end(); + std::vector proj_pts; + proj_pts.reserve(Intrinsic_dimension + 1); // For each point p for (int ii = 0 ; ii <= Intrinsic_dimension ; ++ii) { @@ -470,16 +474,9 @@ private: } Tr_bare_point c = center_of_sphere( - boost::make_transform_iterator(proj_pts.begin(), drop_w), - boost::make_transform_iterator(proj_pts.end(), drop_w)); + proj_pts.begin(), proj_pts.end()); - //********************************* - //Tr_vertex_to_global_point v2gp(m_points); - //Point c = k_center_of_sphere( - // boost::make_transform_iterator(cell->vertices_begin(), v2gp), - // boost::make_transform_iterator(cell->vertices_end(), v2gp)); - //********************************* - FT sq_circumdiam = 4.*sqdist(c, drop_w(proj_pts[0])); + FT sq_circumdiam = 4.*sqdist(c, proj_pts[0]); if (sq_circumdiam > star_sphere_squared_radius) star_sphere_squared_radius = sq_circumdiam; } @@ -578,11 +575,34 @@ private: //return compute_gram_schmidt_basis(ts, m_k); */ } + + // Project the point in the tangent space + // The weight will be the squared distance between p and the projection of p + Tr_bare_point project_point(const Point &p, const Point &origin, + const Tangent_space_basis &ts) const + { + Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); + Kernel::Difference_of_points_d diff_points = + m_k.difference_of_points_d_object(); + + std::vector coords; + // Ambiant-space coords of the projected point + coords.reserve(Intrinsic_dimension); + for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) + { + // Compute the inner product p * ts[i] + Vector v = diff_points(p, origin); + FT coord = inner_pdct(v, ts[i]); + coords.push_back(coord); + } + + return Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()); + } // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p - Tr_point project_point(const Point &p, const Point &origin, - const Tangent_space_basis &ts) const + Tr_point project_point_and_compute_weight( + const Point &p, const Point &origin, const Tangent_space_basis &ts) const { Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); Kernel::Difference_of_points_d diff_points = From fcbc96fbf843cf060824f6df56d798f60447462b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 16:14:17 +0200 Subject: [PATCH 039/269] Rename WallClockTimer => Wall_clock_timer (internal timer using TBB timers if available) --- Mesh_3/demo/Mesh_3/Mesh_function.h | 2 +- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h | 6 +++--- Mesh_3/include/CGAL/Mesh_3/Mesher_3.h | 4 ++-- Mesh_3/include/CGAL/Mesh_3/Mesher_level.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h | 8 ++++---- Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h | 4 ++-- Tangential_complex/include/CGAL/Tangential_complex.h | 2 +- Triangulation_3/include/CGAL/Delaunay_triangulation_3.h | 4 ++-- Triangulation_3/include/CGAL/Regular_triangulation_3.h | 4 ++-- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Mesh_3/demo/Mesh_3/Mesh_function.h b/Mesh_3/demo/Mesh_3/Mesh_function.h index b9e8e8e7147..d6d6a5a7f01 100644 --- a/Mesh_3/demo/Mesh_3/Mesh_function.h +++ b/Mesh_3/demo/Mesh_3/Mesh_function.h @@ -204,7 +204,7 @@ launch() /*mesher_->initialize(); #ifdef CGAL_MESH_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif while ( ! mesher_->is_algorithm_done() && continue_ ) diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index ef7e7a5b96c..605c8acb4c9 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -2599,7 +2599,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 diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h index 80f52a349ab..f5fcea26540 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h @@ -311,7 +311,7 @@ private: #ifdef CGAL_MESH_3_PROFILING std::cerr << "Computing moves..."; - WallClockTimer t; + Wall_clock_timer t; #endif @@ -690,7 +690,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 @@ -898,7 +898,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 diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h index cea06d3fbf6..56e6ad56eec 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h @@ -320,7 +320,7 @@ Mesher_3::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 @@ -476,7 +476,7 @@ initialize() { #ifdef CGAL_MESH_3_PROFILING std::cerr << "Initializing... "; - WallClockTimer t; + Wall_clock_timer t; #endif //===================================== // Bounding box estimation diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h index 509be7abe19..79943874df4 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h @@ -194,7 +194,7 @@ protected: #ifdef CGAL_MESH_3_PROFILING protected: - WallClockTimer m_timer; + Wall_clock_timer m_timer; #endif public: diff --git a/Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h b/Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h index eb436c93af3..32c707f9d9e 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h +++ b/Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h @@ -28,10 +28,10 @@ // TBB timers #ifdef CGAL_LINKED_WITH_TBB #include - 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 - struct WallClockTimer + struct Wall_clock_timer { CGAL::Real_timer t; - WallClockTimer() + Wall_clock_timer() { t.start(); } diff --git a/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h b/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h index 776cd4f4796..8b6e17cb96b 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Refine_cells_3.h @@ -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 diff --git a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h index 1bdcc3b66d9..a58627b667a 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h @@ -882,7 +882,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 diff --git a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h index fd3847f41ec..74fb202daf1 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h +++ b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h @@ -799,7 +799,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) diff --git a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h index 7f6a06f9ed5..cf135a4c08d 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h +++ b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h @@ -449,7 +449,7 @@ public: // methods operator()(Visitor visitor = Visitor()) { #ifdef CGAL_MESH_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif Mesh_optimization_return_code ret = @@ -950,7 +950,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); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index aad9f85681d..728fc5ef8df 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -149,7 +149,7 @@ public: void compute_tangential_complex() { #ifdef CGAL_TC_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif // We need to do that because we don't want the container to copy the diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h index 427bb375010..08461059f56 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h @@ -281,7 +281,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(); @@ -622,7 +622,7 @@ public: size_type n = number_of_vertices(); #ifdef CGAL_TRIANGULATION_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif // Parallel diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index cd47e98642b..8ffbe734f11 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -208,7 +208,7 @@ namespace CGAL { #endif #ifdef CGAL_TRIANGULATION_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif size_type n = number_of_vertices(); @@ -618,7 +618,7 @@ namespace CGAL { size_type n = number_of_vertices(); #ifdef CGAL_TRIANGULATION_3_PROFILING - WallClockTimer t; + Wall_clock_timer t; #endif // Parallel From 3cf1b89fe04d1b3eb0b6e69af1be1a8ef916136e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 17:04:21 +0200 Subject: [PATCH 040/269] Improved profiling --- .../include/CGAL/Tangential_complex.h | 4 +++- .../include/CGAL/Tangential_complex/config.h | 2 +- .../test_tangential_complex.cpp | 19 ++++++++++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 728fc5ef8df..5ba9c5db4d8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -34,7 +34,9 @@ #include #include -#include +#ifdef CGAL_TC_PROFILING +# include +#endif #include // CJTODO TEMP diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 004c5d7c309..a83560acd60 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -24,7 +24,7 @@ #include //========================= Debugging & profiling ============================= -#define CGAL_TC_PROFILING +//#define CGAL_TC_PROFILING //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 82626f91dde..5d0e344833b 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -77,6 +78,8 @@ int main() # endif #endif + Wall_clock_timer t; + //std::vector points = generate_points_on_sphere(3.0); std::vector points = generate_points_on_klein_bottle(4., 3.); @@ -84,14 +87,28 @@ int main() Kernel, INTRINSIC_DIMENSION, CGAL::Parallel_tag> tc(points.begin(), points.end()); + double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); - + double computation_time = t.elapsed(); t.reset(); + std::stringstream output_filename; output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); tc.export_to_off(off_stream); + double export_time = t.elapsed(); t.reset(); + + std::cerr << std::endl + << "================================================" << 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: " << export_time << std::endl + << "================================================" << std::endl + << std::endl; return 0; } \ No newline at end of file From 164032d1fee707470882290636b5b85e069afadc Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 17:04:54 +0200 Subject: [PATCH 041/269] Let's use some negative weights --- Tangential_complex/include/CGAL/Tangential_complex.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5ba9c5db4d8..48b3c44269f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -378,13 +378,11 @@ private: // Build a minimal triangulation in the tangent space // (we only need the star of p) //*************************************************** - - // CJTODO: replace 1000000 with something better // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(0, 0), - 1000000); + 0); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -418,7 +416,7 @@ private: FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); - FT w = 1000000 - squared_dist_to_tangent_plane; + FT w = -squared_dist_to_tangent_plane; Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( drop_w(proj_pt), w); From 8c677a8f5f89e11d675e24246043c63508ac512b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 24 Sep 2014 18:45:15 +0200 Subject: [PATCH 042/269] Show inconsistencies in red --- .../include/CGAL/Tangential_complex.h | 63 +++++++++++++++++-- .../test_tangential_complex.cpp | 26 ++++++-- 2 files changed, 80 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 48b3c44269f..8d6d1a99440 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -183,7 +183,8 @@ public: #endif } - std::ostream &export_to_off(std::ostream & os) + std::ostream &export_to_off(std::ostream & os, + bool color_inconsistencies = false) { const int ambient_dim = Ambient_dimension::value; if (ambient_dim < 2) @@ -251,13 +252,32 @@ public: for ( ; it_c != it_c_end ; ++it_c) { output << Intrinsic_dimension + 1 << " "; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - output << (*it_c)->vertex(i)->data() << " "; + + if (color_inconsistencies) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + output << data << " "; + c.insert(data); + } + if (is_simplex_consistent(c)) + output << "200 200 200"; + else + output << "255 0 0"; + } + else + { + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + output << (*it_c)->vertex(i)->data() << " "; + } + output << std::endl; ++num_cells; } } - + os << "OFF \n" << m_points.size() << " " << num_cells << " " @@ -631,6 +651,41 @@ private: m_k.squared_distance_d_object()(p, projected_pt)); } + // A simplex here is a list of point indices + bool is_simplex_consistent(std::set const& simplex) + { + // Check if the simplex is in the stars of all its vertices + std::set::const_iterator it_point_idx = simplex.begin(); + // For each point + for ( ; it_point_idx != simplex.end() ; ++it_point_idx) + { + std::size_t point_idx = *it_point_idx; + Triangulation const& tr = m_triangulations[point_idx].tr(); + Tr_vertex_handle center_vh = m_triangulations[point_idx].center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + bool found = false; + for ( ; !found && it_c != it_c_end ; ++it_c) + { + std::set cell; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + cell.insert((*it_c)->vertex(i)->data()); + if (cell == simplex) + found = true; + } + + if (!found) + return false; + } + + return true; + } + private: const Kernel m_k; Points m_points; diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 5d0e344833b..ef2b13168b1 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -23,7 +23,7 @@ #ifdef _DEBUG const int NUM_POINTS = 150; #else - const int NUM_POINTS = 50000; + const int NUM_POINTS = 10000; #endif template @@ -39,18 +39,34 @@ std::vector generate_points_on_sphere(double radius) // a = big radius, b = small radius template -std::vector generate_points_on_klein_bottle(double a, double b) +std::vector generate_points_on_klein_bottle( + double a, double b, bool uniform = false) { typedef typename CGAL::Kernel_traits::type Kernel; typedef typename Kernel::FT FT; CGAL::Random rng; + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + std::vector points; points.reserve(NUM_POINTS); for (int i = 0 ; i != NUM_POINTS ; ++i) { - FT u = rng.get_double(0, 6.2832); - FT v = rng.get_double(0, 6.2832); + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int 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); + } points.push_back(Kernel().construct_point_d_object()( (a + b*cos(v))*cos(u), (a + b*cos(v))*sin(u), @@ -96,7 +112,7 @@ int main() output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); - tc.export_to_off(off_stream); + tc.export_to_off(off_stream, true); double export_time = t.elapsed(); t.reset(); std::cerr << std::endl From f6a4576d19afeff9081a76a7afa7fe32e6189e4b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 2 Oct 2014 11:30:33 +0200 Subject: [PATCH 043/269] Remove the use of Kernel_traits + bug fix in OFF export --- .../include/CGAL/Tangential_complex.h | 14 ++++++++++++-- .../CGAL/Tangential_complex/Point_cloud.h | 17 ++++++++--------- .../include/CGAL/Tangential_complex/utilities.h | 1 - .../Regular_triangulation_euclidean_traits.h | 1 - 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8d6d1a99440..6be99ecce1a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -96,7 +96,7 @@ class Tangential_complex typedef std::vector Tangent_space_basis; typedef std::vector Points; - typedef Point_cloud_data_structure Points_ds; + typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; typedef typename Points_ds::INS_range INS_range; @@ -251,6 +251,9 @@ public: // For each cell for ( ; it_c != it_c_end ; ++it_c) { + if (tr.is_infinite(*it_c)) // Don't export infinite cells + continue; + output << Intrinsic_dimension + 1 << " "; if (color_inconsistencies) @@ -263,7 +266,7 @@ public: c.insert(data); } if (is_simplex_consistent(c)) - output << "200 200 200"; + output << "128 128 128"; else output << "255 0 0"; } @@ -520,6 +523,13 @@ private: Tangent_space_basis compute_tangent_space(const Point &p) const { + /*Tangent_space_basis ts; + ts.reserve(Intrinsic_dimension); + ts.push_back(Vector(1,0,0)); + ts.push_back(Vector(0,1,0)); + + return ts;*/ + // Kernel functors Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 8cc5e68fe19..ec6b6932b5d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -23,7 +23,6 @@ #include #include -#include #include #ifdef CGAL_TC_USE_NANOFLANN @@ -38,11 +37,11 @@ namespace CGAL { namespace Tangential_complex_ { // "dataset to kd-tree" adaptor class -template +template class Point_cloud_adaptator { public: - typedef typename Point_container_::value_type Point; + typedef typename Point_container_::value_type Point; typedef typename CGAL::Kernel_traits::type Kernel; typedef typename Kernel::FT FT; @@ -107,12 +106,12 @@ protected: }; -template +template class Point_cloud_data_structure { public: - typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Point_container_::value_type Point; + typedef typename K Kernel; typedef typename Kernel::FT FT; static const int AMB_DIM = Ambient_dimension::value; @@ -189,7 +188,7 @@ public: } protected: - typedef Point_cloud_adaptator Adaptor; + typedef Point_cloud_adaptator Adaptor; typedef nanoflann::KDTreeSingleIndexAdaptor< nanoflann::L2_Simple_Adaptor , Adaptor, @@ -222,12 +221,12 @@ protected: namespace CGAL { namespace Tangential_complex_ { -template +template class Point_cloud_data_structure { public: typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename K Kernel; typedef typename Kernel::FT FT; typedef CGAL::Search_traits< diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index f58ace643b3..be1a3febd20 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -22,7 +22,6 @@ #define CGAL_TC_UTILITIES_H #include -#include #include #include diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index 3f5a9630a85..c5eb0248859 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -24,7 +24,6 @@ #include #include #include -#include #include From 50679b358c33e63032ad7f3a6de2bc8970d3c7d3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 2 Oct 2014 19:05:45 +0200 Subject: [PATCH 044/269] Use a boost optional for "star sphere" + export normals for 3D surface meshes --- .../include/CGAL/Tangential_complex.h | 56 ++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6be99ecce1a..be46c2ac26d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -55,6 +56,8 @@ # include #endif +//#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) + namespace CGAL { using namespace Tangential_complex_; @@ -133,6 +136,9 @@ class Tangential_complex typedef typename std::vector Tr_container; typedef typename std::vector TS_container; +#ifdef CGAL_TC_EXPORT_NORMALS + typedef typename std::vector Normals; +#endif public: /// Constructor @@ -159,6 +165,9 @@ public: // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); m_tangent_spaces.resize(m_points.size()); +#ifdef CGAL_TC_EXPORT_NORMALS + m_normals.resize(m_points.size()); +#endif #ifdef CGAL_LINKED_WITH_TBB // Parallel @@ -218,7 +227,10 @@ public: std::stringstream output; //******** VERTICES ************ - + +#ifdef CGAL_TC_EXPORT_NORMALS + Normals::const_iterator it_n = m_normals.begin(); +#endif Points::const_iterator it_p = m_points.begin(); Points::const_iterator it_p_end = m_points.end(); // For each point p @@ -229,6 +241,13 @@ public: output << (*it_p)[i] << " "; if (i == 2) output << "0"; + +#ifdef CGAL_TC_EXPORT_NORMALS + for (i = 0 ; i < num_coords ; ++i) + output << " " << (*it_n)[i]; + ++it_n; +#endif + output << std::endl; } @@ -280,6 +299,10 @@ public: ++num_cells; } } + +#ifdef CGAL_TC_EXPORT_NORMALS + os << "N"; +#endif os << "OFF \n" << m_points.size() << " " @@ -395,7 +418,11 @@ private: // Estimate the tangent space const Point ¢er_pt = m_points[i]; +#ifdef CGAL_TC_EXPORT_NORMALS + m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); +#else m_tangent_spaces[i] = compute_tangent_space(center_pt); +#endif //*************************************************** // Build a minimal triangulation in the tangent space @@ -417,7 +444,7 @@ private: // of the sphere "star sphere" centered at "center_vertex" // and which contains all the // circumspheres of the star of "center_vertex" - FT star_sphere_squared_radius = std::numeric_limits::max(); + boost::optional star_sphere_squared_radius; // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; @@ -431,7 +458,8 @@ private: { const Point &neighbor_pt = m_points[neighbor_point_idx]; - if (k_sqdist(center_pt, neighbor_pt) > star_sphere_squared_radius) + if (star_sphere_squared_radius + && k_sqdist(center_pt, neighbor_pt) > *star_sphere_squared_radius) break; Tr_point proj_pt = project_point_and_compute_weight( @@ -453,7 +481,7 @@ private: // Let's recompute star_sphere_squared_radius if (local_tr.current_dimension() >= Intrinsic_dimension) { - star_sphere_squared_radius = 0.; + star_sphere_squared_radius = 0; // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; local_tr.incident_full_cells( @@ -463,7 +491,7 @@ private: { if (local_tr.is_infinite(cell)) { - star_sphere_squared_radius = std::numeric_limits::max(); + star_sphere_squared_radius = boost::none; break; } else @@ -500,7 +528,8 @@ private: proj_pts.begin(), proj_pts.end()); FT sq_circumdiam = 4.*sqdist(c, proj_pts[0]); - if (sq_circumdiam > star_sphere_squared_radius) + if (!star_sphere_squared_radius + || sq_circumdiam > *star_sphere_squared_radius) star_sphere_squared_radius = sq_circumdiam; } } @@ -521,7 +550,11 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } - Tangent_space_basis compute_tangent_space(const Point &p) const + Tangent_space_basis compute_tangent_space(const Point &p +#ifdef CGAL_TC_EXPORT_NORMALS + , Vector *p_normal +#endif + ) const { /*Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); @@ -567,6 +600,12 @@ private: eig.eigenvectors().col(i).data(), eig.eigenvectors().col(i).data() + amb_dim)); } +#ifdef CGAL_TC_EXPORT_NORMALS + *p_normal = constr_vec( + amb_dim, + eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data(), + eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data() + amb_dim); +#endif //************************************************************************* @@ -703,6 +742,9 @@ private: TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations // and their center vertex +#ifdef CGAL_TC_EXPORT_NORMALS + Normals m_normals; +#endif }; // /class Tangential_complex From 4c6c0be37f4101cfca11718470bf610bb1ea54d7 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 13 Oct 2014 17:11:43 +0200 Subject: [PATCH 045/269] Unofficial Epeck_d (exact and very slow) for testing purposes. --- NewKernel_d/include/CGAL/Epeck_d.h | 53 ++++++++++++++++++++++++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 36 +++++++++------- 2 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 NewKernel_d/include/CGAL/Epeck_d.h diff --git a/NewKernel_d/include/CGAL/Epeck_d.h b/NewKernel_d/include/CGAL/Epeck_d.h new file mode 100644 index 00000000000..52bce84ca3f --- /dev/null +++ b/NewKernel_d/include/CGAL/Epeck_d.h @@ -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 +#include +#include +#include + + +namespace CGAL { +#define CGAL_BASE \ + Cartesian_base_d::Type, Dim> +template +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, \ + Epeck_d > > +template +struct Epeck_d +: CGAL_BASE +{ + CGAL_CONSTEXPR Epeck_d(){} + CGAL_CONSTEXPR Epeck_d(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE +} +#endif diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 0635bc4cc3f..01c63d26ac7 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -13,6 +13,7 @@ #include #include #include +#include //typedef CGAL::Cartesian_base_d > K0; //typedef CGAL::Cartesian_base_d > KA; @@ -185,11 +186,12 @@ void test2(){ CGAL_USE(cli); CGAL_USE(cr); CGAL_USE(cib); + 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}; @@ -203,8 +205,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; @@ -253,9 +255,9 @@ void test2(){ assert(v.size()==1); assert(lr(tab3+0,tab3+2)==1); H h=ch(tab2+1,tab2+3); - 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); @@ -312,20 +314,23 @@ 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 Sp un1; CGAL_USE(un1); H un2; CGAL_USE(un2); S un3; CGAL_USE(un3); @@ -418,6 +423,7 @@ void test3(){ SD sd Kinit(squared_distance_d_object); PD pd Kinit(point_dimension_d_object); AI ai Kinit(affinely_independent_d_object); + using std::abs; P a; // Triangulation needs this :-( a=cp(2,3,4); assert(pd(a)==3); @@ -441,7 +447,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) << ' '; From b5bee8fbfc95a9ea6581c909ed419b3224fa11e6 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Oct 2014 16:08:11 +0200 Subject: [PATCH 046/269] Fix a bug in the computation of the weights + better export and debug code + remove the uses of Ambient_dimension + improved test + Comments clean-up --- .../include/CGAL/Tangential_complex.h | 404 +++++++++++++----- .../CGAL/Tangential_complex/Point_cloud.h | 10 +- .../include/CGAL/Tangential_complex/config.h | 1 + .../CGAL/Tangential_complex/utilities.h | 17 +- .../test_tangential_complex.cpp | 126 ++++-- 5 files changed, 409 insertions(+), 149 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index be46c2ac26d..909ee277852 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -31,8 +31,10 @@ #include #include #include +#include #include #include +#include #ifdef CGAL_TC_PROFILING # include @@ -47,10 +49,12 @@ #include #include +#include #include #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB # include @@ -141,15 +145,12 @@ class Tangential_complex #endif public: - /// Constructor - Tangential_complex(const Kernel &k = Kernel()) - : m_k(k){} /// Constructor for a range of points template Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), m_points(first, last), m_points_ds(m_points, k) {} + : m_k(k), m_points(first, last), m_points_ds(m_points) {} /// Destructor ~Tangential_complex() {} @@ -173,7 +174,6 @@ public: // Parallel if (boost::is_convertible::value) { - // Apply moves in triangulation tbb::parallel_for(tbb::blocked_range(0, m_points.size()), Compute_tangent_triangulation(*this) ); @@ -192,10 +192,16 @@ public: #endif } - std::ostream &export_to_off(std::ostream & os, - bool color_inconsistencies = false) + std::ostream &export_to_off( + std::ostream & os, + bool color_inconsistencies = false, + std::set > const* excluded_simplices = NULL, + bool show_excluded_vertices_in_color = false) { - const int ambient_dim = Ambient_dimension::value; + if (m_points.empty()) + return os; + + const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); if (ambient_dim < 2) { std::cerr << "Error: export_to_off => ambient dimension should be >= 2." @@ -211,8 +217,6 @@ public: << std::endl; } - int num_coords = min(ambient_dim, 3); - if (Intrinsic_dimension < 1 || Intrinsic_dimension > 3) { std::cerr << "Error: export_to_off => intrinsic dimension should be " @@ -225,80 +229,11 @@ public: } std::stringstream output; - - //******** VERTICES ************ - -#ifdef CGAL_TC_EXPORT_NORMALS - Normals::const_iterator it_n = m_normals.begin(); -#endif - Points::const_iterator it_p = m_points.begin(); - Points::const_iterator it_p_end = m_points.end(); - // For each point p - for ( ; it_p != it_p_end ; ++it_p) - { - int i = 0; - for ( ; i < num_coords ; ++i) - output << (*it_p)[i] << " "; - if (i == 2) - output << "0"; - -#ifdef CGAL_TC_EXPORT_NORMALS - for (i = 0 ; i < num_coords ; ++i) - output << " " << (*it_n)[i]; - ++it_n; -#endif - - output << std::endl; - } - - //******** CELLS ************ - - std::size_t num_cells = 0; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); - // For each triangulation - for ( ; it_tr != it_tr_end ; ++it_tr) - { - Triangulation const& tr = it_tr->tr(); - Tr_vertex_handle center_vh = it_tr->center_vertex(); - - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); - // For each cell - for ( ; it_c != it_c_end ; ++it_c) - { - if (tr.is_infinite(*it_c)) // Don't export infinite cells - continue; - - output << Intrinsic_dimension + 1 << " "; - - if (color_inconsistencies) - { - std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - { - std::size_t data = (*it_c)->vertex(i)->data(); - output << data << " "; - c.insert(data); - } - if (is_simplex_consistent(c)) - output << "128 128 128"; - else - output << "255 0 0"; - } - else - { - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - output << (*it_c)->vertex(i)->data() << " "; - } - - output << std::endl; - ++num_cells; - } - } + std::size_t num_cells, num_vertices; + export_vertices_to_off(output, num_vertices); + export_simplices_to_off( + output, num_cells, color_inconsistencies, + excluded_simplices, show_excluded_vertices_in_color); #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; @@ -312,6 +247,121 @@ public: return os; } + + bool check_if_all_simplices_are_in_the_ambient_delaunay( + std::set > * incorrect_simplices = NULL) + { + if (m_points.empty()) + return true; + + const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); + typedef typename Delaunay_triangulation< + Kernel, + Triangulation_data_structure + < + Kernel::Dimension, + Triangulation_vertex + > + > DT; + typedef typename DT::Vertex_handle DT_VH; + typedef typename DT::Finite_full_cell_const_iterator FFC_it; + typedef std::set Indexed_simplex; + + //------------------------------------------------------------------------- + // Build the ambient Delaunay triangulation + // Then save its simplices into "amb_dt_simplices" + //------------------------------------------------------------------------- + + DT ambient_dt(ambient_dim); + std::size_t i = 0; + for (Point const& p : m_points) // CJTODO C++11 + { + DT_VH vh = ambient_dt.insert(p); + vh->data() = i; + ++i; + } + + std::set amb_dt_simplices; + + for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; + cit != ambient_dt.finite_full_cells_end() ; ++cit ) + { + CGAL::Combination_enumerator combi( + Intrinsic_dimension + 1, 0, ambient_dim + 1); + + for ( ; !combi.finished() ; ++combi) + { + Indexed_simplex simplex; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + simplex.insert(cit.base()->vertex(combi[i])->data()); + + amb_dt_simplices.insert(simplex); + } + } + + //------------------------------------------------------------------------- + // Parse the TC and save its simplices into "stars_simplices" + //------------------------------------------------------------------------- + + std::set stars_simplices; + + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + if (tr.is_infinite(*it_c)) + { + std::cerr << "Warning: infinite cell in star" << std::endl; + continue; + } + Indexed_simplex simplex; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + simplex.insert((*it_c)->vertex(i)->data()); + + stars_simplices.insert(simplex); + } + } + + //------------------------------------------------------------------------- + // Check if simplices of "stars_simplices" are all in "amb_dt_simplices" + //------------------------------------------------------------------------- + + std::set diff; + if (!incorrect_simplices) + incorrect_simplices = &diff; + set_difference(stars_simplices.begin(), stars_simplices.end(), + amb_dt_simplices.begin(), amb_dt_simplices.end(), + std::inserter(*incorrect_simplices, + incorrect_simplices->begin()) ); + + if (!incorrect_simplices->empty()) + { + std::cerr + << "ERROR check_if_all_simplices_are_in_the_ambient_delaunay:" + << std::endl + << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << std::endl + << " Number of unique simplices in TC stars: " << stars_simplices.size() + << std::endl + << " Number of wrong simplices: " << incorrect_simplices->size() + << std::endl; + return false; + } + else + return true; + } private: @@ -556,13 +606,6 @@ private: #endif ) const { - /*Tangent_space_basis ts; - ts.reserve(Intrinsic_dimension); - ts.push_back(Vector(1,0,0)); - ts.push_back(Vector(0,1,0)); - - return ts;*/ - // Kernel functors Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); @@ -574,8 +617,8 @@ private: p, NUM_POINTS_FOR_PCA, false); //******************************* PCA ************************************* - - const int amb_dim = Ambient_dimension::value; + + const int amb_dim = m_k.point_dimension_d_object()(p); // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); KNS_iterator nn_it = kns_range.begin(); @@ -584,7 +627,7 @@ private: ++j, ++nn_it) { for (int i = 0 ; i < amb_dim ; ++i) - mat_points(j, i) = m_points[nn_it->first][i]; // CJTODO: Use kernel functor + mat_points(j, i) = CGAL::to_double(m_points[nn_it->first][i]); // CJTODO: Use kernel functor } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -610,7 +653,7 @@ private: //************************************************************************* //Vector n = m_k.point_to_vector_d_object()(p); - //n = scaled_vec(n, 1./sqrt(sqlen(n))); + //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; return compute_gram_schmidt_basis(ts, m_k); @@ -623,18 +666,20 @@ private: p[0] * t1[1] - p[1] * t1[0]); // Normalize t1 and t2 - Kernel::Scaled_vector_d scale = m_k.scaled_vector_d_object(); + Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); - ts.push_back(scale(t1, 1./CGAL::sqrt(sqlen(t1)))); - ts.push_back(scale(t2, 1./CGAL::sqrt(sqlen(t2)))); + ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); + ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); - return ts; + return ts;*/ + /* // Alternative code (to be used later) //Vector n = m_k.point_to_vector_d_object()(p); - //n = scaled_vec(n, 1./sqrt(sqlen(n))); + //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //Vector t1(12., 15., 65.); //Vector t2(32., 5., 85.); //Tangent_space_basis ts; @@ -673,29 +718,43 @@ private: Tr_point project_point_and_compute_weight( const Point &p, const Point &origin, const Tangent_space_basis &ts) const { + const int point_dim = m_k.point_dimension_d_object()(p); Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); + Kernel::Construct_cartesian_const_iterator_d ccci = + m_k.construct_cartesian_const_iterator_d_object(); + + Vector v = diff_points(p, origin); std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(origin.cartesian_begin(), origin.cartesian_end()); // CJTODO: use kernel functors? + std::vector p_proj(ccci(origin), ccci(origin, 0)); coords.reserve(Intrinsic_dimension); for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) { // Compute the inner product p * ts[i] - Vector v = diff_points(p, origin); FT coord = inner_pdct(v, ts[i]); coords.push_back(coord); // p_proj += coord * v; - for (int j = 0 ; j < Ambient_dimension::value ; ++j) - p_proj[i] += coord * ts[i][j]; + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += coord * ts[i][j]; } - Point projected_pt(Ambient_dimension::value, - p_proj.begin(), p_proj.end()); - return Tr_point( + // CJTODO TEMP: test it + /*Kernel::Construct_vector_d c_vec = m_k.construct_vector_d_object(); + Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + Point proj_pt = origin; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + Vector base_i = c_vec(point_dim, ts[i].begin(), ts[i].end()); + FT coef = inner_pdct(v, base_i); + proj_pt = proj_pt + scaled_vec(base_i, coef); + }*/ + + Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); + return Tr_point( // CJTODO: use kernel constructions Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), m_k.squared_distance_d_object()(p, projected_pt)); } @@ -735,6 +794,137 @@ private: return true; } + std::ostream &export_vertices_to_off( + std::ostream & os, std::size_t &num_vertices) + { + if (m_points.empty()) + { + num_vertices = 0; + return os; + } + + const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); + int num_coords = min(ambient_dim, 3); +#ifdef CGAL_TC_EXPORT_NORMALS + Normals::const_iterator it_n = m_normals.begin(); +#endif + Points::const_iterator it_p = m_points.begin(); + Points::const_iterator it_p_end = m_points.end(); + // For each point p + for ( ; it_p != it_p_end ; ++it_p) + { + int i = 0; + for ( ; i < num_coords ; ++i) + os << CGAL::to_double((*it_p)[i]) << " "; // CJTODO: use kernel functors, not [] + if (i == 2) + os << "0"; + +#ifdef CGAL_TC_EXPORT_NORMALS + for (i = 0 ; i < num_coords ; ++i) + os << " " << CGAL::to_double((*it_n)[i]); // CJTODO: use kernel functors, not [] + ++it_n; +#endif + + os << std::endl; + } + + num_vertices = m_points.size(); + return os; + } + + std::ostream &export_simplices_to_off( + std::ostream & os, std::size_t &num_cells, + bool color_inconsistencies = false, + std::set > const* excluded_simplices = NULL, + bool show_excluded_vertices_in_color = false) + { + num_cells = 0; + std::size_t num_inconsistent_simplices = 0; + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + + // Color for this star + std::stringstream color; + //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; + color << 128 << " " << 128 << " " << 128; + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + if (tr.is_infinite(*it_c)) // Don't export infinite cells + continue; + + if (color_inconsistencies || excluded_simplices) + { + std::set c; + std::stringstream sstr_c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + sstr_c << data << " "; + c.insert(data); + } + + bool excluded = + (excluded_simplices + && excluded_simplices->find(c) != excluded_simplices->end()); + + if (!excluded) + { + os << Intrinsic_dimension + 1 << " " << sstr_c.str() << " "; + if (color_inconsistencies && is_simplex_consistent(c)) + os << color.str(); + else + { + os << "255 0 0"; + ++num_inconsistent_simplices; + } + ++num_cells; + } + else if (show_excluded_vertices_in_color) + { + os << Intrinsic_dimension + 1 << " " + << sstr_c.str() << " " + << "0 0 255"; + ++num_cells; + } + } + else + { + os << Intrinsic_dimension + 1 << " "; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + os << (*it_c)->vertex(i)->data() << " "; + ++num_cells; + } + + os << std::endl; + } + } + +#ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "================================================" << std::endl + << "Export to OFF:\n" + << " * Total number of simplices in stars (incl. duplicates): " + << num_cells << std::endl + << " * Number of inconsistent simplices in stars (incl. duplicates): " + << num_inconsistent_simplices << std::endl + << "================================================" << std::endl; +#endif + + return os; + } + private: const Kernel m_k; Points m_points; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index ec6b6932b5d..a8f53b8c24c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -114,7 +114,7 @@ public: typedef typename K Kernel; typedef typename Kernel::FT FT; - static const int AMB_DIM = Ambient_dimension::value; + static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar /// Constructor Point_cloud_data_structure(Point_container_ &points, Kernel const& k) @@ -249,10 +249,10 @@ public: typedef typename Incremental_neighbor_search::iterator INS_iterator; typedef Incremental_neighbor_search INS_range; - static const int AMB_DIM = Ambient_dimension::value; + static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar /// Constructor - Point_cloud_data_structure(Point_container_ const& points, Kernel const& k) + Point_cloud_data_structure(Point_container_ const& points) : m_points(points), m_tree( boost::counting_iterator(0), @@ -284,7 +284,7 @@ public: m_tree, sp, k, - FT(0.0), + FT(0), true, Distance_adapter >( (Point*)&(m_points[0])), @@ -301,7 +301,7 @@ public: Incremental_neighbor_search search( m_tree, sp, - FT(0.0), + FT(0), true, Distance_adapter >( (Point*)&(m_points[0])) ); diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index a83560acd60..f6e830ef9f8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -25,6 +25,7 @@ //========================= Debugging & profiling ============================= //#define CGAL_TC_PROFILING +#define CGAL_TC_VERBOSE //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index be1a3febd20..bcf66a6dda8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -35,17 +35,17 @@ namespace Tangential_complex_ { std::vector const& input_basis, K const& kernel) { - typedef typename K::Vector_d Vector; - typedef std::vector Basis; - const int D = Ambient_dimension::value; + typedef typename K::FT FT; + typedef typename K::Vector_d Vector; + typedef std::vector Basis; + + const int D = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar // Kernel functors K::Squared_length_d sqlen = kernel.squared_length_d_object(); K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); - //K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); - //K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); - Get_functor::type inner_pdct(kernel); // CJTODO TEMP - Get_functor::type diff_vec(kernel); + K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); + K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); Basis output_basis; @@ -63,7 +63,8 @@ namespace Tangential_complex_ { u = diff_vec(u, u_proj); } - output_basis.push_back(scaled_vec(u, 1./CGAL::sqrt(sqlen(u)))); + output_basis.push_back( + scaled_vec(u, FT(1)/CGAL::sqrt(sqlen(u)))); } return output_basis; diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index ef2b13168b1..5817608f200 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -21,11 +21,28 @@ #endif #ifdef _DEBUG - const int NUM_POINTS = 150; + const int NUM_POINTS = 6; #else - const int NUM_POINTS = 10000; + const int NUM_POINTS = 50000; #endif +template +std::vector generate_points_on_plane() +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT x = rng.get_double(0, 5); + FT y = rng.get_double(0, 5); + points.push_back(Kernel().construct_point_d_object()(x, y, 0)); + } + return points; +} + template std::vector generate_points_on_sphere(double radius) { @@ -39,7 +56,46 @@ std::vector generate_points_on_sphere(double radius) // a = big radius, b = small radius template -std::vector generate_points_on_klein_bottle( +std::vector generate_points_on_klein_bottle_3D( + double a, double b, bool uniform = false) +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int 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); + points.push_back(Kernel().construct_point_d_object()( + (a + b*tmp)*cos(u), + (a + b*tmp)*sin(u), + b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)))); + } + return points; +} + +// a = big radius, b = small radius +template +std::vector generate_points_on_klein_bottle_4D( double a, double b, bool uniform = false) { typedef typename CGAL::Kernel_traits::type Kernel; @@ -94,37 +150,49 @@ int main() # endif #endif - Wall_clock_timer t; + int i = 0; + bool stop = false; + //for ( ; !stop ; ++i) + { + Wall_clock_timer t; + CGAL::default_random = CGAL::Random(i); + std::cerr << "Random seed = " << i << std::endl; + + //std::vector points = generate_points_on_plane(); + //std::vector points = generate_points_on_sphere(3.0); + //std::vector points = generate_points_on_klein_bottle_3D(4., 3.); + std::vector points = generate_points_on_klein_bottle_4D(4., 3.); - //std::vector points = generate_points_on_sphere(3.0); - std::vector points = generate_points_on_klein_bottle(4., 3.); + CGAL::Tangential_complex< + Kernel, + INTRINSIC_DIMENSION, + CGAL::Parallel_tag> tc(points.begin(), points.end()); + double init_time = t.elapsed(); t.reset(); - CGAL::Tangential_complex< - Kernel, - INTRINSIC_DIMENSION, - CGAL::Parallel_tag> tc(points.begin(), points.end()); - double init_time = t.elapsed(); t.reset(); + tc.compute_tangential_complex(); + double computation_time = t.elapsed(); t.reset(); - tc.compute_tangential_complex(); - double computation_time = t.elapsed(); t.reset(); + std::set > incorrect_simplices; + //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); - std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION - << "_in_R" << AMBIENT_DIMENSION << ".off"; - std::ofstream off_stream(output_filename.str()); - tc.export_to_off(off_stream, true); - double export_time = t.elapsed(); t.reset(); + std::stringstream output_filename; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION + << "_in_R" << AMBIENT_DIMENSION << ".off"; + std::ofstream off_stream(output_filename.str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + double export_time = t.elapsed(); t.reset(); - std::cerr << std::endl - << "================================================" << 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: " << export_time << std::endl - << "================================================" << std::endl - << std::endl; + std::cerr << std::endl + << "================================================" << 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: " << export_time << std::endl + << "================================================" << std::endl + << std::endl; + } return 0; } \ No newline at end of file From 57690e3a908b59f2837322185c55fddb3d4346c2 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 14 Oct 2014 16:15:33 +0200 Subject: [PATCH 047/269] Translated_point_d --- NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h | 2 ++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index dcbea88278c..cd8269f07da 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -73,6 +73,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type In_flat_power_test_d; typedef typename Get_functor::type Point_to_vector_d; typedef typename Get_functor::type Vector_to_point_d; + typedef typename Get_functor::type Translated_point_d; typedef typename Get_functor::type Scaled_vector_d; typedef typename Get_functor::type Difference_of_vectors_d; typedef typename Get_functor::type Difference_of_points_d; @@ -184,6 +185,7 @@ template struct Kernel_d_interface : public Base_ { In_flat_power_test_d in_flat_power_test_d_object()const{ return In_flat_power_test_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); } diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 01c63d26ac7..c98fad5d9cd 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -121,6 +121,7 @@ void test2(){ typedef typename K1::Scalar_product_d SP; typedef typename K1::Difference_of_vectors_d DV; typedef typename K1::Difference_of_points_d DP; + typedef typename K1::Translated_point_d TP; CGAL_USE_TYPE(AT); CGAL_USE_TYPE(D); @@ -178,6 +179,7 @@ void test2(){ SP spr Kinit(scalar_product_d_object); DV dv Kinit(difference_of_vectors_d_object); DP dp Kinit(difference_of_points_d_object); + TP tp Kinit(translated_point_d_object); CGAL_USE(bc); CGAL_USE(pol); @@ -331,6 +333,8 @@ void test2(){ assert(abs(sd(cent0,psp1)-25)<.0001); assert(abs(sd(cent0,psp2)-25)<.0001); #endif + P x2py1 = tp(x2,y1); + assert(x2py1[1]==-2); Sp un1; CGAL_USE(un1); H un2; CGAL_USE(un2); S un3; CGAL_USE(un3); From a1d9b2477ef225d380ecf1e4f60ad36004ac6165 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Oct 2014 17:24:13 +0200 Subject: [PATCH 048/269] Missing "typename"s + better use of the kernel --- .../include/CGAL/Tangential_complex.h | 81 ++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 909ee277852..fef6c48845f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -259,7 +259,7 @@ public: Kernel, Triangulation_data_structure < - Kernel::Dimension, + typename Kernel::Dimension, Triangulation_vertex > > DT; @@ -373,7 +373,8 @@ private: bool operator()(Point const& p1, Point const& p2) { - Kernel::Squared_distance_d sqdist = m_k.squared_distance_d_object(); + typename Kernel::Squared_distance_d sqdist = + m_k.squared_distance_d_object(); return sqdist(p1, m_ref) < sqdist(p2, m_ref); } @@ -453,9 +454,9 @@ private: Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects - Kernel::Difference_of_points_d k_diff_pts = + typename Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - Kernel::Squared_distance_d k_sqdist = + typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); // Triangulation's traits functor & objects @@ -481,7 +482,7 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(0, 0), + local_tr_traits.construct_point_d_object()(Intrinsic_dimension), 0); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -513,7 +514,7 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, center_pt, m_tangent_spaces[i]); + neighbor_pt, center_pt, m_tangent_spaces[i], local_tr_traits); FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); @@ -607,11 +608,18 @@ private: ) const { // Kernel functors - Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); - Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); + typename Kernel::Construct_vector_d constr_vec = + m_k.construct_vector_d_object(); + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename Kernel::Squared_length_d sqlen = + m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Scalar_product_d inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Difference_of_vectors_d diff_vec = + m_k.difference_of_vectors_d_object(); KNS_range kns_range = m_points_ds.query_ANN( p, NUM_POINTS_FOR_PCA, false); @@ -627,7 +635,7 @@ private: ++j, ++nn_it) { for (int i = 0 ; i < amb_dim ; ++i) - mat_points(j, i) = CGAL::to_double(m_points[nn_it->first][i]); // CJTODO: Use kernel functor + mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -666,8 +674,8 @@ private: p[0] * t1[1] - p[1] * t1[0]); // Normalize t1 and t2 - Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts; ts.reserve(Intrinsic_dimension); @@ -695,8 +703,9 @@ private: Tr_bare_point project_point(const Point &p, const Point &origin, const Tangent_space_basis &ts) const { - Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - Kernel::Difference_of_points_d diff_points = + typename Kernel::Scalar_product_d inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); std::vector coords; @@ -716,13 +725,15 @@ private: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p Tr_point project_point_and_compute_weight( - const Point &p, const Point &origin, const Tangent_space_basis &ts) const + const Point &p, const Point &origin, const Tangent_space_basis &ts, + const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); - Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); - Kernel::Difference_of_points_d diff_points = + typename Kernel::Scalar_product_d inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); - Kernel::Construct_cartesian_const_iterator_d ccci = + typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); Vector v = diff_points(p, origin); @@ -742,21 +753,14 @@ private: p_proj[j] += coord * ts[i][j]; } - // CJTODO TEMP: test it - /*Kernel::Construct_vector_d c_vec = m_k.construct_vector_d_object(); - Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - Point proj_pt = origin; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - Vector base_i = c_vec(point_dim, ts[i].begin(), ts[i].end()); - FT coef = inner_pdct(v, base_i); - proj_pt = proj_pt + scaled_vec(base_i, coef); - }*/ - Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); - return Tr_point( // CJTODO: use kernel constructions - Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()), - m_k.squared_distance_d_object()(p, projected_pt)); + + return tr_traits.construct_weighted_point_d_object() + ( + tr_traits.construct_point_d_object()( + Intrinsic_dimension, coords.begin(), coords.end()), + m_k.squared_distance_d_object()(p, projected_pt) + ); } // A simplex here is a list of point indices @@ -804,6 +808,11 @@ private: } const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); + + // Kernel functors + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + int num_coords = min(ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS Normals::const_iterator it_n = m_normals.begin(); @@ -815,13 +824,13 @@ private: { int i = 0; for ( ; i < num_coords ; ++i) - os << CGAL::to_double((*it_p)[i]) << " "; // CJTODO: use kernel functors, not [] + os << CGAL::to_double(coord(*it_p, i)) << " "; if (i == 2) os << "0"; #ifdef CGAL_TC_EXPORT_NORMALS for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double((*it_n)[i]); // CJTODO: use kernel functors, not [] + os << " " << CGAL::to_double(coord(*it_n, i)); ++it_n; #endif From dc209b8e3427831c549e3befeac4186fe9ae2332 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Oct 2014 17:25:51 +0200 Subject: [PATCH 049/269] Clean-up comment --- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 9ad874311a4..b5174b0f698 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -1036,7 +1036,7 @@ Regular_triangulation } else { - Orientation_d ori = geom_traits().orientation_d_object(); // CJTODO: create member variables for this? + Orientation_d ori = geom_traits().orientation_d_object(); Power_test_d side = geom_traits().power_test_d_object(); Conflict_pred_in_fullspace c(*this, p, ori, side); return c(s); From 5cf4767597e4aef1a5cb5c3b6042f67d21bb42dd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Oct 2014 17:56:45 +0200 Subject: [PATCH 050/269] Add ORIGIN to construct a (0,... 0) point --- Tangential_complex/include/CGAL/Tangential_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fef6c48845f..3c229c83239 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -482,7 +482,7 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(Intrinsic_dimension), + local_tr_traits.construct_point_d_object()(Intrinsic_dimension, ORIGIN), 0); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -509,7 +509,7 @@ private: { const Point &neighbor_pt = m_points[neighbor_point_idx]; - if (star_sphere_squared_radius + if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) > *star_sphere_squared_radius) break; From 584e6255c917690d06a58ac51e0524df5f192a23 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 15:36:54 +0200 Subject: [PATCH 051/269] Add function "number_of_inconsistent_simplices" --- .../include/CGAL/Tangential_complex.h | 72 ++++++++++++++++--- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3c229c83239..473aee33c72 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -191,7 +191,57 @@ public: << " seconds." << std::endl; #endif } + + // Return a pair + std::pair number_of_inconsistent_simplices() + { + std::size_t num_simplices = 0; + std::size_t num_inconsistent_simplices = 0; + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + c.insert(data); + } + + if (!is_simplex_consistent(c)) + ++num_inconsistent_simplices; + ++num_simplices; + } + } + +#ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "================================================" << std::endl + << "Inconsistencies:\n" + << " * Total number of simplices in stars (incl. duplicates): " + << num_simplices << std::endl + << " * Number of inconsistent simplices in stars (incl. duplicates): " + << num_inconsistent_simplices << std::endl + << " * Percentage of inconsistencies: " + << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl + << "================================================" << std::endl; +#endif + + return std::make_pair(num_simplices, num_inconsistent_simplices); + } + std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, @@ -229,10 +279,10 @@ public: } std::stringstream output; - std::size_t num_cells, num_vertices; + std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); export_simplices_to_off( - output, num_cells, color_inconsistencies, + output, num_simplices, color_inconsistencies, excluded_simplices, show_excluded_vertices_in_color); #ifdef CGAL_TC_EXPORT_NORMALS @@ -241,7 +291,7 @@ public: os << "OFF \n" << m_points.size() << " " - << num_cells << " " + << num_simplices << " " << "0 \n" << output.str(); @@ -840,14 +890,14 @@ private: num_vertices = m_points.size(); return os; } - + std::ostream &export_simplices_to_off( - std::ostream & os, std::size_t &num_cells, + std::ostream & os, std::size_t &num_simplices, bool color_inconsistencies = false, std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) { - num_cells = 0; + num_simplices = 0; std::size_t num_inconsistent_simplices = 0; Tr_container::const_iterator it_tr = m_triangulations.begin(); Tr_container::const_iterator it_tr_end = m_triangulations.end(); @@ -898,14 +948,14 @@ private: os << "255 0 0"; ++num_inconsistent_simplices; } - ++num_cells; + ++num_simplices; } else if (show_excluded_vertices_in_color) { os << Intrinsic_dimension + 1 << " " << sstr_c.str() << " " << "0 0 255"; - ++num_cells; + ++num_simplices; } } else @@ -913,7 +963,7 @@ private: os << Intrinsic_dimension + 1 << " "; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) os << (*it_c)->vertex(i)->data() << " "; - ++num_cells; + ++num_simplices; } os << std::endl; @@ -925,9 +975,11 @@ private: << "================================================" << std::endl << "Export to OFF:\n" << " * Total number of simplices in stars (incl. duplicates): " - << num_cells << std::endl + << num_simplices << std::endl << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl + << " * Percentage of inconsistencies: " + << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl << "================================================" << std::endl; #endif From 13b9f6b254141fdc4e445d197dc8db45f601df4e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 18:17:38 +0200 Subject: [PATCH 052/269] Code reorganization + function to generate points on n-spheres --- .../test_tangential_complex.cpp | 132 ++------------- .../test/Tangential_complex/test_utilities.h | 152 ++++++++++++++++++ 2 files changed, 168 insertions(+), 116 deletions(-) create mode 100644 Tangential_complex/test/Tangential_complex/test_utilities.h diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 5817608f200..1123f9a81f6 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -6,9 +6,10 @@ # define TBB_USE_THREADING_TOOL #endif +#include "test_utilities.h" + #include #include -#include #include #include #include @@ -21,121 +22,15 @@ #endif #ifdef _DEBUG - const int NUM_POINTS = 6; + const int NUM_POINTS = 50; #else - const int NUM_POINTS = 50000; + const int NUM_POINTS = 500; #endif -template -std::vector generate_points_on_plane() -{ - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - CGAL::Random rng; - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - { - FT x = rng.get_double(0, 5); - FT y = rng.get_double(0, 5); - points.push_back(Kernel().construct_point_d_object()(x, y, 0)); - } - return points; -} - -template -std::vector generate_points_on_sphere(double radius) -{ - CGAL::Random_points_on_sphere_3 generator(radius); - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - points.push_back(*generator++); - return points; -} - -// a = big radius, b = small radius -template -std::vector generate_points_on_klein_bottle_3D( - double a, double b, bool uniform = false) -{ - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - CGAL::Random rng; - - // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; - - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - { - FT u, v; - if (uniform) - { - int k1 = i / num_lines; - int 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); - points.push_back(Kernel().construct_point_d_object()( - (a + b*tmp)*cos(u), - (a + b*tmp)*sin(u), - b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)))); - } - return points; -} - -// a = big radius, b = small radius -template -std::vector generate_points_on_klein_bottle_4D( - double a, double b, bool uniform = false) -{ - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - CGAL::Random rng; - - // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; - - std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) - { - FT u, v; - if (uniform) - { - int k1 = i / num_lines; - int 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); - } - points.push_back(Kernel().construct_point_d_object()( - (a + b*cos(v))*cos(u), - (a + b*cos(v))*sin(u), - b*sin(v)*cos(u/2), - b*sin(v)*sin(u/2))); - } - return points; -} - int main() { - const int INTRINSIC_DIMENSION = 2; - const int AMBIENT_DIMENSION = 4; + const int INTRINSIC_DIMENSION = 4; + const int AMBIENT_DIMENSION = 5; typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; @@ -158,10 +53,11 @@ int main() CGAL::default_random = CGAL::Random(i); std::cerr << "Random seed = " << i << std::endl; - //std::vector points = generate_points_on_plane(); - //std::vector points = generate_points_on_sphere(3.0); - //std::vector points = generate_points_on_klein_bottle_3D(4., 3.); - std::vector points = generate_points_on_klein_bottle_4D(4., 3.); + //std::vector points = generate_points_on_plane(NUM_POINTS); + //std::vector points = generate_points_on_sphere_3(NUM_POINTS, 3.0); + std::vector points = generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); + //std::vector points = generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); + //std::vector points = generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); CGAL::Tangential_complex< Kernel, @@ -179,7 +75,11 @@ int main() output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; std::ofstream off_stream(output_filename.str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); + if (INTRINSIC_DIMENSION <= 3) + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + else + tc.number_of_inconsistent_simplices(); + double export_time = t.elapsed(); t.reset(); std::cerr << std::endl diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h new file mode 100644 index 00000000000..6391fe1da6f --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -0,0 +1,152 @@ +// 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 +#include +#include + +template +std::vector generate_points_on_plane(std::size_t num_points) +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT x = rng.get_double(0, 5); + FT y = rng.get_double(0, 5); + points.push_back(Kernel().construct_point_d_object()(x, y, 0)); + } + return points; +} + +template +std::vector generate_points_on_sphere_3( + std::size_t num_points, double radius) +{ + CGAL::Random_points_on_sphere_3 generator(radius); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + points.push_back(*generator++); + return points; +} + +template +std::vector generate_points_on_sphere_d( + std::size_t num_points, int dim, double radius) +{ + CGAL::Random_points_on_sphere_d generator(dim, radius); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + points.push_back(*generator++); + return points; +} + +// a = big radius, b = small radius +template +std::vector generate_points_on_klein_bottle_3D( + std::size_t num_points, double a, double b, bool uniform = false) +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int 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); + points.push_back(Kernel().construct_point_d_object()( + (a + b*tmp)*cos(u), + (a + b*tmp)*sin(u), + b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)))); + } + return points; +} + +// a = big radius, b = small radius +template +std::vector generate_points_on_klein_bottle_4D( + std::size_t num_points, double a, double b, bool uniform = false) +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + CGAL::Random rng; + + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int 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); + } + points.push_back(Kernel().construct_point_d_object()( + (a + b*cos(v))*cos(u) + rng.get_double(0, 0.01), + (a + b*cos(v))*sin(u) + rng.get_double(0, 0.01), + b*sin(v)*cos(u/2) + rng.get_double(0, 0.01), + b*sin(v)*sin(u/2) + rng.get_double(0, 0.01)) ); + } + return points; +} + +#endif // CGAL_MESH_3_TEST_TEST_UTILITIES_H From 7f11985e6919136042912ef75f37293ca9f9ff45 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 18:58:48 +0200 Subject: [PATCH 053/269] Comment noise + add generate_points_on_circle_2 --- .../test/Tangential_complex/test_utilities.h | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 6391fe1da6f..c6ad351a120 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -27,6 +27,7 @@ #define CGAL_TC_TEST_TEST_UTILITIES_H #include +#include #include #include @@ -47,6 +48,18 @@ std::vector generate_points_on_plane(std::size_t num_points) return points; } +template +std::vector generate_points_on_circle_2( + std::size_t num_points, double radius) +{ + CGAL::Random_points_on_circle_2 generator(radius); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + points.push_back(*generator++); + return points; +} + template std::vector generate_points_on_sphere_3( std::size_t num_points, double radius) @@ -141,10 +154,10 @@ std::vector generate_points_on_klein_bottle_4D( v = rng.get_double(0, 6.2832); } points.push_back(Kernel().construct_point_d_object()( - (a + b*cos(v))*cos(u) + rng.get_double(0, 0.01), - (a + b*cos(v))*sin(u) + rng.get_double(0, 0.01), - b*sin(v)*cos(u/2) + rng.get_double(0, 0.01), - b*sin(v)*sin(u/2) + rng.get_double(0, 0.01)) ); + (a + b*cos(v))*cos(u) /*+ rng.get_double(0, 0.01)*/, + (a + b*cos(v))*sin(u) /*+ rng.get_double(0, 0.01)*/, + b*sin(v)*cos(u/2) /*+ rng.get_double(0, 0.01)*/, + b*sin(v)*sin(u/2) /*+ rng.get_double(0, 0.01)*/) ); } return points; } From ff4491a7b3c709b531caad37a9ec4212cad62cde Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 19:00:07 +0200 Subject: [PATCH 054/269] Trick to export complexes with intrinsic dim = 2 --- .../include/CGAL/Tangential_complex.h | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 473aee33c72..5c03866e9c1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -290,7 +290,7 @@ public: #endif os << "OFF \n" - << m_points.size() << " " + << num_vertices << " " << num_simplices << " " << "0 \n" << output.str(); @@ -856,7 +856,11 @@ private: num_vertices = 0; return os; } - + + // If Intrinsic_dimension = 1, we output each point two times + // to be able to export each segment as a flat triangle with 3 different + // indices (otherwise, Meshlab detects degenerated simplices) + const int N = (Intrinsic_dimension == 1 ? 2 : 1); const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors @@ -872,22 +876,26 @@ private: // For each point p for ( ; it_p != it_p_end ; ++it_p) { - int i = 0; - for ( ; i < num_coords ; ++i) - os << CGAL::to_double(coord(*it_p, i)) << " "; - if (i == 2) - os << "0"; + for (int ii = 0 ; ii < N ; ++ii) + { + int i = 0; + for ( ; i < num_coords ; ++i) + os << CGAL::to_double(coord(*it_p, i)) << " "; + if (i == 2) + os << "0"; #ifdef CGAL_TC_EXPORT_NORMALS - for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double(coord(*it_n, i)); + for (i = 0 ; i < num_coords ; ++i) + os << " " << CGAL::to_double(coord(*it_n, i)); +#endif + os << std::endl; + } +#ifdef CGAL_TC_EXPORT_NORMALS ++it_n; #endif - - os << std::endl; } - num_vertices = m_points.size(); + num_vertices = N*m_points.size(); return os; } @@ -897,6 +905,11 @@ private: std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) { + // If Intrinsic_dimension = 1, each point is output two times + // (see export_vertices_to_off) + int factor = (Intrinsic_dimension == 1 ? 2 : 1); + int OFF_simplices_dim = + (Intrinsic_dimension == 1 ? 3 : Intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; Tr_container::const_iterator it_tr = m_triangulations.begin(); @@ -927,12 +940,16 @@ private: { std::set c; std::stringstream sstr_c; + std::size_t data; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) { - std::size_t data = (*it_c)->vertex(i)->data(); - sstr_c << data << " "; + data = (*it_c)->vertex(i)->data(); + sstr_c << data*factor << " "; c.insert(data); } + // See export_vertices_to_off + if (Intrinsic_dimension == 1) + sstr_c << (data*factor + 1) << " "; bool excluded = (excluded_simplices @@ -940,7 +957,7 @@ private: if (!excluded) { - os << Intrinsic_dimension + 1 << " " << sstr_c.str() << " "; + os << OFF_simplices_dim << " " << sstr_c.str() << " "; if (color_inconsistencies && is_simplex_consistent(c)) os << color.str(); else @@ -952,7 +969,7 @@ private: } else if (show_excluded_vertices_in_color) { - os << Intrinsic_dimension + 1 << " " + os << OFF_simplices_dim << " " << sstr_c.str() << " " << "0 0 255"; ++num_simplices; @@ -960,9 +977,17 @@ private: } else { - os << Intrinsic_dimension + 1 << " "; + os << OFF_simplices_dim << " "; + std::size_t data; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - os << (*it_c)->vertex(i)->data() << " "; + { + data = (*it_c)->vertex(i)->data(); + os << data*factor << " "; + } + // See export_vertices_to_off + if (Intrinsic_dimension == 1) + os << (data*factor + 1) << " "; + ++num_simplices; } From db6dbb9aa98f586f3c2f304a90b8556e93356bed Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 19:00:32 +0200 Subject: [PATCH 055/269] Test generate_points_on_circle_2 + code reorganization --- .../test_tangential_complex.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 1123f9a81f6..6dcfc98366b 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -29,14 +29,6 @@ int main() { - const int INTRINSIC_DIMENSION = 4; - const int AMBIENT_DIMENSION = 5; - - typedef CGAL::Epick_d > Kernel; - typedef Kernel::Point_d Point; - - //CGAL::default_random = CGAL::Random(0); // NO RANDOM - #ifdef CGAL_LINKED_WITH_TBB # ifdef _DEBUG tbb::task_scheduler_init init(1); @@ -45,6 +37,12 @@ int main() # endif #endif + const int INTRINSIC_DIMENSION = 1; + const int AMBIENT_DIMENSION = 2; + + typedef CGAL::Epick_d > Kernel; + typedef Kernel::Point_d Point; + int i = 0; bool stop = false; //for ( ; !stop ; ++i) @@ -53,9 +51,10 @@ int main() CGAL::default_random = CGAL::Random(i); std::cerr << "Random seed = " << i << std::endl; + std::vector points = generate_points_on_circle_2(NUM_POINTS, 3.); //std::vector points = generate_points_on_plane(NUM_POINTS); //std::vector points = generate_points_on_sphere_3(NUM_POINTS, 3.0); - std::vector points = generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); + //std::vector points = generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); //std::vector points = generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); //std::vector points = generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); From 491e02b85a1e17ef1137f561de56b13b270fdd80 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Oct 2014 19:35:18 +0200 Subject: [PATCH 056/269] Stop using Kernel_traits + add generate_points_on_moment_curve --- .../test_tangential_complex.cpp | 17 +++--- .../test/Tangential_complex/test_utilities.h | 53 +++++++++++++------ 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 6dcfc98366b..9e8f1cabe14 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -38,7 +37,7 @@ int main() #endif const int INTRINSIC_DIMENSION = 1; - const int AMBIENT_DIMENSION = 2; + const int AMBIENT_DIMENSION = 3; typedef CGAL::Epick_d > Kernel; typedef Kernel::Point_d Point; @@ -51,12 +50,14 @@ int main() CGAL::default_random = CGAL::Random(i); std::cerr << "Random seed = " << i << std::endl; - std::vector points = generate_points_on_circle_2(NUM_POINTS, 3.); - //std::vector points = generate_points_on_plane(NUM_POINTS); - //std::vector points = generate_points_on_sphere_3(NUM_POINTS, 3.0); - //std::vector points = generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); - //std::vector points = generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - //std::vector points = generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + std::vector points = + //generate_points_on_circle_2(NUM_POINTS, 3.); + generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); + //generate_points_on_plane(NUM_POINTS); + //generate_points_on_sphere_3(NUM_POINTS, 3.0); + //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); + //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); CGAL::Tangential_complex< Kernel, diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index c6ad351a120..0c27cf8dea3 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -31,10 +31,10 @@ #include #include -template -std::vector generate_points_on_plane(std::size_t num_points) +template +std::vector generate_points_on_plane(std::size_t num_points) { - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; CGAL::Random rng; std::vector points; @@ -48,8 +48,31 @@ std::vector generate_points_on_plane(std::size_t num_points) return points; } -template -std::vector generate_points_on_circle_2( +template +std::vector 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; + CGAL::Random rng; + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT x = rng.get_double(min_x, max_x); + std::vector coords; + coords.reserve(dim); + for (int p = 1 ; p <= dim ; ++p) + coords.push_back(std::pow(CGAL::to_double(x), p)); + points.push_back( + Kernel().construct_point_d_object()(dim, coords.begin(), coords.end())); + } + return points; +} + +template +std::vector generate_points_on_circle_2( std::size_t num_points, double radius) { CGAL::Random_points_on_circle_2 generator(radius); @@ -60,8 +83,8 @@ std::vector generate_points_on_circle_2( return points; } -template -std::vector generate_points_on_sphere_3( +template +std::vector generate_points_on_sphere_3( std::size_t num_points, double radius) { CGAL::Random_points_on_sphere_3 generator(radius); @@ -72,8 +95,8 @@ std::vector generate_points_on_sphere_3( return points; } -template -std::vector generate_points_on_sphere_d( +template +std::vector generate_points_on_sphere_d( std::size_t num_points, int dim, double radius) { CGAL::Random_points_on_sphere_d generator(dim, radius); @@ -85,11 +108,11 @@ std::vector generate_points_on_sphere_d( } // a = big radius, b = small radius -template -std::vector generate_points_on_klein_bottle_3D( +template +std::vector generate_points_on_klein_bottle_3D( std::size_t num_points, double a, double b, bool uniform = false) { - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; CGAL::Random rng; @@ -124,11 +147,11 @@ std::vector generate_points_on_klein_bottle_3D( } // a = big radius, b = small radius -template -std::vector generate_points_on_klein_bottle_4D( +template +std::vector generate_points_on_klein_bottle_4D( std::size_t num_points, double a, double b, bool uniform = false) { - typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; CGAL::Random rng; From f455969e08b2d55ba1f4121fa944c4e5706e5b0c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Oct 2014 15:29:38 +0200 Subject: [PATCH 057/269] Display the number of vertices + bug fix when there is very few points --- Tangential_complex/include/CGAL/Tangential_complex.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5c03866e9c1..6ef57c2b8ca 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -230,6 +230,7 @@ public: std::cerr << std::endl << "================================================" << std::endl << "Inconsistencies:\n" + << " * Number of vertices: " << m_points.size() << std::endl << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << std::endl << " * Number of inconsistent simplices in stars (incl. duplicates): " @@ -920,6 +921,9 @@ private: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); + if (tr.current_dimension() < Intrinsic_dimension) + continue; + // Color for this star std::stringstream color; //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; @@ -999,12 +1003,15 @@ private: std::cerr << std::endl << "================================================" << std::endl << "Export to OFF:\n" + << " * Number of vertices: " << m_points.size() << std::endl << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << std::endl << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl << " * Percentage of inconsistencies: " - << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl + << (num_simplices > 0 ? + 100 * num_inconsistent_simplices / num_simplices : 0) << "%" + << std::endl << "================================================" << std::endl; #endif From d0544766e5cb5bd008585abb1d7a454673626383 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Oct 2014 15:30:40 +0200 Subject: [PATCH 058/269] New constructor to include only a part of the vertices into the tree --- .../include/CGAL/Tangential_complex/Point_cloud.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index a8f53b8c24c..3cbd0d16048 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -262,6 +262,19 @@ public: { } + /// 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(begin_idx), + boost::counting_iterator(past_the_end_idx), + Tree::Splitter(), + STraits((Point*)&(points[0])) ) + { + } + /*Point_container_ &points() { return m_points; From ec11025811becf6af05c6f341aace6d565158b41 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Oct 2014 15:31:31 +0200 Subject: [PATCH 059/269] Precompiled headers --- .../test/Tangential_complex/CMakeLists.txt | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt index 8d58f3631fe..c1b10d3b85c 100644 --- a/Tangential_complex/test/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -13,6 +13,35 @@ if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 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 ) @@ -34,7 +63,9 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") include_directories (BEFORE "include") - create_single_source_cgal_program( "test_tangential_complex.cpp" ) + set (SOURCE_FILES "test_tangential_complex.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.") From 834a7554f42153a5a46a524154ed1345705ef521 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Oct 2014 15:32:18 +0200 Subject: [PATCH 060/269] Add a function to sparsify a point set and test it --- .../test_tangential_complex.cpp | 17 ++-- .../test/Tangential_complex/test_utilities.h | 79 +++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 9e8f1cabe14..f0ea68f33aa 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -23,7 +23,7 @@ #ifdef _DEBUG const int NUM_POINTS = 50; #else - const int NUM_POINTS = 500; + const int NUM_POINTS = 5000; #endif int main() @@ -36,33 +36,38 @@ int main() # endif #endif - const int INTRINSIC_DIMENSION = 1; - const int AMBIENT_DIMENSION = 3; + const int INTRINSIC_DIMENSION = 2; + const int AMBIENT_DIMENSION = 4; typedef CGAL::Epick_d > Kernel; + typedef Kernel::FT FT; typedef Kernel::Point_d Point; 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; std::vector points = //generate_points_on_circle_2(NUM_POINTS, 3.); - generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); + //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); //generate_points_on_plane(NUM_POINTS); //generate_points_on_sphere_3(NUM_POINTS, 3.0); //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - //generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + + points = sparsify_point_set(k, points, FT(0.2)*FT(0.2)); CGAL::Tangential_complex< Kernel, INTRINSIC_DIMENSION, - CGAL::Parallel_tag> tc(points.begin(), points.end()); + CGAL::Parallel_tag> tc(points.begin(), points.end(), k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 0c27cf8dea3..43d698e2b80 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -30,6 +30,42 @@ #include #include #include +#include + +template +std::vector +sparsify_point_set( + const Kernel &k, Point_container const& input_pts, + typename Kernel::FT min_squared_dist) +{ + typedef typename Point_container::value_type Point; + typedef typename CGAL::Point_cloud_data_structure Points_ds; + + typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); + + // Create the output container and push the first point into it + std::vector output; + Point_container::const_iterator it_pt = input_pts.begin(); + output.push_back(*it_pt); + ++it_pt; + + // Parse the following points, and add them if they are not too close to + // the other points + std::size_t c = 1; + for ( ; + it_pt != input_pts.end(); + ++it_pt) + { + Points_ds points_ds(output, 0, c); + if (points_ds.query_ANN(*it_pt, 1).begin()->second >= min_squared_dist) + { + output.push_back(*it_pt); + ++c; + } + } + + return output; +} template std::vector generate_points_on_plane(std::size_t num_points) @@ -185,4 +221,47 @@ std::vector generate_points_on_klein_bottle_4D( return points; } + +// a = big radius, b = small radius +template +std::vector +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; + CGAL::Random rng; + + // if uniform + int num_lines = (int)sqrt(NUM_POINTS); + int num_cols = NUM_POINTS/num_lines + 1; + + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0 ; i != NUM_POINTS ; ++i) + { + FT u, v; + if (uniform) + { + int k1 = i / num_lines; + int 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; + + points.push_back(Kernel().construct_point_d_object()(x1, x2, x3, x4, x5) ); + } + return points; +} + #endif // CGAL_MESH_3_TEST_TEST_UTILITIES_H From 20177a0d75237e9596f70a4a4eaaab2f64566d3c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 17 Oct 2014 14:38:07 +0200 Subject: [PATCH 061/269] Missing typedefs --- Tangential_complex/test/Tangential_complex/test_utilities.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 43d698e2b80..70212f9b3dd 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -111,6 +111,7 @@ template std::vector generate_points_on_circle_2( std::size_t num_points, double radius) { + typedef typename Kernel::Point_d Point; CGAL::Random_points_on_circle_2 generator(radius); std::vector points; points.reserve(NUM_POINTS); @@ -123,6 +124,7 @@ template std::vector generate_points_on_sphere_3( std::size_t num_points, double radius) { + typedef typename Kernel::Point_d Point; CGAL::Random_points_on_sphere_3 generator(radius); std::vector points; points.reserve(NUM_POINTS); @@ -135,6 +137,7 @@ template std::vector generate_points_on_sphere_d( std::size_t num_points, int dim, double radius) { + typedef typename Kernel::Point_d Point; CGAL::Random_points_on_sphere_d generator(dim, radius); std::vector points; points.reserve(NUM_POINTS); From b1f795a6da9923d64bcf70db65412674107e9b65 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 17 Oct 2014 17:34:06 +0200 Subject: [PATCH 062/269] Fisrt try to remove inconsistencies. Not very good. --- .../include/CGAL/Tangential_complex.h | 219 +++++++++++++++--- .../include/CGAL/Tangential_complex/config.h | 1 + .../test_tangential_complex.cpp | 37 ++- 3 files changed, 213 insertions(+), 44 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6ef57c2b8ca..9784b27ce9d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -103,6 +103,7 @@ class Tangential_complex typedef std::vector Tangent_space_basis; typedef std::vector Points; + typedef std::vector Weights; typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; @@ -150,11 +151,19 @@ public: template Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), m_points(first, last), m_points_ds(m_points) {} + : m_k(k), + m_points(first, last), + m_points_ds(m_points) + {} /// Destructor ~Tangential_complex() {} + std::size_t number_of_vertices() + { + return m_points.size(); + } + void compute_tangential_complex() { #ifdef CGAL_TC_PROFILING @@ -166,6 +175,7 @@ public: // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); m_tangent_spaces.resize(m_points.size()); + m_weights.resize(m_points.size(), FT(0)); #ifdef CGAL_TC_EXPORT_NORMALS m_normals.resize(m_points.size()); #endif @@ -192,8 +202,136 @@ public: #endif } + void refresh_tangential_complex() + { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif + +#ifdef CGAL_LINKED_WITH_TBB + // Parallel + if (boost::is_convertible::value) + { + tbb::parallel_for(tbb::blocked_range(0, m_points.size()), + Compute_tangent_triangulation(*this, true) + ); + } + // Sequential + else +#endif // CGAL_LINKED_WITH_TBB + { + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + compute_tangent_triangulation(i, true); + } + +#ifdef CGAL_TC_PROFILING + std::cerr << "Tangential complex refreshed in " << t.elapsed() + << " seconds." << std::endl; +#endif + } + + void fix_inconsistencies() + { + Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); + Kernel::Construct_weighted_point_d cwp = + m_k.construct_weighted_point_d_object(); + + std::pair stats_before = + number_of_inconsistent_simplices(false); + + bool done = false; + while (!done) + { + std::size_t num_failures = 0; + Tr_container::const_iterator it_tr = m_triangulations.begin(); + Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for (int pt_idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++pt_idx) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = incident_cells.begin(); + std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + c.insert(data); + } + + // Inconsistent? + if (!is_simplex_consistent(c)) + { + bool fixed = false; + // Try to find a weight that solves the inconsistency + for (int i = 0 ; i < 50 && !fixed ; ++i) + { + CGAL::Random rng; + m_weights[pt_idx] = + rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + + for (std::size_t j : c) // CJTODO: C++11 + compute_tangent_triangulation(j); + + fixed = is_simplex_consistent(c); + } + if (!fixed) + ++num_failures; + + refresh_tangential_complex(); // CJTODO: heavy computation! + } + } + } + + std::pair stats_after = + number_of_inconsistent_simplices(false); + +#ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "================================================" << std::endl + << "Inconsistencies:\n" + << " * Number of vertices: " << m_points.size() << std::endl + << std::endl + << " * BEFORE fix_inconsistencies:" << std::endl + << " - Total number of simplices in stars (incl. duplicates): " + << stats_before.first << std::endl + << " - Number of inconsistent simplices in stars (incl. duplicates): " + << stats_before.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_before.second / stats_before.first << "%" + << std::endl + << std::endl + << " * AFTER fix_inconsistencies:" << std::endl + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Number of inconsistent simplices in stars (incl. duplicates): " + << stats_after.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_before.first << "%" + << std::endl + << "================================================" << std::endl; +#endif + done = (stats_after.second == 0); + stats_before = stats_after; + } + } + + // Return a pair - std::pair number_of_inconsistent_simplices() + std::pair number_of_inconsistent_simplices( +#ifdef CGAL_TC_VERBOSE + bool verbose = true +#else + bool verbose = false +#endif + ) { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; @@ -213,32 +351,26 @@ public: // For each cell for ( ; it_c != it_c_end ; ++it_c) { - std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - { - std::size_t data = (*it_c)->vertex(i)->data(); - c.insert(data); - } - - if (!is_simplex_consistent(c)) + if (!is_simplex_consistent(*it_c)) ++num_inconsistent_simplices; ++num_simplices; } } -#ifdef CGAL_TC_VERBOSE - std::cerr << std::endl - << "================================================" << std::endl - << "Inconsistencies:\n" - << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices in stars (incl. duplicates): " - << num_simplices << std::endl - << " * Number of inconsistent simplices in stars (incl. duplicates): " - << num_inconsistent_simplices << std::endl - << " * Percentage of inconsistencies: " - << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl - << "================================================" << std::endl; -#endif + if (verbose) + { + std::cerr << std::endl + << "================================================" << std::endl + << "Inconsistencies:\n" + << " * Number of vertices: " << m_points.size() << std::endl + << " * Total number of simplices in stars (incl. duplicates): " + << num_simplices << std::endl + << " * Number of inconsistent simplices in stars (incl. duplicates): " + << num_inconsistent_simplices << std::endl + << " * Percentage of inconsistencies: " + << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl + << "================================================" << std::endl; + } return std::make_pair(num_simplices, num_inconsistent_simplices); } @@ -475,11 +607,14 @@ private: class Compute_tangent_triangulation { Tangential_complex & m_tc; + bool m_tangent_spaces_are_already_computed; public: // Constructor - Compute_tangent_triangulation(Tangential_complex &tc) - : m_tc(tc) + Compute_tangent_triangulation( + Tangential_complex &tc, bool tangent_spaces_are_already_computed = false) + : m_tc(tc), + m_tangent_spaces_are_already_computed(tangent_spaces_are_already_computed) {} // Constructor @@ -491,12 +626,16 @@ private: void operator()( const tbb::blocked_range& r ) const { for( size_t i = r.begin() ; i != r.end() ; ++i) - m_tc.compute_tangent_triangulation(i); + { + m_tc.compute_tangent_triangulation( + i, m_tangent_spaces_are_already_computed); + } } }; #endif // CGAL_LINKED_WITH_TBB - void compute_tangent_triangulation(std::size_t i) + void compute_tangent_triangulation( + std::size_t i, bool tangent_spaces_are_already_computed = false) { //std::cerr << "***********************************************" << std::endl; Triangulation &local_tr = @@ -520,11 +659,14 @@ private: // Estimate the tangent space const Point ¢er_pt = m_points[i]; + if (!tangent_spaces_are_already_computed) + { #ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); + m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt); + m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif + } //*************************************************** // Build a minimal triangulation in the tangent space @@ -534,7 +676,7 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(Intrinsic_dimension, ORIGIN), - 0); + m_weights[i]); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -569,7 +711,7 @@ private: FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); - FT w = -squared_dist_to_tangent_plane; + FT w = -squared_dist_to_tangent_plane + m_weights[neighbor_point_idx]; Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( drop_w(proj_pt), w); @@ -813,6 +955,18 @@ private: m_k.squared_distance_d_object()(p, projected_pt) ); } + + // A simplex here is a local tri's full cell handle + bool is_simplex_consistent(Tr_full_cell_handle fch) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = fch->vertex(i)->data(); + c.insert(data); + } + return is_simplex_consistent(c); + } // A simplex here is a list of point indices bool is_simplex_consistent(std::set const& simplex) @@ -1010,7 +1164,7 @@ private: << num_inconsistent_simplices << std::endl << " * Percentage of inconsistencies: " << (num_simplices > 0 ? - 100 * num_inconsistent_simplices / num_simplices : 0) << "%" + 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" << std::endl << "================================================" << std::endl; #endif @@ -1021,6 +1175,7 @@ private: private: const Kernel m_k; Points m_points; + Weights m_weights; Points_ds m_points_ds; TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index f6e830ef9f8..ce88cf276c4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -32,5 +32,6 @@ //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 50; +const double INPUT_SPARSITY = 0.5; #endif // CGAL_TC_CONFIG_H diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index f0ea68f33aa..25006c3ebde 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -23,7 +23,7 @@ #ifdef _DEBUG const int NUM_POINTS = 50; #else - const int NUM_POINTS = 5000; + const int NUM_POINTS = 100; #endif int main() @@ -37,7 +37,7 @@ int main() #endif const int INTRINSIC_DIMENSION = 2; - const int AMBIENT_DIMENSION = 4; + const int AMBIENT_DIMENSION = 4; typedef CGAL::Epick_d > Kernel; typedef Kernel::FT FT; @@ -62,7 +62,10 @@ int main() generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); - points = sparsify_point_set(k, points, FT(0.2)*FT(0.2)); + points = sparsify_point_set( + k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + std::cerr << "Number of points after sparsification: " + << points.size() << std::endl; CGAL::Tangential_complex< Kernel, @@ -76,24 +79,34 @@ int main() std::set > incorrect_simplices; //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); - std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION - << "_in_R" << AMBIENT_DIMENSION << ".off"; - std::ofstream off_stream(output_filename.str()); - if (INTRINSIC_DIMENSION <= 3) - tc.export_to_off(off_stream, true, &incorrect_simplices, true); - else - tc.number_of_inconsistent_simplices(); + t.reset(); + tc.fix_inconsistencies(); + double fix_time = t.elapsed(); t.reset(); + + double export_time = -1.; + if (INTRINSIC_DIMENSION <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION + << "_in_R" << AMBIENT_DIMENSION << ".off"; + std::ofstream off_stream(output_filename.str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + double export_time = t.elapsed(); t.reset(); + } + /*else + tc.number_of_inconsistent_simplices();*/ - double export_time = t.elapsed(); t.reset(); 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 + << " * Fix inconsistencies: " << fix_time << std::endl << " * Export to OFF: " << export_time << std::endl << "================================================" << std::endl << std::endl; From 8c5e28cd3d44f2786cef1dc26604fbff32e5a1db Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 21 Oct 2014 17:20:20 +0200 Subject: [PATCH 063/269] Power_center. --- .../include/CGAL/NewKernel_d/Types/Sphere.h | 1 - .../CGAL/NewKernel_d/Types/Weighted_point.h | 80 +++++++++++++++++++ .../include/CGAL/NewKernel_d/functor_tags.h | 3 + NewKernel_d/test/NewKernel_d/Epick_d.cpp | 22 +++++ 4 files changed, 105 insertions(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h index 7ab10f16b99..aac6259cd09 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Sphere.h @@ -57,7 +57,6 @@ template struct Construct_sphere : Store_kernel { typedef typename LA::Square_matrix Matrix; typedef typename LA::Vector Vec; typedef typename LA::Construct_vector CVec; - typedef typename Get_type::type Point; typename Get_functor::type c(this->kernel()); typename Get_functor >::type cp(this->kernel()); typename Get_functor::type pd(this->kernel()); diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 32e8b586b58..4c76c32d579 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -75,6 +75,33 @@ template struct Point_weight { } }; +template struct Power_distance : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_distance) + typedef typename Get_type::type first_argument_type; + typedef first_argument_type second_argument_type; + typedef typename Get_type::type result_type; + + result_type operator()(first_argument_type const&a, second_argument_type const&b)const{ + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + typename Get_functor::type sd(this->kernel()); + return sd(pdw(a),pdw(b))-pw(a)-pw(b); + } +}; +template struct Power_distance_to_point : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_distance_to_point) + typedef typename Get_type::type first_argument_type; + typedef typename Get_type::type second_argument_type; + typedef typename Get_type::type result_type; + + result_type operator()(first_argument_type const&a, second_argument_type const&b)const{ + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + typename Get_functor::type sd(this->kernel()); + return sd(pdw(a),b)-pw(a); + } +}; + template struct Power_test : private Store_kernel { CGAL_FUNCTOR_INIT_STORE(Power_test) typedef R_ R; @@ -114,6 +141,56 @@ template struct In_flat_power_test : private Store_kernel { } }; +// Construct a point at (weighted) distance 0 from all the input +template struct Power_center : Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_center) + typedef typename Get_type::type WPoint; + typedef WPoint result_type; + typedef typename Get_type::type Point; + typedef typename Get_type::type FT; + template + 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::type c(this->kernel()); + typename Get_functor >::type cp(this->kernel()); + typename Get_functor::type pd(this->kernel()); + typename Get_functor::type sdo(this->kernel()); + typename Get_functor::type pdp(this->kernel()); + typename Get_functor::type pdw(this->kernel()); + typename Get_functor::type pw(this->kernel()); + typename Get_functor >::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),(Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag,(CartesianDKernelFunctors::Construct_weighted_point),(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),(Weighted_point_tag,Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Power_test_tag,(CartesianDKernelFunctors::Power_test),(Weighted_point_tag),(Power_test_raw_tag,Point_drop_weight_tag,Point_weight_tag)); CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_test_tag,(CartesianDKernelFunctors::In_flat_power_test),(Weighted_point_tag),(In_flat_power_test_raw_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_distance_tag,(CartesianDKernelFunctors::Power_distance),(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),(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),(Weighted_point_tag,Point_tag),(Compute_point_cartesian_coordinate_tag,Construct_ttag,Construct_ttag,Point_dimension_tag,Squared_distance_to_origin_tag,Point_drop_weight_tag,Point_weight_tag,Power_distance_to_point_tag)); } // namespace CGAL #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index afe0720955a..56036b09d0e 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -218,6 +218,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 {}; \ @@ -268,6 +270,7 @@ namespace CGAL { CGAL_DECL_CONSTRUCT(Point_to_vector,Vector); CGAL_DECL_CONSTRUCT(Vector_to_point,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 {}; \ diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index c98fad5d9cd..96ca0b4c39e 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -74,6 +74,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; @@ -122,6 +123,12 @@ void test2(){ typedef typename K1::Difference_of_vectors_d DV; typedef typename K1::Difference_of_points_d DP; typedef typename K1::Translated_point_d TP; + typedef typename CGAL::Get_functor::type PC; + typedef typename CGAL::Get_functor::type 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); @@ -180,6 +187,11 @@ void test2(){ DV dv Kinit(difference_of_vectors_d_object); DP dp Kinit(difference_of_points_d_object); TP tp Kinit(translated_point_d_object); + PC pc (k); + 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 (k); CGAL_USE(bc); CGAL_USE(pol); @@ -335,6 +347,16 @@ void test2(){ #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); + Sp un1; CGAL_USE(un1); H un2; CGAL_USE(un2); S un3; CGAL_USE(un3); From 7115484e5d3e6c233bad5fd7dd37aef4de1318c9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 4 Nov 2014 14:36:04 +0100 Subject: [PATCH 064/269] Better version of the inconsistencies solver --- .../include/CGAL/Tangential_complex.h | 206 +++++++++++++----- 1 file changed, 148 insertions(+), 58 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 9784b27ce9d..b3c492837e6 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -58,6 +58,7 @@ #ifdef CGAL_LINKED_WITH_TBB # include +# include #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) @@ -119,14 +120,21 @@ class Tangential_complex Tr_and_VH(int dim) : m_tr(new Triangulation(dim)) {} - ~Tr_and_VH() { delete m_tr; } + ~Tr_and_VH() { destroy_triangulation(); } Triangulation & construct_triangulation(int dim) - { + { + delete m_tr; m_tr = new Triangulation(dim); return tr(); } + void destroy_triangulation() + { + delete m_tr; + m_tr = NULL; + } + Triangulation & tr() { return *m_tr; } Triangulation const& tr() const { return *m_tr; } @@ -139,8 +147,13 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; - typedef typename std::vector Tr_container; typedef typename std::vector TS_container; + typedef typename std::vector Tr_container; +#ifdef CGAL_LINKED_WITH_TBB + // CJTODO: test other mutexes + // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm + typedef tbb::queuing_mutex Tr_mutex; +#endif #ifdef CGAL_TC_EXPORT_NORMALS typedef typename std::vector Normals; #endif @@ -174,6 +187,9 @@ public: // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); +#ifdef CGAL_LINKED_WITH_TBB + m_tr_mutexes.resize(m_points.size()); +#endif m_tangent_spaces.resize(m_points.size()); m_weights.resize(m_points.size(), FT(0)); #ifdef CGAL_TC_EXPORT_NORMALS @@ -236,60 +252,39 @@ public: Kernel::Construct_weighted_point_d cwp = m_k.construct_weighted_point_d_object(); +#ifdef CGAL_TC_VERBOSE + std::cerr << "Fixing inconsistencies..." << std::endl; +#endif + std::pair stats_before = number_of_inconsistent_simplices(false); + +#ifdef CGAL_TC_VERBOSE + std::cerr << "Initial number of inconsistencies: " + << stats_before.second << std::endl; +#endif bool done = false; while (!done) { - std::size_t num_failures = 0; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); - // For each triangulation - for (int pt_idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++pt_idx) +// CJTODO: the parallel version is not working for now +/*#ifdef CGAL_LINKED_WITH_TBB + // Parallel + if (boost::is_convertible::value) { - Triangulation const& tr = it_tr->tr(); - Tr_vertex_handle center_vh = it_tr->center_vertex(); - - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); - // For each cell - for ( ; it_c != it_c_end ; ++it_c) - { - std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - { - std::size_t data = (*it_c)->vertex(i)->data(); - c.insert(data); - } - - // Inconsistent? - if (!is_simplex_consistent(c)) - { - bool fixed = false; - // Try to find a weight that solves the inconsistency - for (int i = 0 ; i < 50 && !fixed ; ++i) - { - CGAL::Random rng; - m_weights[pt_idx] = - rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); - - for (std::size_t j : c) // CJTODO: C++11 - compute_tangent_triangulation(j); - - fixed = is_simplex_consistent(c); - } - if (!fixed) - ++num_failures; - - refresh_tangential_complex(); // CJTODO: heavy computation! - } - } + tbb::parallel_for( + tbb::blocked_range(0, m_triangulations.size()), + Try_to_solve_inconsistencies_in_a_local_triangulation(*this) + ); } - + // Sequential + else +#endif // CGAL_LINKED_WITH_TBB*/ + { + for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) + try_to_solve_inconsistencies_in_a_local_triangulation(i); + } + std::pair stats_after = number_of_inconsistent_simplices(false); @@ -973,7 +968,8 @@ private: { // Check if the simplex is in the stars of all its vertices std::set::const_iterator it_point_idx = simplex.begin(); - // For each point + // For each point p of the simplex, we parse the incidents cells of p + // and we check if "simplex" is among them for ( ; it_point_idx != simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; @@ -1003,6 +999,97 @@ private: return true; } +#ifdef CGAL_LINKED_WITH_TBB + // Functor for try_to_solve_inconsistencies_in_a_local_triangulation function + class Try_to_solve_inconsistencies_in_a_local_triangulation + { + Tangential_complex & m_tc; + + public: + // Constructor + Try_to_solve_inconsistencies_in_a_local_triangulation( + Tangential_complex &tc) + : m_tc(tc) + {} + + // Constructor + Try_to_solve_inconsistencies_in_a_local_triangulation( + const Compute_tangent_triangulation &ctt) + : m_tc(ctt.m_tc) + {} + + // operator() + void operator()( const tbb::blocked_range& r ) const + { + for( size_t i = r.begin() ; i != r.end() ; ++i) + m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(i); + } + }; +#endif // CGAL_LINKED_WITH_TBB + + void try_to_solve_inconsistencies_in_a_local_triangulation( + std::size_t tr_index) + { +#ifdef CGAL_LINKED_WITH_TBB + Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); +#endif + + Triangulation const& tr = m_triangulations[tr_index].tr(); + Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + std::vector::const_iterator it_c = + incident_cells.begin(); + std::vector::const_iterator it_c_end= + incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + std::set c; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + { + std::size_t data = (*it_c)->vertex(i)->data(); + c.insert(data); + } + + // Inconsistent? + if (!is_simplex_consistent(c)) + { + CGAL::Random rng; + for (std::size_t j : c) // CJTODO: C++11 + { + m_weights[j] = + rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + } + + for (std::size_t j : c) // CJTODO: C++11 + { +#ifdef CGAL_LINKED_WITH_TBB + if (j == tr_index) + { + compute_tangent_triangulation(j); + } + else + { + Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); + compute_tangent_triangulation(j); + } +#else + compute_tangent_triangulation(j); +#endif + } + + refresh_tangential_complex(); // CJTODO: heavy computation! + + // We will try the other cells next time (incident_cells is not + // valid anymore here) + break; + } + } + } + std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices) { @@ -1173,15 +1260,18 @@ private: } private: - const Kernel m_k; - Points m_points; - Weights m_weights; - Points_ds m_points_ds; - TS_container m_tangent_spaces; - Tr_container m_triangulations; // Contains the triangulations - // and their center vertex + const Kernel m_k; + Points m_points; + Weights m_weights; + Points_ds m_points_ds; + TS_container m_tangent_spaces; + Tr_container m_triangulations; // Contains the triangulations + // and their center vertex +#ifdef CGAL_LINKED_WITH_TBB + std::vector m_tr_mutexes; +#endif #ifdef CGAL_TC_EXPORT_NORMALS - Normals m_normals; + Normals m_normals; #endif }; // /class Tangential_complex From 6981ebe0d4f3c9f557a30c2db9e5ff64243962d0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 18 Nov 2014 10:31:26 +0100 Subject: [PATCH 065/269] Do not test consistency of infinite cells + fix indentation --- .../include/CGAL/Tangential_complex.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b3c492837e6..5195c26623e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -253,17 +253,25 @@ public: m_k.construct_weighted_point_d_object(); #ifdef CGAL_TC_VERBOSE - std::cerr << "Fixing inconsistencies..." << std::endl; + std::cerr << "Fixing inconsistencies..." << std::endl; #endif std::pair stats_before = number_of_inconsistent_simplices(false); #ifdef CGAL_TC_VERBOSE - std::cerr << "Initial number of inconsistencies: " - << stats_before.second << std::endl; + std::cerr << "Initial number of inconsistencies: " + << stats_before.second << std::endl; #endif + if (stats_before.second == 0) + { +#ifdef CGAL_TC_VERBOSE + std::cerr << "Nothing to fix." << std::endl; +#endif + return; + } + bool done = false; while (!done) { @@ -346,6 +354,9 @@ public: // For each cell for ( ; it_c != it_c_end ; ++it_c) { + if (tr.is_infinite(*it_c)) // Don't check infinite cells + continue; + if (!is_simplex_consistent(*it_c)) ++num_inconsistent_simplices; ++num_simplices; From 1b32cc956323190a9356f3b518cc78381c3dfcf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 18 Nov 2014 11:02:18 +0100 Subject: [PATCH 066/269] Fix compilation errors for linux --- .../include/CGAL/Tangential_complex.h | 99 ++++++++++--------- .../CGAL/Tangential_complex/Point_cloud.h | 18 ++-- .../CGAL/Tangential_complex/utilities.h | 16 +-- .../test_tangential_complex.cpp | 2 +- .../test/Tangential_complex/test_utilities.h | 51 +++++----- .../include/CGAL/Delaunay_triangulation.h | 6 +- .../CGAL/IO/Triangulation_off_ostream.h | 4 +- .../include/CGAL/Regular_triangulation.h | 3 +- 8 files changed, 102 insertions(+), 97 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b3c492837e6..d044d3395a2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -96,11 +96,11 @@ class Tangential_complex typedef Tr Triangulation; typedef typename Triangulation::Geom_traits Tr_traits; - typedef typename Triangulation::Point Tr_point; + typedef typename Triangulation::Weighted_point Tr_point; typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; - + typedef std::vector Tangent_space_basis; typedef std::vector Points; @@ -248,8 +248,8 @@ public: void fix_inconsistencies() { - Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); - Kernel::Construct_weighted_point_d cwp = + typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); + typename Kernel::Construct_weighted_point_d cwp = m_k.construct_weighted_point_d_object(); #ifdef CGAL_TC_VERBOSE @@ -330,8 +330,8 @@ public: { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { @@ -341,8 +341,10 @@ public: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); + typename std::vector::const_iterator it_c = + incident_cells.begin(); + typename std::vector::const_iterator it_c_end = + incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { @@ -433,30 +435,26 @@ public: return true; const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); - typedef typename Delaunay_triangulation< - Kernel, - Triangulation_data_structure - < - typename Kernel::Dimension, - Triangulation_vertex - > - > DT; + typedef Delaunay_triangulation + > > DT; typedef typename DT::Vertex_handle DT_VH; typedef typename DT::Finite_full_cell_const_iterator FFC_it; typedef std::set Indexed_simplex; - + //------------------------------------------------------------------------- // Build the ambient Delaunay triangulation // Then save its simplices into "amb_dt_simplices" //------------------------------------------------------------------------- DT ambient_dt(ambient_dim); - std::size_t i = 0; - for (Point const& p : m_points) // CJTODO C++11 + for (std::size_t i=0; idata() = i; - ++i; } std::set amb_dt_simplices; @@ -476,15 +474,15 @@ public: amb_dt_simplices.insert(simplex); } } - + //------------------------------------------------------------------------- // Parse the TC and save its simplices into "stars_simplices" //------------------------------------------------------------------------- std::set stars_simplices; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { @@ -493,9 +491,11 @@ public: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); + + typename std::vector::const_iterator it_c = + incident_cells.begin(); + typename std::vector::const_iterator it_c_end = + incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { @@ -563,8 +563,8 @@ private: struct Tr_vertex_to_global_point { - typedef typename Tr_vertex_handle argument_type; - typedef typename Point result_type; + typedef Tr_vertex_handle argument_type; + typedef Point result_type; Tr_vertex_to_global_point(Points const& points) : m_points(points) {} @@ -580,8 +580,8 @@ private: struct Tr_vertex_to_bare_point { - typedef typename Tr_vertex_handle argument_type; - typedef typename Tr_bare_point result_type; + typedef Tr_vertex_handle argument_type; + typedef Tr_bare_point result_type; Tr_vertex_to_bare_point(Tr_traits const& traits) : m_traits(traits) {} @@ -645,11 +645,11 @@ private: m_k.squared_distance_d_object(); // Triangulation's traits functor & objects - Tr_traits::Squared_distance_d sqdist = + typename Tr_traits::Squared_distance_d sqdist = local_tr_traits.squared_distance_d_object(); - Tr_traits::Point_drop_weight_d drop_w = + typename Tr_traits::Point_drop_weight_d drop_w = local_tr_traits.point_drop_weight_d_object(); - Tr_traits::Center_of_sphere_d center_of_sphere = + typename Tr_traits::Center_of_sphere_d center_of_sphere = local_tr_traits.center_of_sphere_d_object(); // Estimate the tangent space @@ -726,8 +726,10 @@ private: local_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); - for (auto cell : incident_cells) // CJTODO C++11 + for (typename std::vector::iterator cit = + incident_cells.begin(); cit != incident_cells.end(); ++cit) { + Tr_full_cell_handle cell = *cit; if (local_tr.is_infinite(cell)) { star_sphere_squared_radius = boost::none; @@ -979,8 +981,8 @@ private: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end= incident_cells.end(); // For each cell bool found = false; for ( ; !found && it_c != it_c_end ; ++it_c) @@ -1040,9 +1042,9 @@ private: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - std::vector::const_iterator it_c = + typename std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= + typename std::vector::const_iterator it_c_end= incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) @@ -1058,14 +1060,15 @@ private: if (!is_simplex_consistent(c)) { CGAL::Random rng; - for (std::size_t j : c) // CJTODO: C++11 + for (std::set::iterator it=c.begin(); it!=c.end(); ++it) { - m_weights[j] = + m_weights[*it] = rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); } - for (std::size_t j : c) // CJTODO: C++11 - { + for (std::set::iterator it=c.begin(); it!=c.end(); ++it) + { + std::size_t j = *it; #ifdef CGAL_LINKED_WITH_TBB if (j == tr_index) { @@ -1113,8 +1116,8 @@ private: #ifdef CGAL_TC_EXPORT_NORMALS Normals::const_iterator it_n = m_normals.begin(); #endif - Points::const_iterator it_p = m_points.begin(); - Points::const_iterator it_p_end = m_points.end(); + typename Points::const_iterator it_p = m_points.begin(); + typename Points::const_iterator it_p_end = m_points.end(); // For each point p for ( ; it_p != it_p_end ; ++it_p) { @@ -1154,8 +1157,8 @@ private: (Intrinsic_dimension == 1 ? 3 : Intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; - Tr_container::const_iterator it_tr = m_triangulations.begin(); - Tr_container::const_iterator it_tr_end = m_triangulations.end(); + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) { @@ -1173,8 +1176,8 @@ private: std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - std::vector::const_iterator it_c = incident_cells.begin(); - std::vector::const_iterator it_c_end= incident_cells.end(); + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end= incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 3cbd0d16048..334fcbdcb20 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -226,7 +226,7 @@ class Point_cloud_data_structure { public: typedef typename Point_container_::value_type Point; - typedef typename K Kernel; + typedef K Kernel; typedef typename Kernel::FT FT; typedef CGAL::Search_traits< @@ -254,14 +254,12 @@ public: /// Constructor Point_cloud_data_structure(Point_container_ const& points) : m_points(points), - m_tree( - boost::counting_iterator(0), - boost::counting_iterator(points.size()), - Tree::Splitter(), - STraits((Point*)&(points[0])) ) - { - } - + m_tree(boost::counting_iterator(0), + boost::counting_iterator(points.size()), + typename Tree::Splitter(), + STraits((Point*)&(points[0])) ) + { } + /// Constructor Point_cloud_data_structure( Point_container_ const& points, @@ -270,7 +268,7 @@ public: m_tree( boost::counting_iterator(begin_idx), boost::counting_iterator(past_the_end_idx), - Tree::Splitter(), + typename Tree::Splitter(), STraits((Point*)&(points[0])) ) { } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index bcf66a6dda8..3797268d6ae 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -40,22 +40,22 @@ namespace Tangential_complex_ { typedef std::vector Basis; const int D = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar - + // Kernel functors - K::Squared_length_d sqlen = kernel.squared_length_d_object(); - K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); - K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); - K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); + typename K::Squared_length_d sqlen = kernel.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); + typename K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); + typename K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); Basis output_basis; - Basis::const_iterator inb_it = input_basis.begin(); - Basis::const_iterator inb_it_end = input_basis.end(); + 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) { Vector u = *inb_it; - Basis::iterator outb_it = output_basis.begin(); + typename Basis::iterator outb_it = output_basis.begin(); for (int j = 0 ; j < i ; ++j) { Vector const& ej = *outb_it; diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 25006c3ebde..4c4657975e6 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -90,7 +90,7 @@ int main() std::stringstream output_filename; output_filename << "data/test_tc_" << INTRINSIC_DIMENSION << "_in_R" << AMBIENT_DIMENSION << ".off"; - std::ofstream off_stream(output_filename.str()); + std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); double export_time = t.elapsed(); t.reset(); } diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 70212f9b3dd..d75d02527cb 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -39,13 +39,14 @@ sparsify_point_set( typename Kernel::FT min_squared_dist) { typedef typename Point_container::value_type Point; - typedef typename CGAL::Point_cloud_data_structure Points_ds; - + typedef typename CGAL::Tangential_complex_::Point_cloud_data_structure Points_ds; + typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); // Create the output container and push the first point into it std::vector output; - Point_container::const_iterator it_pt = input_pts.begin(); + typename Point_container::const_iterator it_pt = input_pts.begin(); output.push_back(*it_pt); ++it_pt; @@ -74,8 +75,8 @@ std::vector generate_points_on_plane(std::size_t num_p typedef typename Kernel::FT FT; CGAL::Random rng; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT x = rng.get_double(0, 5); FT y = rng.get_double(0, 5); @@ -93,8 +94,8 @@ std::vector generate_points_on_moment_curve( typedef typename Kernel::FT FT; CGAL::Random rng; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT x = rng.get_double(min_x, max_x); std::vector coords; @@ -114,8 +115,8 @@ std::vector generate_points_on_circle_2( typedef typename Kernel::Point_d Point; CGAL::Random_points_on_circle_2 generator(radius); std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -127,8 +128,8 @@ std::vector generate_points_on_sphere_3( typedef typename Kernel::Point_d Point; CGAL::Random_points_on_sphere_3 generator(radius); std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -140,8 +141,8 @@ std::vector generate_points_on_sphere_d( typedef typename Kernel::Point_d Point; CGAL::Random_points_on_sphere_d generator(dim, radius); std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -156,12 +157,12 @@ std::vector generate_points_on_klein_bottle_3D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; + int num_lines = (int)sqrt(num_points); + int num_cols = num_points/num_lines + 1; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) @@ -195,12 +196,12 @@ std::vector generate_points_on_klein_bottle_4D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; + int num_lines = (int)sqrt(num_points); + int num_cols = num_points/num_lines + 1; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) @@ -236,12 +237,12 @@ generate_points_on_klein_bottle_variant_5D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(NUM_POINTS); - int num_cols = NUM_POINTS/num_lines + 1; + int num_lines = (int)sqrt(num_points); + int num_cols = num_points/num_lines + 1; std::vector points; - points.reserve(NUM_POINTS); - for (int i = 0 ; i != NUM_POINTS ; ++i) + points.reserve(num_points); + for (int i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index dfc5ff43210..e30d419b46b 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -75,6 +75,8 @@ public: // PUBLIC NESTED TYPES typedef typename Base::Full_cell_iterator Full_cell_iterator; typedef typename Base::Full_cell_const_handle Full_cell_const_handle; typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; + typedef typename Base::Finite_full_cell_const_iterator + Finite_full_cell_const_iterator; typedef typename Base::size_type size_type; typedef typename Base::difference_type difference_type; @@ -861,8 +863,8 @@ Delaunay_triangulation 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 ) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 590c2a6b0e6..44506b807fa 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -124,8 +124,8 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) std::vector coords; while (line_sstr >> temp) coords.push_back(temp); - - std::vector::iterator last = coords.end() - 1; + + typename std::vector::iterator last = coords.end() - 1; P p = P(coords.begin(), last); wp = WP(p, *last); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index b5174b0f698..0d6dc509f9b 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -68,8 +68,9 @@ public: // PUBLIC NESTED TYPES typedef typename Base::Full_cell Full_cell; typedef typename Base::Facet Facet; typedef typename Base::Face Face; - + typedef Maximal_dimension_ Maximal_dimension; + typedef typename Base::Point Point; typedef typename RTTraits::Bare_point Bare_point; typedef typename RTTraits::Weighted_point Weighted_point; From 3f5bb0cdd54247ed804ad11c004712eb4a69d1b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 18 Nov 2014 11:33:31 +0100 Subject: [PATCH 067/269] Fix trailing whitespace --- .../CGAL/NewKernel_d/Cartesian_filter_K.h | 10 +- .../include/CGAL/Tangential_complex.h | 186 +++++++++--------- .../CGAL/Tangential_complex/Point_cloud.h | 66 +++---- .../test_tangential_complex.cpp | 12 +- .../test/Tangential_complex/test_utilities.h | 10 +- .../include/CGAL/Delaunay_triangulation.h | 36 ++-- .../CGAL/IO/Triangulation_off_ostream.h | 18 +- .../include/CGAL/Regular_triangulation.h | 106 +++++----- 8 files changed, 222 insertions(+), 222 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index 403a0e4d68c..179e97bf016 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -30,7 +30,7 @@ namespace CGAL { template < typename Base_, typename AK_, typename EK_ > struct Cartesian_filter_K : public Base_, - private Store_kernel, private Store_kernel2 + private Store_kernel, private Store_kernel2 { 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 struct Type : Get_type {}; template::type> struct Functor : - Inherit_functor {}; + Inherit_functor {}; template struct Functor { - typedef typename Get_functor::type AP; - typedef typename Get_functor::type EP; - typedef Filtered_predicate2 type; + typedef typename Get_functor::type AP; + typedef typename Get_functor::type EP; + typedef Filtered_predicate2 type; }; // TODO: // template struct Functor : diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d044d3395a2..a505cb47d2a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -66,10 +66,10 @@ namespace CGAL { using namespace Tangential_complex_; - + /// The class Tangential_complex represents a tangential complex template < - typename Kernel, + typename Kernel, int Intrinsic_dimension, typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Regular_triangulation @@ -119,7 +119,7 @@ class Tangential_complex : m_tr(NULL) {} Tr_and_VH(int dim) : m_tr(new Triangulation(dim)) {} - + ~Tr_and_VH() { destroy_triangulation(); } Triangulation & construct_triangulation(int dim) @@ -137,7 +137,7 @@ class Tangential_complex Triangulation & tr() { return *m_tr; } Triangulation const& tr() const { return *m_tr; } - + Tr_vertex_handle const& center_vertex() const { return m_center_vertex; } Tr_vertex_handle & center_vertex() { return m_center_vertex; } @@ -150,23 +150,23 @@ class Tangential_complex typedef typename std::vector TS_container; typedef typename std::vector Tr_container; #ifdef CGAL_LINKED_WITH_TBB - // CJTODO: test other mutexes + // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - typedef tbb::queuing_mutex Tr_mutex; + typedef tbb::queuing_mutex Tr_mutex; #endif #ifdef CGAL_TC_EXPORT_NORMALS typedef typename std::vector Normals; #endif public: - + /// Constructor for a range of points template - Tangential_complex(InputIterator first, InputIterator last, + Tangential_complex(InputIterator first, InputIterator last, const Kernel &k = Kernel()) - : m_k(k), + : m_k(k), m_points(first, last), - m_points_ds(m_points) + m_points_ds(m_points) {} /// Destructor @@ -195,7 +195,7 @@ public: #ifdef CGAL_TC_EXPORT_NORMALS m_normals.resize(m_points.size()); #endif - + #ifdef CGAL_LINKED_WITH_TBB // Parallel if (boost::is_convertible::value) @@ -211,19 +211,19 @@ public: for (std::size_t i = 0 ; i < m_points.size() ; ++i) compute_tangent_triangulation(i); } - + #ifdef CGAL_TC_PROFILING - std::cerr << "Tangential complex computed in " << t.elapsed() + std::cerr << "Tangential complex computed in " << t.elapsed() << " seconds." << std::endl; #endif } - + void refresh_tangential_complex() { #ifdef CGAL_TC_PROFILING Wall_clock_timer t; #endif - + #ifdef CGAL_LINKED_WITH_TBB // Parallel if (boost::is_convertible::value) @@ -239,33 +239,33 @@ public: for (std::size_t i = 0 ; i < m_points.size() ; ++i) compute_tangent_triangulation(i, true); } - + #ifdef CGAL_TC_PROFILING - std::cerr << "Tangential complex refreshed in " << t.elapsed() + std::cerr << "Tangential complex refreshed in " << t.elapsed() << " seconds." << std::endl; #endif } - + void fix_inconsistencies() { typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); typename Kernel::Construct_weighted_point_d cwp = m_k.construct_weighted_point_d_object(); - + #ifdef CGAL_TC_VERBOSE std::cerr << "Fixing inconsistencies..." << std::endl; #endif std::pair stats_before = number_of_inconsistent_simplices(false); - + #ifdef CGAL_TC_VERBOSE - std::cerr << "Initial number of inconsistencies: " + std::cerr << "Initial number of inconsistencies: " << stats_before.second << std::endl; #endif bool done = false; - while (!done) + while (!done) { // CJTODO: the parallel version is not working for now /*#ifdef CGAL_LINKED_WITH_TBB @@ -295,21 +295,21 @@ public: << " * Number of vertices: " << m_points.size() << std::endl << std::endl << " * BEFORE fix_inconsistencies:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " + << " - Total number of simplices in stars (incl. duplicates): " << stats_before.first << std::endl - << " - Number of inconsistent simplices in stars (incl. duplicates): " + << " - Number of inconsistent simplices in stars (incl. duplicates): " << stats_before.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_before.second / stats_before.first << "%" + << " - Percentage of inconsistencies: " + << 100. * stats_before.second / stats_before.first << "%" << std::endl << std::endl << " * AFTER fix_inconsistencies:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " + << " - Total number of simplices in stars (incl. duplicates): " << stats_after.first << std::endl - << " - Number of inconsistent simplices in stars (incl. duplicates): " + << " - Number of inconsistent simplices in stars (incl. duplicates): " << stats_after.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_before.first << "%" + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_before.first << "%" << std::endl << "================================================" << std::endl; #endif @@ -317,7 +317,7 @@ public: stats_before = stats_after; } } - + // Return a pair std::pair number_of_inconsistent_simplices( @@ -360,20 +360,20 @@ public: << "================================================" << std::endl << "Inconsistencies:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices in stars (incl. duplicates): " + << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << std::endl - << " * Number of inconsistent simplices in stars (incl. duplicates): " + << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl - << " * Percentage of inconsistencies: " + << " * Percentage of inconsistencies: " << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl << "================================================" << std::endl; } return std::make_pair(num_simplices, num_inconsistent_simplices); } - + std::ostream &export_to_off( - std::ostream & os, + std::ostream & os, bool color_inconsistencies = false, std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) @@ -386,14 +386,14 @@ public: { std::cerr << "Error: export_to_off => ambient dimension should be >= 2." << std::endl; - os << "Error: export_to_off => ambient dimension should be >= 2." + os << "Error: export_to_off => ambient dimension should be >= 2." << std::endl; return os; } if (ambient_dim > 3) { std::cerr << "Warning: export_to_off => ambient dimension should be " - "<= 3. Only the first 3 coordinates will be exported." + "<= 3. Only the first 3 coordinates will be exported." << std::endl; } @@ -412,22 +412,22 @@ public: std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); export_simplices_to_off( - output, num_simplices, color_inconsistencies, + output, num_simplices, color_inconsistencies, excluded_simplices, show_excluded_vertices_in_color); - + #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; #endif os << "OFF \n" - << num_vertices << " " + << num_vertices << " " << num_simplices << " " << "0 \n" << output.str(); return os; } - + bool check_if_all_simplices_are_in_the_ambient_delaunay( std::set > * incorrect_simplices = NULL) { @@ -456,7 +456,7 @@ public: DT_VH vh = ambient_dt.insert(p); vh->data() = i; } - + std::set amb_dt_simplices; for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; @@ -511,7 +511,7 @@ public: stars_simplices.insert(simplex); } } - + //------------------------------------------------------------------------- // Check if simplices of "stars_simplices" are all in "amb_dt_simplices" //------------------------------------------------------------------------- @@ -521,19 +521,19 @@ public: incorrect_simplices = &diff; set_difference(stars_simplices.begin(), stars_simplices.end(), amb_dt_simplices.begin(), amb_dt_simplices.end(), - std::inserter(*incorrect_simplices, + std::inserter(*incorrect_simplices, incorrect_simplices->begin()) ); if (!incorrect_simplices->empty()) { - std::cerr + std::cerr << "ERROR check_if_all_simplices_are_in_the_ambient_delaunay:" << std::endl - << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << " Number of simplices in ambient DT: " << amb_dt_simplices.size() << std::endl - << " Number of unique simplices in TC stars: " << stars_simplices.size() + << " Number of unique simplices in TC stars: " << stars_simplices.size() << std::endl - << " Number of wrong simplices: " << incorrect_simplices->size() + << " Number of wrong simplices: " << incorrect_simplices->size() << std::endl; return false; } @@ -551,7 +551,7 @@ private: bool operator()(Point const& p1, Point const& p2) { - typename Kernel::Squared_distance_d sqdist = + typename Kernel::Squared_distance_d sqdist = m_k.squared_distance_d_object(); return sqdist(p1, m_ref) < sqdist(p2, m_ref); } @@ -608,7 +608,7 @@ private: // Constructor Compute_tangent_triangulation( Tangential_complex &tc, bool tangent_spaces_are_already_computed = false) - : m_tc(tc), + : m_tc(tc), m_tangent_spaces_are_already_computed(tangent_spaces_are_already_computed) {} @@ -641,7 +641,7 @@ private: // Kernel functor & objects typename Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - typename Kernel::Squared_distance_d k_sqdist = + typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); // Triangulation's traits functor & objects @@ -662,7 +662,7 @@ private: m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif } - + //*************************************************** // Build a minimal triangulation in the tangent space // (we only need the star of p) @@ -678,16 +678,16 @@ private: //const int NUM_NEIGHBORS = 150; //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); - + // While building the local triangulation, we keep the radius - // of the sphere "star sphere" centered at "center_vertex" + // of the sphere "star sphere" centered at "center_vertex" // and which contains all the // circumspheres of the star of "center_vertex" boost::optional star_sphere_squared_radius; // Insert points until we find a point which is outside "star shere" - for (INS_iterator nn_it = ins_range.begin() ; - nn_it != ins_range.end() ; + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; ++nn_it) { std::size_t neighbor_point_idx = nn_it->first; @@ -704,13 +704,13 @@ private: Tr_point proj_pt = project_point_and_compute_weight( neighbor_pt, center_pt, m_tangent_spaces[i], local_tr_traits); - FT squared_dist_to_tangent_plane = + FT squared_dist_to_tangent_plane = local_tr_traits.point_weight_d_object()(proj_pt); FT w = -squared_dist_to_tangent_plane + m_weights[neighbor_point_idx]; Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( drop_w(proj_pt), w); - + Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) @@ -724,7 +724,7 @@ private: // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; local_tr.incident_full_cells( - center_vertex, + center_vertex, std::back_inserter(incident_cells)); for (typename std::vector::iterator cit = incident_cells.begin(); cit != incident_cells.end(); ++cit) @@ -739,7 +739,7 @@ private: { //********************************* // We don't compute the circumsphere of the simplex in the - // local tangent plane since it would involve to take the + // local tangent plane since it would involve to take the // weights of the points into account later // (which is a problem since the ANN is performed on the // points in the ambient dimension) @@ -750,7 +750,7 @@ private: tsb.reserve(Intrinsic_dimension); Point const& orig = m_points[cell->vertex(0)->data()]; for (int ii = 1 ; ii <= Intrinsic_dimension ; ++ii) - { + { tsb.push_back(k_diff_pts( m_points[cell->vertex(ii)->data()], orig)); } @@ -764,12 +764,12 @@ private: proj_pts.push_back(project_point( m_points[cell->vertex(ii)->data()], orig, tsb)); } - + Tr_bare_point c = center_of_sphere( proj_pts.begin(), proj_pts.end()); FT sq_circumdiam = 4.*sqdist(c, proj_pts[0]); - if (!star_sphere_squared_radius + if (!star_sphere_squared_radius || sq_circumdiam > *star_sphere_squared_radius) star_sphere_squared_radius = sq_circumdiam; } @@ -800,7 +800,7 @@ private: // Kernel functors typename Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = + typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); @@ -815,13 +815,13 @@ private: p, NUM_POINTS_FOR_PCA, false); //******************************* PCA ************************************* - + const int amb_dim = m_k.point_dimension_d_object()(p); // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); KNS_iterator nn_it = kns_range.begin(); - for (int j = 0 ; - j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + for (int j = 0 ; + j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { for (int i = 0 ; i < amb_dim ; ++i) @@ -837,14 +837,14 @@ private: for (int i = amb_dim - 1 ; i >= amb_dim - Intrinsic_dimension ; --i) { ts.push_back(constr_vec( - amb_dim, - eig.eigenvectors().col(i).data(), + amb_dim, + eig.eigenvectors().col(i).data(), eig.eigenvectors().col(i).data() + amb_dim)); } #ifdef CGAL_TC_EXPORT_NORMALS *p_normal = constr_vec( - amb_dim, - eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data(), + amb_dim, + eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data(), eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data() + amb_dim); #endif @@ -862,7 +862,7 @@ private: Vector t2(p[1] * t1[2] - p[2] * t1[1], p[2] * t1[0] - p[0] * t1[2], p[0] * t1[1] - p[1] * t1[0]); - + // Normalize t1 and t2 typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); @@ -887,13 +887,13 @@ private: //return compute_gram_schmidt_basis(ts, m_k); */ } - + // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p - Tr_bare_point project_point(const Point &p, const Point &origin, + Tr_bare_point project_point(const Point &p, const Point &origin, const Tangent_space_basis &ts) const { - typename Kernel::Scalar_product_d inner_pdct = + typename Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); @@ -925,7 +925,7 @@ private: m_k.difference_of_points_d_object(); typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); - + Vector v = diff_points(p, origin); std::vector coords; @@ -952,7 +952,7 @@ private: m_k.squared_distance_d_object()(p, projected_pt) ); } - + // A simplex here is a local tri's full cell handle bool is_simplex_consistent(Tr_full_cell_handle fch) { @@ -997,7 +997,7 @@ private: if (!found) return false; } - + return true; } @@ -1101,7 +1101,7 @@ private: num_vertices = 0; return os; } - + // If Intrinsic_dimension = 1, we output each point two times // to be able to export each segment as a flat triangle with 3 different // indices (otherwise, Meshlab detects degenerated simplices) @@ -1109,7 +1109,7 @@ private: const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors - typename Kernel::Compute_coordinate_d coord = + typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); int num_coords = min(ambient_dim, 3); @@ -1128,7 +1128,7 @@ private: os << CGAL::to_double(coord(*it_p, i)) << " "; if (i == 2) os << "0"; - + #ifdef CGAL_TC_EXPORT_NORMALS for (i = 0 ; i < num_coords ; ++i) os << " " << CGAL::to_double(coord(*it_n, i)); @@ -1145,7 +1145,7 @@ private: } std::ostream &export_simplices_to_off( - std::ostream & os, std::size_t &num_simplices, + std::ostream & os, std::size_t &num_simplices, bool color_inconsistencies = false, std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) @@ -1153,7 +1153,7 @@ private: // If Intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) int factor = (Intrinsic_dimension == 1 ? 2 : 1); - int OFF_simplices_dim = + int OFF_simplices_dim = (Intrinsic_dimension == 1 ? 3 : Intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; @@ -1199,10 +1199,10 @@ private: if (Intrinsic_dimension == 1) sstr_c << (data*factor + 1) << " "; - bool excluded = + bool excluded = (excluded_simplices && excluded_simplices->find(c) != excluded_simplices->end()); - + if (!excluded) { os << OFF_simplices_dim << " " << sstr_c.str() << " "; @@ -1217,7 +1217,7 @@ private: } else if (show_excluded_vertices_in_color) { - os << OFF_simplices_dim << " " + os << OFF_simplices_dim << " " << sstr_c.str() << " " << "0 0 255"; ++num_simplices; @@ -1248,13 +1248,13 @@ private: << "================================================" << std::endl << "Export to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices in stars (incl. duplicates): " + << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << std::endl - << " * Number of inconsistent simplices in stars (incl. duplicates): " + << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl - << " * Percentage of inconsistencies: " - << (num_simplices > 0 ? - 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" + << " * Percentage of inconsistencies: " + << (num_simplices > 0 ? + 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" << std::endl << "================================================" << std::endl; #endif @@ -1268,7 +1268,7 @@ private: Weights m_weights; Points_ds m_points_ds; TS_container m_tangent_spaces; - Tr_container m_triangulations; // Contains the triangulations + Tr_container m_triangulations; // Contains the triangulations // and their center vertex #ifdef CGAL_LINKED_WITH_TBB std::vector m_tr_mutexes; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 334fcbdcb20..5b82f49099f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -46,27 +46,27 @@ public: typedef typename Kernel::FT FT; /// The constructor that sets the data set source - Point_cloud_adaptator(Point_container_ &points, Kernel const& k) + Point_cloud_adaptator(Point_container_ &points, Kernel const& k) : m_points(points), m_k(k) {} /// CRTP helper method - inline Point_container_ const& points() const - { + inline Point_container_ const& points() const + { return m_points; - } - inline Point_container_& points() + } + inline Point_container_& points() { return m_points; } // Must return the number of data points - inline size_t kdtree_get_point_count() const + inline size_t kdtree_get_point_count() const { return m_points.size(); } - // Returns the distance between the vector "p1[0:size-1]" + // 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 @@ -76,18 +76,18 @@ public: } // Returns the dim'th component of the idx'th point in the class: - // Since this is inlined and the "dim" argument is typically an + // 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 + // 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 + // 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 + // Look at bb.size() to find out the expected dimensionality // (e.g. 2 or 3 for point clouds) template bool kdtree_get_bbox(Bbox &bb) const @@ -100,7 +100,7 @@ public: return m_k; } -protected: +protected: Point_container_& m_points; //!< A ref to the data set origin Kernel const& m_k; //!< A const ref to the kernel @@ -119,13 +119,13 @@ public: /// Constructor Point_cloud_data_structure(Point_container_ &points, Kernel const& k) : m_adaptor(points, k), - m_kd_tree(AMB_DIM, - m_adaptor, + m_kd_tree(AMB_DIM, + m_adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) { m_kd_tree.buildIndex(); } - + /*Point_container_ &points() { return m_adaptor.points(); @@ -150,19 +150,19 @@ public: nanoflann::KNNResultSet result_set(k); result_set.init(neighbor_indices, squared_distance); m_kd_tree.findNeighbors(result_set, - &sp_vec[0], + &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] << ")" + << " (out_dist_sqr = " << squared_distance[i] << ")" << std::endl; }*/ } - - void query_ball(const Point &sp, + + void query_ball(const Point &sp, const FT radius, std::vector > &neighbors, bool sort_output = true) @@ -182,7 +182,7 @@ public: for (const auto idx_and_dist : neighbors) { std::cout << " * neighbor_indices = " << idx_and_dist.first - << " (out_dist_sqr = " << idx_and_dist.second << ")" + << " (out_dist_sqr = " << idx_and_dist.second << ")" << std::endl; }*/ } @@ -244,7 +244,7 @@ public: typedef K_neighbor_search KNS_range; typedef CGAL::Orthogonal_incremental_neighbor_search< - STraits, Distance, CGAL::Sliding_midpoint, Tree> + STraits, Distance, CGAL::Sliding_midpoint, Tree> Incremental_neighbor_search; typedef typename Incremental_neighbor_search::iterator INS_iterator; typedef Incremental_neighbor_search INS_range; @@ -262,7 +262,7 @@ public: /// Constructor Point_cloud_data_structure( - Point_container_ const& points, + Point_container_ const& points, std::size_t begin_idx, std::size_t past_the_end_idx) : m_points(points), m_tree( @@ -272,7 +272,7 @@ public: STraits((Point*)&(points[0])) ) { } - + /*Point_container_ &points() { return m_points; @@ -283,7 +283,7 @@ public: return m_points; }*/ - KNS_range query_ANN(const + KNS_range query_ANN(const Point &sp, unsigned int k, bool sorted = true) const @@ -292,18 +292,18 @@ public: // 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), + m_tree, + sp, + k, + FT(0), true, Distance_adapter >( (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 @@ -312,11 +312,11 @@ public: Incremental_neighbor_search search( m_tree, sp, - FT(0), + FT(0), true, Distance_adapter >( (Point*)&(m_points[0])) ); - + return search; } @@ -330,4 +330,4 @@ protected: #endif // CGAL_TC_USE_NANOFLANN -#endif // POINT_CLOUD_H \ No newline at end of file +#endif // POINT_CLOUD_H diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 4c4657975e6..90f424c7a84 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -51,8 +51,8 @@ int main() Wall_clock_timer t; CGAL::default_random = CGAL::Random(i); std::cerr << "Random seed = " << i << std::endl; - - std::vector points = + + std::vector points = //generate_points_on_circle_2(NUM_POINTS, 3.); //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); //generate_points_on_plane(NUM_POINTS); @@ -64,12 +64,12 @@ int main() points = sparsify_point_set( k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); - std::cerr << "Number of points after sparsification: " + std::cerr << "Number of points after sparsification: " << points.size() << std::endl; CGAL::Tangential_complex< - Kernel, - INTRINSIC_DIMENSION, + Kernel, + INTRINSIC_DIMENSION, CGAL::Parallel_tag> tc(points.begin(), points.end(), k); double init_time = t.elapsed(); t.reset(); @@ -113,4 +113,4 @@ int main() } return 0; -} \ No newline at end of file +} diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index d75d02527cb..c8296211c8d 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -35,7 +35,7 @@ template std::vector sparsify_point_set( - const Kernel &k, Point_container const& input_pts, + const Kernel &k, Point_container const& input_pts, typename Kernel::FT min_squared_dist) { typedef typename Point_container::value_type Point; @@ -173,13 +173,13 @@ std::vector generate_points_on_klein_bottle_3D( 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); points.push_back(Kernel().construct_point_d_object()( - (a + b*tmp)*cos(u), + (a + b*tmp)*cos(u), (a + b*tmp)*sin(u), b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)))); } @@ -212,7 +212,7 @@ std::vector generate_points_on_klein_bottle_4D( v = 6.2832 * k2 / num_lines; } else - { + { u = rng.get_double(0, 6.2832); v = rng.get_double(0, 6.2832); } @@ -253,7 +253,7 @@ generate_points_on_klein_bottle_variant_5D( v = 6.2832 * k2 / num_lines; } else - { + { u = rng.get_double(0, 6.2832); v = rng.get_double(0, 6.2832); } diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index e30d419b46b..790dc8ef789 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -121,7 +121,7 @@ public: using Base::vertices_begin; using Base::vertices_end; // using Base:: - + private: //*** Side_of_oriented_subsphere_d *** typedef typename Base::Flat_orientation_d Flat_orientation_d; @@ -149,7 +149,7 @@ private: } }; public: - + // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS Delaunay_triangulation(int dim, const Geom_traits &k = Geom_traits()) @@ -158,12 +158,12 @@ public: } // With this constructor, - // the user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension // (= preset_flat_orientation_.first) // It it used by the dark triangulations created by DT::remove Delaunay_triangulation( - int dim, + int dim, const std::pair &preset_flat_orientation, const Geom_traits &k = Geom_traits()) : Base(dim, preset_flat_orientation, k) @@ -178,8 +178,8 @@ public: Side_of_oriented_subsphere_d side_of_oriented_subsphere_predicate() const { return Side_of_oriented_subsphere_d ( - flat_orientation_, - geom_traits().construct_flat_orientation_d_object(), + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), geom_traits().in_flat_side_of_oriented_sphere_d_object() ); } @@ -291,7 +291,7 @@ public: Orientation o = ori_( boost::make_transform_iterator(s->vertices_begin(), spivi), - boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, + boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, spivi)); if( POSITIVE == o ) @@ -320,9 +320,9 @@ public: return pred_(dc_.full_cell(f)->neighbor(dc_.index_of_covertex(f))); } }; - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY - + bool is_valid(bool verbose = false, int level = 0) const; private: @@ -339,7 +339,7 @@ private: Conflict_traversal_pred_in_fullspace; }; -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // FUNCTIONS THAT ARE MEMBER METHODS: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS @@ -530,7 +530,7 @@ Delaunay_triangulation typedef typename Base::template Full_cell_set Dark_full_cells; Dark_full_cells conflict_zone; std::back_insert_iterator dark_out(conflict_zone); - + dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out); // Make the dark simplices in the conflict zone searchable conflict_zone.make_searchable(); @@ -628,7 +628,7 @@ Delaunay_triangulation int li = light_s->index(dark_s->vertex(di)->data()); Rotor light_r(light_s, li, light_i); typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i); - + while( simps.contains(full_cell(light_r)->neighbor(index_of_covertex(light_r))) ) light_r = rotate_rotor(light_r); @@ -856,7 +856,7 @@ template< typename DCTraits, typename TDS > bool Delaunay_triangulation ::is_valid(bool verbose, int level) const -{ +{ if (!Base::is_valid(verbose, level)) return false; @@ -867,16 +867,16 @@ Delaunay_triangulation cit != this->finite_full_cells_end() ; ++cit ) { Full_cell_const_handle ch = cit.base(); - for(int i = 0; i < dim+1 ; ++i ) + for(int i = 0; i < dim+1 ; ++i ) { // If the i-th neighbor is not an infinite cell - Vertex_handle opposite_vh = + Vertex_handle opposite_vh = ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); if (!is_infinite(opposite_vh)) { - Side_of_oriented_sphere_d side = + Side_of_oriented_sphere_d side = geom_traits().side_of_oriented_sphere_d_object(); - if (side(Point_const_iterator(ch->vertices_begin()), + if (side(Point_const_iterator(ch->vertices_begin()), Point_const_iterator(ch->vertices_end()), opposite_vh->point()) == ON_BOUNDED_SIDE) { diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index 44506b807fa..1ca28265e21 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -53,7 +53,7 @@ input_point(std::istream & is, const Traits &traits, P & p) { typedef typename Traits::FT FT; std::vector coords; - + std::string line; for(;;) { @@ -84,7 +84,7 @@ operator>>(std::istream &is, typename Wrap::Point_d & p) typedef typename Wrap::Point_d P; typedef typename K::FT FT; std::vector coords; - + std::string line; for(;;) { @@ -134,7 +134,7 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) template < class GT, class TDS > std::ostream & -export_triangulation_to_off(std::ostream & os, +export_triangulation_to_off(std::ostream & os, const Triangulation & tr, bool in_3D_export_surface_only = false) { @@ -147,7 +147,7 @@ export_triangulation_to_off(std::ostream & os, typedef typename Tr::Full_cell_const_iterator Full_cell_iterator; typedef typename Tr::Full_cell Full_cell; typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator; - + if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3) { std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3."; @@ -158,11 +158,11 @@ export_triangulation_to_off(std::ostream & os, size_t n = tr.number_of_vertices(); std::stringstream output; - + // write the vertices std::map index_of_vertex; int i = 0; - for(Finite_vertex_iterator it = tr.finite_vertices_begin(); + for(Finite_vertex_iterator it = tr.finite_vertices_begin(); it != tr.finite_vertices_end(); ++it, ++i) { Triangulation_IO::output_point(output, tr.geom_traits(), it->point()); @@ -172,7 +172,7 @@ export_triangulation_to_off(std::ostream & os, index_of_vertex[it.base()] = i; } CGAL_assertion( i == n ); - + size_t number_of_triangles = 0; if (tr.maximal_dimension() == 2) { @@ -207,7 +207,7 @@ export_triangulation_to_off(std::ostream & os, output << index_of_vertex[*vit] << " "; } output << std::endl; - ++number_of_triangles; + ++number_of_triangles; } } } @@ -243,7 +243,7 @@ export_triangulation_to_off(std::ostream & os, } os << "OFF \n" - << n << " " + << n << " " << number_of_triangles << " 0\n" << output.str(); diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 0d6dc509f9b..1e424d0b1e2 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -42,15 +42,15 @@ class Regular_triangulation { typedef typename RTTraits::Dimension Maximal_dimension_; typedef typename Default::Get< - TDS_, + TDS_, Triangulation_data_structure< Maximal_dimension_, Triangulation_vertex, - Triangulation_full_cell + Triangulation_full_cell > >::type TDS; typedef Triangulation Base; typedef Regular_triangulation Self; - + typedef typename RTTraits::Orientation_d Orientation_d; typedef typename RTTraits::Construct_weighted_point_d Construct_weighted_point_d; typedef typename RTTraits::Power_test_d Power_test_d; @@ -154,7 +154,7 @@ private: } }; public: - + // - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS Regular_triangulation(int dim, const Geom_traits &k = Geom_traits()) @@ -163,12 +163,12 @@ public: } // With this constructor, - // the user can specify a Flat_orientation_d object to be used for - // orienting simplices of a specific dimension + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension // (= preset_flat_orientation_.first) // It it used by the dark triangulations created by DT::remove Regular_triangulation( - int dim, + int dim, const std::pair &preset_flat_orientation, const Geom_traits &k = Geom_traits()) : Base(dim, preset_flat_orientation, k) @@ -183,8 +183,8 @@ public: Power_test_in_flat_d power_test_in_flat_predicate() const { return Power_test_in_flat_d ( - flat_orientation_, - geom_traits().construct_flat_orientation_d_object(), + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), geom_traits().in_flat_power_test_d_object() ); } @@ -249,13 +249,13 @@ public: return number_of_vertices() - n; } - Vertex_handle insert(const Weighted_point &, - const Locate_type, - const Face &, - const Facet &, + Vertex_handle insert(const Weighted_point &, + const Locate_type, + const Face &, + const Facet &, const Full_cell_handle); - Vertex_handle insert(const Weighted_point & p, + Vertex_handle insert(const Weighted_point & p, const Full_cell_handle start = Full_cell_handle()) { Locate_type lt; @@ -275,14 +275,14 @@ public: Vertex_handle insert_in_conflicting_cell( const Weighted_point &, const Full_cell_handle, const Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle()); - - Vertex_handle insert_if_in_star(const Weighted_point &, - const Vertex_handle, - const Locate_type, - const Face &, - const Facet &, + + Vertex_handle insert_if_in_star(const Weighted_point &, + const Vertex_handle, + const Locate_type, + const Face &, + const Facet &, const Full_cell_handle); - + Vertex_handle insert_if_in_star( const Weighted_point & p, const Vertex_handle star_center, const Full_cell_handle start = Full_cell_handle()) @@ -295,7 +295,7 @@ public: } Vertex_handle insert_if_in_star( - const Weighted_point & p, const Vertex_handle star_center, + const Weighted_point & p, const Vertex_handle star_center, const Vertex_handle hint) { CGAL_assertion( Vertex_handle() != hint ); @@ -351,7 +351,7 @@ public: Orientation o = ori_( boost::make_transform_iterator(s->vertices_begin(), spivi), - boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, + boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, spivi)); if( POSITIVE == o ) @@ -380,16 +380,16 @@ public: return pred_(rt_.full_cell(f)->neighbor(rt_.index_of_covertex(f))); } }; - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY - + bool is_valid(bool verbose = false, int level = 0) const; private: - + template bool - does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end, + does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end, Vertex_handle vh) const { // Check all vertices @@ -408,7 +408,7 @@ private: template void - process_conflict_zone(InputIterator cz_begin, InputIterator cz_end, + process_conflict_zone(InputIterator cz_begin, InputIterator cz_end, OutputIterator vertices_out) const { // Get all vertices @@ -428,10 +428,10 @@ private: } } - + template void - process_cz_vertices_after_insertion(InputIterator vertices_begin, + process_cz_vertices_after_insertion(InputIterator vertices_begin, InputIterator vertices_end) { // Get all vertices @@ -459,14 +459,14 @@ private: Conflict_traversal_pred_in_subspace; typedef Conflict_traversal_predicate Conflict_traversal_pred_in_fullspace; - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MEMBER VARIABLES std::vector m_hidden_points; }; // class Regular_triangulation -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // FUNCTIONS THAT ARE MEMBER METHODS: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS @@ -541,8 +541,8 @@ Regular_triangulation typedef Triangulation_full_cell< Geom_traits, internal::Triangulation::Dark_full_cell_data > Dark_full_cell_base; - typedef Triangulation_data_structure Dark_tds; typedef Regular_triangulation Dark_triangulation; @@ -661,7 +661,7 @@ Regular_triangulation typedef typename Base::template Full_cell_set Dark_full_cells; Dark_full_cells conflict_zone; std::back_insert_iterator dark_out(conflict_zone); - + dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out); // Make the dark simplices in the conflict zone searchable conflict_zone.make_searchable(); @@ -686,8 +686,8 @@ Regular_triangulation dark_incident_s.clear(); dark_out = std::back_inserter(dark_incident_s); dark_side.tds().incident_full_cells(dark_v, dark_out); - for(typename Dark_full_cells::iterator it = dark_incident_s.begin(); - it != dark_incident_s.end(); + for(typename Dark_full_cells::iterator it = dark_incident_s.begin(); + it != dark_incident_s.end(); ++it) { (*it)->data().count_ += 1; @@ -761,7 +761,7 @@ Regular_triangulation int li = light_s->index(dark_s->vertex(di)->data()); Rotor light_r(light_s, li, light_i); typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i); - + while( simps.contains(full_cell(light_r)->neighbor(index_of_covertex(light_r))) ) light_r = rotate_rotor(light_r); @@ -871,9 +871,9 @@ Regular_triangulation template< typename RTTraits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation -::insert_if_in_star(const Weighted_point & p, +::insert_if_in_star(const Weighted_point & p, const Vertex_handle star_center, - const Locate_type lt, const Face & f, const Facet & ft, + const Locate_type lt, const Face & f, const Facet & ft, const Full_cell_handle s) { switch( lt ) @@ -915,7 +915,7 @@ Regular_triangulation template< typename RTTraits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation -::insert_in_conflicting_cell(const Weighted_point & p, +::insert_in_conflicting_cell(const Weighted_point & p, const Full_cell_handle s, const Vertex_handle only_if_this_vertex_is_in_the_cz) { @@ -937,10 +937,10 @@ Regular_triangulation cs.reserve(64); std::back_insert_iterator out(cs); Facet ft = compute_conflict_zone(p, s, out); - + // Check if the CZ contains "only_if_this_vertex_is_in_the_cz" if (only_if_this_vertex_is_in_the_cz != Vertex_handle() - && !does_cell_range_contain_vertex(cs.begin(), cs.end(), + && !does_cell_range_contain_vertex(cs.begin(), cs.end(), only_if_this_vertex_is_in_the_cz)) { return Vertex_handle(); @@ -949,7 +949,7 @@ Regular_triangulation // Otherwise, proceed with the insertion std::vector cz_vertices; cz_vertices.reserve(64); - process_conflict_zone(cs.begin(), cs.end(), + process_conflict_zone(cs.begin(), cs.end(), std::back_inserter(cz_vertices)); Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft); @@ -1030,8 +1030,8 @@ Regular_triangulation if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( - *this, p, - coaffine_orientation_predicate(), + *this, p, + coaffine_orientation_predicate(), power_test_in_flat_predicate()); return c(s); } @@ -1054,8 +1054,8 @@ Regular_triangulation if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( - *this, p, - coaffine_orientation_predicate(), + *this, p, + coaffine_orientation_predicate(), power_test_in_flat_predicate()); Conflict_traversal_pred_in_subspace tp(*this, c); return tds().gather_full_cells(s, tp, out); @@ -1076,7 +1076,7 @@ template< typename RTTraits, typename TDS > bool Regular_triangulation ::is_valid(bool verbose, int level) const -{ +{ if (!Base::is_valid(verbose, level)) return false; @@ -1087,16 +1087,16 @@ Regular_triangulation cit != finite_full_cells_end() ; ++cit ) { Full_cell_const_handle ch = cit.base(); - for(int i = 0; i < dim+1 ; ++i ) + for(int i = 0; i < dim+1 ; ++i ) { // If the i-th neighbor is not an infinite cell - Vertex_handle opposite_vh = + Vertex_handle opposite_vh = ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); if (!is_infinite(opposite_vh)) { - Power_test_d side = + Power_test_d side = geom_traits().power_test_d_object(); - if (side(Point_const_iterator(ch->vertices_begin()), + if (side(Point_const_iterator(ch->vertices_begin()), Point_const_iterator(ch->vertices_end()), opposite_vh->point()) == ON_POSITIVE_SIDE) { From 8be281a33fb67a396b129b6c60351bfd11a64d5f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Dec 2014 12:56:00 +0100 Subject: [PATCH 068/269] Fix a warning: use std::size_t --- .../test/Tangential_complex/test_utilities.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index c8296211c8d..fde74425301 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -237,18 +237,18 @@ generate_points_on_klein_bottle_variant_5D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(num_points); - int num_cols = num_points/num_lines + 1; + std::size_t num_lines = (std::size_t)sqrt(num_points); + std::size_t num_cols = num_points/num_lines + 1; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) { - int k1 = i / num_lines; - int k2 = i % num_lines; + 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; } From 0e089a2081b7c9f845448fb28208c2364568403c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Dec 2014 17:31:25 +0100 Subject: [PATCH 069/269] Use Power_center for the "star sphere" optimization --- .../include/CGAL/Tangential_complex.h | 61 ++++++++----------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ba60601a65e..ea61c4a2450 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -45,7 +45,6 @@ #include #include -#include #include #include @@ -658,10 +657,13 @@ private: // Triangulation's traits functor & objects typename Tr_traits::Squared_distance_d sqdist = local_tr_traits.squared_distance_d_object(); + typename Tr_traits::Point_weight_d point_weight = + local_tr_traits.point_weight_d_object(); typename Tr_traits::Point_drop_weight_d drop_w = local_tr_traits.point_drop_weight_d_object(); - typename Tr_traits::Center_of_sphere_d center_of_sphere = - local_tr_traits.center_of_sphere_d_object(); + /*typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object();*/ // CJTODO + typename Get_functor::type power_center(local_tr_traits); // Estimate the tangent space const Point ¢er_pt = m_points[i]; @@ -695,6 +697,7 @@ private: // and which contains all the // circumspheres of the star of "center_vertex" boost::optional star_sphere_squared_radius; + FT star_sphere_squared_radius_plus_margin = 0; // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; @@ -709,7 +712,8 @@ private: const Point &neighbor_pt = m_points[neighbor_point_idx]; if (star_sphere_squared_radius - && k_sqdist(center_pt, neighbor_pt) > *star_sphere_squared_radius) + && k_sqdist(center_pt, neighbor_pt) + > star_sphere_squared_radius_plus_margin) break; Tr_point proj_pt = project_point_and_compute_weight( @@ -726,6 +730,12 @@ private: //Tr_vertex_handle vh = local_tr.insert(wp); if (vh != Tr_vertex_handle()) { + // CJTODO TEMP TEST + /*if (star_sphere_squared_radius + && k_sqdist(center_pt, neighbor_pt) + > star_sphere_squared_radius_plus_margin) + std::cout << "ARGGGGGGGH" << std::endl;*/ + vh->data() = neighbor_point_idx; // Let's recompute star_sphere_squared_radius @@ -748,41 +758,24 @@ private: } else { - //********************************* - // We don't compute the circumsphere of the simplex in the - // local tangent plane since it would involve to take the - // weights of the points into account later - // (which is a problem since the ANN is performed on the - // points in the ambient dimension) - // Instead, we compute the subspace defined by the simplex - // and we compute the circumsphere in this subspace - // and we extract the diameter - Tangent_space_basis tsb; - tsb.reserve(Intrinsic_dimension); - Point const& orig = m_points[cell->vertex(0)->data()]; - for (int ii = 1 ; ii <= Intrinsic_dimension ; ++ii) - { - tsb.push_back(k_diff_pts( - m_points[cell->vertex(ii)->data()], orig)); - } - tsb = compute_gram_schmidt_basis(tsb, m_k); - - std::vector proj_pts; - proj_pts.reserve(Intrinsic_dimension + 1); + std::vector cell_pts; + cell_pts.reserve(Intrinsic_dimension + 1); // For each point p for (int ii = 0 ; ii <= Intrinsic_dimension ; ++ii) - { - proj_pts.push_back(project_point( - m_points[cell->vertex(ii)->data()], orig, tsb)); - } + cell_pts.push_back(cell->vertex(ii)->point()); - Tr_bare_point c = center_of_sphere( - proj_pts.begin(), proj_pts.end()); + Tr_point c = power_center(cell_pts.begin(), cell_pts.end()); + FT sq_power_sphere_diam = 4*point_weight(c); - FT sq_circumdiam = 4.*sqdist(c, proj_pts[0]); if (!star_sphere_squared_radius - || sq_circumdiam > *star_sphere_squared_radius) - star_sphere_squared_radius = sq_circumdiam; + || sq_power_sphere_diam > *star_sphere_squared_radius) + { + star_sphere_squared_radius = sq_power_sphere_diam; + star_sphere_squared_radius_plus_margin = + CGAL::sqrt(sq_power_sphere_diam) + 0.5*INPUT_SPARSITY; + star_sphere_squared_radius_plus_margin *= + star_sphere_squared_radius_plus_margin; // squared + } } } } From 1172403b97b1ad9352df4dcc9f110612225abb56 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Dec 2014 12:09:12 +0100 Subject: [PATCH 070/269] Simplify computation of the weight (projected points) --- .../include/CGAL/Tangential_complex.h | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ea61c4a2450..76794af0977 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -710,6 +710,7 @@ private: if (neighbor_point_idx != i) { const Point &neighbor_pt = m_points[neighbor_point_idx]; + FT neighbor_weight = m_weights[neighbor_point_idx]; if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) @@ -717,17 +718,11 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, center_pt, m_tangent_spaces[i], local_tr_traits); + neighbor_pt, neighbor_weight, center_pt, m_tangent_spaces[i], + local_tr_traits); - FT squared_dist_to_tangent_plane = - local_tr_traits.point_weight_d_object()(proj_pt); - FT w = -squared_dist_to_tangent_plane + m_weights[neighbor_point_idx]; - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - drop_w(proj_pt), - w); - - Tr_vertex_handle vh = local_tr.insert_if_in_star(wp, center_vertex); - //Tr_vertex_handle vh = local_tr.insert(wp); + Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); + //Tr_vertex_handle vh = local_tr.insert(proj_pt); if (vh != Tr_vertex_handle()) { // CJTODO TEMP TEST @@ -919,7 +914,7 @@ private: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p Tr_point project_point_and_compute_weight( - const Point &p, const Point &origin, const Tangent_space_basis &ts, + const Point &p, FT w, const Point &origin, const Tangent_space_basis &ts, const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); @@ -953,7 +948,7 @@ private: ( tr_traits.construct_point_d_object()( Intrinsic_dimension, coords.begin(), coords.end()), - m_k.squared_distance_d_object()(p, projected_pt) + w - m_k.squared_distance_d_object()(p, projected_pt) ); } From cd1fe19554e060c939ee9d56cd94c146c3cb3885 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Dec 2014 12:09:42 +0100 Subject: [PATCH 071/269] No need to recompute the tangent plane here --- Tangential_complex/include/CGAL/Tangential_complex.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 76794af0977..081d4411e54 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1071,15 +1071,15 @@ private: #ifdef CGAL_LINKED_WITH_TBB if (j == tr_index) { - compute_tangent_triangulation(j); + compute_tangent_triangulation(j, true); } else { Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); - compute_tangent_triangulation(j); + compute_tangent_triangulation(j, true); } #else - compute_tangent_triangulation(j); + compute_tangent_triangulation(j, true); #endif } From 305e02c865598c7da96fb905cfc66dbc8ca569dc Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Dec 2014 18:00:23 +0100 Subject: [PATCH 072/269] Try a new way to solve inconsistencies --- .../include/CGAL/Tangential_complex.h | 120 +++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 081d4411e54..f835510388c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -66,6 +66,19 @@ namespace CGAL { using namespace Tangential_complex_; +class Vertex_data +{ +public: + Vertex_data(std::size_t data = std::numeric_limits::max()) + : m_data(data) + {} + operator std::size_t() { return m_data; } + operator std::size_t() const { return m_data; } + +private: + std::size_t m_data; +}; + /// The class Tangential_complex represents a tangential complex template < typename Kernel, @@ -81,7 +94,7 @@ template < typename Regular_triangulation_euclidean_traits< Epick_d > >::Dimension, Triangulation_vertex > >, std::size_t >, + Epick_d > >, Vertex_data >, Triangulation_full_cell > > > > @@ -448,7 +461,7 @@ public: typedef Delaunay_triangulation + Triangulation_vertex > > DT; typedef typename DT::Vertex_handle DT_VH; typedef typename DT::Finite_full_cell_const_iterator FFC_it; @@ -974,6 +987,8 @@ private: for ( ; it_point_idx != simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; + if (point_idx == std::numeric_limits::max()) + continue; Triangulation const& tr = m_triangulations[point_idx].tr(); Tr_vertex_handle center_vh = m_triangulations[point_idx].center_vertex(); @@ -1037,6 +1052,7 @@ private: Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); + const Tr_traits &local_tr_traits = tr.geom_traits(); std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); @@ -1048,6 +1064,9 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { + +#ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS + std::set c; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) { @@ -1089,6 +1108,103 @@ private: // valid anymore here) break; } +#else + // Inconsistent? + // N.B.: we don't test infinite cells + if (!is_simplex_consistent(*it_c)) + { + // Get the k + 2 closest points + + /*int point_dim = m_k.point_dimension_d_object()(*m_points.begin()); + std::vector center(point_dim, FT(0)); + for (int i = 0 ; i < point_dim ; ++i) + { + for (int j = 0 ; j < Intrinsic_dimension + 1 ; ++j) + { + std::size_t data = (*it_c)->vertex(j)->data(); + const Point &p = m_points[data]; + center[i] += p[i]; + } + center[i] /= (Intrinsic_dimension + 1); + } + Point global_center(center.begin(), center.end());*/ + + std::vector cell_idx; // CJTODO TEMP + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + cell_idx.push_back((*it_c)->vertex(i)->data()); + + std::vector simplex_pts; + for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + simplex_pts.push_back((*it_c)->vertex(i)->point()); + + //typename Tr_traits::Power_center_d power_center = + // local_tr_traits.power_center_d_object(); // CJTODO + typename Get_functor::type power_center(local_tr_traits); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + + // CJTODO URGENT : que se passe-t-il si c'est un simplex infini ? + Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); + Point global_center = m_points[tr_index]; + const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_center = k_transl( + global_center, + k_scaled_vec(tsb[i], coord(local_center, i))); + } + + KNS_range kns_range = m_points_ds.query_ANN(global_center, Intrinsic_dimension + 2); + std::vector neighbors; + for (KNS_iterator nn_it = kns_range.begin() ; + nn_it != kns_range.end() ; + ++nn_it) + { + neighbors.push_back(nn_it->first); + } + + CGAL::Random rng; + for (std::vector::iterator it = neighbors.begin(); + it != neighbors.end() ; + ++it) + { + m_weights[*it] = + rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + } + + for (std::vector::iterator it = neighbors.begin(); + it != neighbors.end() ; + ++it) + { + std::size_t j = *it; +#ifdef CGAL_LINKED_WITH_TBB + if (j == tr_index) + { + compute_tangent_triangulation(j, true); + } + else + { + Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); + compute_tangent_triangulation(j, true); + } +#else + compute_tangent_triangulation(j, true); +#endif + } + + refresh_tangential_complex(); // CJTODO: heavy computation! + + // We will try the other cells next time (incident_cells is not + // valid anymore here) + break; + } + +#endif } } From a35c173f950311b0d1844c49bc1e7b2709a2dd44 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Dec 2014 18:00:44 +0100 Subject: [PATCH 073/269] Use std::size_t everywhere --- .../test/Tangential_complex/test_utilities.h | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index fde74425301..ac930649b3b 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -76,7 +76,7 @@ std::vector generate_points_on_plane(std::size_t num_p CGAL::Random rng; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT x = rng.get_double(0, 5); FT y = rng.get_double(0, 5); @@ -95,7 +95,7 @@ std::vector generate_points_on_moment_curve( CGAL::Random rng; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT x = rng.get_double(min_x, max_x); std::vector coords; @@ -116,7 +116,7 @@ std::vector generate_points_on_circle_2( CGAL::Random_points_on_circle_2 generator(radius); std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -129,7 +129,7 @@ std::vector generate_points_on_sphere_3( CGAL::Random_points_on_sphere_3 generator(radius); std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -142,7 +142,7 @@ std::vector generate_points_on_sphere_d( CGAL::Random_points_on_sphere_d generator(dim, radius); std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) points.push_back(*generator++); return points; } @@ -157,18 +157,18 @@ std::vector generate_points_on_klein_bottle_3D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(num_points); - int num_cols = num_points/num_lines + 1; + std::size_t num_lines = (std::size_t)sqrt(num_points); + std::size_t num_cols = num_points/num_lines + 1; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) { - int k1 = i / num_lines; - int k2 = i % num_lines; + 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; } @@ -196,18 +196,18 @@ std::vector generate_points_on_klein_bottle_4D( CGAL::Random rng; // if uniform - int num_lines = (int)sqrt(num_points); - int num_cols = num_points/num_lines + 1; + std::size_t num_lines = (std::size_t)sqrt(num_points); + std::size_t num_cols = num_points/num_lines + 1; std::vector points; points.reserve(num_points); - for (int i = 0 ; i != num_points ; ++i) + for (std::size_t i = 0 ; i != num_points ; ++i) { FT u, v; if (uniform) { - int k1 = i / num_lines; - int k2 = i % num_lines; + 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; } From 2328dbc852d8024752289416c9345c6269b14515 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Dec 2014 18:47:08 +0100 Subject: [PATCH 074/269] Code clean-up & improvements --- .../include/CGAL/Tangential_complex.h | 66 +++++-------------- .../include/CGAL/Tangential_complex/config.h | 11 +++- 2 files changed, 25 insertions(+), 52 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f835510388c..23d78d93c1c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -241,7 +241,8 @@ public: if (boost::is_convertible::value) { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), - Compute_tangent_triangulation(*this, true) + Compute_tangent_triangulation(*this, + true) //tangent_spaces_are_already_computed ); } // Sequential @@ -249,8 +250,12 @@ public: #endif // CGAL_LINKED_WITH_TBB { for (std::size_t i = 0 ; i < m_points.size() ; ++i) - compute_tangent_triangulation(i, true); + { + compute_tangent_triangulation(i, + true); // tangent_spaces_are_already_computed + } } + #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex refreshed in " << t.elapsed() @@ -1084,25 +1089,7 @@ private: rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); } - for (std::set::iterator it=c.begin(); it!=c.end(); ++it) - { - std::size_t j = *it; -#ifdef CGAL_LINKED_WITH_TBB - if (j == tr_index) - { - compute_tangent_triangulation(j, true); - } - else - { - Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); - compute_tangent_triangulation(j, true); - } -#else - compute_tangent_triangulation(j, true); -#endif - } - - refresh_tangential_complex(); // CJTODO: heavy computation! + refresh_tangential_complex(); // We will try the other cells next time (incident_cells is not // valid anymore here) @@ -1110,7 +1097,6 @@ private: } #else // Inconsistent? - // N.B.: we don't test infinite cells if (!is_simplex_consistent(*it_c)) { // Get the k + 2 closest points @@ -1128,10 +1114,6 @@ private: center[i] /= (Intrinsic_dimension + 1); } Point global_center(center.begin(), center.end());*/ - - std::vector cell_idx; // CJTODO TEMP - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) - cell_idx.push_back((*it_c)->vertex(i)->data()); std::vector simplex_pts; for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) @@ -1148,7 +1130,6 @@ private: typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - // CJTODO URGENT : que se passe-t-il si c'est un simplex infini ? Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; @@ -1159,7 +1140,10 @@ private: k_scaled_vec(tsb[i], coord(local_center, i))); } - KNS_range kns_range = m_points_ds.query_ANN(global_center, Intrinsic_dimension + 2); + KNS_range kns_range = m_points_ds.query_ANN( + global_center, + Intrinsic_dimension + 1 + + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; nn_it != kns_range.end() ; @@ -1176,28 +1160,8 @@ private: m_weights[*it] = rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); } - - for (std::vector::iterator it = neighbors.begin(); - it != neighbors.end() ; - ++it) - { - std::size_t j = *it; -#ifdef CGAL_LINKED_WITH_TBB - if (j == tr_index) - { - compute_tangent_triangulation(j, true); - } - else - { - Tr_mutex::scoped_lock lock(m_tr_mutexes[j]); - compute_tangent_triangulation(j, true); - } -#else - compute_tangent_triangulation(j, true); -#endif - } - - refresh_tangential_complex(); // CJTODO: heavy computation! + + refresh_tangential_complex(); // We will try the other cells next time (incident_cells is not // valid anymore here) @@ -1379,8 +1343,10 @@ private: private: const Kernel m_k; + Points m_points; Weights m_weights; + Points_ds m_points_ds; TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index ce88cf276c4..af37b7e1e47 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -24,14 +24,21 @@ #include //========================= Debugging & profiling ============================= -//#define CGAL_TC_PROFILING +#define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE +// Solving inconsistencies: only change the weights of the inconsistent simplex +// or more? +#define CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS + +// Otherwise... +const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; + //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 50; -const double INPUT_SPARSITY = 0.5; +const double INPUT_SPARSITY = 0.1; #endif // CGAL_TC_CONFIG_H From 6fd090b634e2af7591d90dfd1f211d5051cdea00 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Dec 2014 18:59:16 +0100 Subject: [PATCH 075/269] Much faster sparsification function --- .../test/Tangential_complex/test_utilities.h | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index ac930649b3b..35fb7f48024 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -38,32 +38,58 @@ sparsify_point_set( const Kernel &k, Point_container const& input_pts, typename Kernel::FT min_squared_dist) { - typedef typename Point_container::value_type Point; - typedef typename CGAL::Tangential_complex_::Point_cloud_data_structure Points_ds; + 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::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 and push the first point into it + // Create the output container std::vector output; - typename Point_container::const_iterator it_pt = input_pts.begin(); - output.push_back(*it_pt); - ++it_pt; + + Points_ds points_ds(input_pts); // Parse the following points, and add them if they are not too close to // the other points - std::size_t c = 1; - for ( ; + std::size_t pt_idx = 0; + for (typename Point_container::const_iterator it_pt = input_pts.begin() ; it_pt != input_pts.end(); - ++it_pt) + ++it_pt, ++pt_idx) { - Points_ds points_ds(output, 0, c); - if (points_ds.query_ANN(*it_pt, 1).begin()->second >= min_squared_dist) + INS_range ins_range = points_ds.query_incremental_ANN(*it_pt); + + // Drop it if there is another point that: + // - is closer that min_squared_dist + // - and has a higher index + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) { - output.push_back(*it_pt); - ++c; + std::size_t neighbor_point_idx = nn_it->first; + typename Kernel::FT sq_dist = nn_it->second; + // The neighbor is further, we keep the point + if (sq_dist >= min_squared_dist) + { + output.push_back(*it_pt); + break; + } + // The neighbor is close and it has a higher index + else if (neighbor_point_idx > pt_idx) + break; // We drop the point + // Otherwise, we go the next closest point } } + +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set sparsified in " << t.elapsed() + << " seconds." << std::endl; +#endif return output; } From 9e48b7caf41e6cfea967e5750580c21dbe26fef4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 11 Dec 2014 18:14:09 +0100 Subject: [PATCH 076/269] Add an insert function to the spatial sorting data structure --- .../include/CGAL/Tangential_complex/Point_cloud.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 5b82f49099f..1e466d65049 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -283,6 +283,13 @@ public: 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, From e18ba7133cf30a0babbb6b97685179dd01668bd4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 11 Dec 2014 18:17:32 +0100 Subject: [PATCH 077/269] Add an accurate but slow way to generate a sparse point set --- .../include/CGAL/Tangential_complex/config.h | 3 +- .../test_tangential_complex.cpp | 16 +- .../test/Tangential_complex/test_utilities.h | 183 +++++++++++++++--- 3 files changed, 174 insertions(+), 28 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index af37b7e1e47..ba34aaf568e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -29,13 +29,14 @@ // Solving inconsistencies: only change the weights of the inconsistent simplex // or more? -#define CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS +//#define CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS // Otherwise... const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN +//#define CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 50; diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 90f424c7a84..77102284fbd 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -6,13 +6,13 @@ # define TBB_USE_THREADING_TOOL #endif -#include "test_utilities.h" - #include #include #include #include +#include "test_utilities.h" + #include #include @@ -23,7 +23,7 @@ #ifdef _DEBUG const int NUM_POINTS = 50; #else - const int NUM_POINTS = 100; + const int NUM_POINTS = 10000; #endif int main() @@ -51,7 +51,10 @@ int main() 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 points = //generate_points_on_circle_2(NUM_POINTS, 3.); //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); @@ -61,6 +64,11 @@ int main() //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set generated in " << t_gen.elapsed() + << " seconds." << std::endl; +#endif points = sparsify_point_set( k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 35fb7f48024..53f6e11980e 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -32,6 +32,56 @@ #include #include +// 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 +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(INPUT_SPARSITY*INPUT_SPARSITY)) + : 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 + template std::vector sparsify_point_set( @@ -102,11 +152,21 @@ std::vector generate_points_on_plane(std::size_t num_p CGAL::Random rng; std::vector points; points.reserve(num_points); - for (std::size_t i = 0 ; i != num_points ; ++i) +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) { FT x = rng.get_double(0, 5); FT y = rng.get_double(0, 5); - points.push_back(Kernel().construct_point_d_object()(x, y, 0)); + Point p = Kernel().construct_point_d_object()(x, y, 0); +#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; } @@ -121,15 +181,25 @@ std::vector generate_points_on_moment_curve( CGAL::Random rng; std::vector points; points.reserve(num_points); - for (std::size_t i = 0 ; i != num_points ; ++i) +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) { FT x = rng.get_double(min_x, max_x); std::vector coords; coords.reserve(dim); for (int p = 1 ; p <= dim ; ++p) coords.push_back(std::pow(CGAL::to_double(x), p)); - points.push_back( - Kernel().construct_point_d_object()(dim, coords.begin(), coords.end())); + Point p = Kernel().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; } @@ -142,8 +212,20 @@ std::vector generate_points_on_circle_2( CGAL::Random_points_on_circle_2 generator(radius); std::vector points; points.reserve(num_points); - for (std::size_t i = 0 ; i != num_points ; ++i) - points.push_back(*generator++); +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) + { + Point p = *generator++; +#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; } @@ -155,8 +237,20 @@ std::vector generate_points_on_sphere_3( CGAL::Random_points_on_sphere_3 generator(radius); std::vector points; points.reserve(num_points); - for (std::size_t i = 0 ; i != num_points ; ++i) - points.push_back(*generator++); +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) + { + Point p = *generator++; +#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; } @@ -168,8 +262,20 @@ std::vector generate_points_on_sphere_d( CGAL::Random_points_on_sphere_d generator(dim, radius); std::vector points; points.reserve(num_points); - for (std::size_t i = 0 ; i != num_points ; ++i) - points.push_back(*generator++); +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) + { + Point p = *generator++; +#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; } @@ -188,7 +294,10 @@ std::vector generate_points_on_klein_bottle_3D( std::vector points; points.reserve(num_points); - for (std::size_t i = 0 ; i != num_points ; ++i) +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) { FT u, v; if (uniform) @@ -204,10 +313,17 @@ std::vector generate_points_on_klein_bottle_3D( v = rng.get_double(0, 6.2832); } double tmp = cos(u/2)*sin(v) - sin(u/2)*sin(2.*v); - points.push_back(Kernel().construct_point_d_object()( + Point p = Kernel().construct_point_d_object()( (a + b*tmp)*cos(u), (a + b*tmp)*sin(u), - b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)))); + 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; } @@ -227,7 +343,10 @@ std::vector generate_points_on_klein_bottle_4D( std::vector points; points.reserve(num_points); - for (std::size_t i = 0 ; i != num_points ; ++i) +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) { FT u, v; if (uniform) @@ -242,11 +361,19 @@ std::vector generate_points_on_klein_bottle_4D( u = rng.get_double(0, 6.2832); v = rng.get_double(0, 6.2832); } - points.push_back(Kernel().construct_point_d_object()( - (a + b*cos(v))*cos(u) /*+ rng.get_double(0, 0.01)*/, - (a + b*cos(v))*sin(u) /*+ rng.get_double(0, 0.01)*/, - b*sin(v)*cos(u/2) /*+ rng.get_double(0, 0.01)*/, - b*sin(v)*sin(u/2) /*+ rng.get_double(0, 0.01)*/) ); + Point p = Kernel().construct_point_d_object()( + Kernel().construct_point_d_object()( + (a + b*cos(v))*cos(u) /*+ rng.get_double(0, 0.01)*/, + (a + b*cos(v))*sin(u) /*+ rng.get_double(0, 0.01)*/, + b*sin(v)*cos(u/2) /*+ rng.get_double(0, 0.01)*/, + b*sin(v)*sin(u/2) /*+ rng.get_double(0, 0.01)*/) ); +#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; } @@ -268,7 +395,10 @@ generate_points_on_klein_bottle_variant_5D( std::vector points; points.reserve(num_points); - for (std::size_t i = 0 ; i != num_points ; ++i) +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) { FT u, v; if (uniform) @@ -288,8 +418,15 @@ generate_points_on_klein_bottle_variant_5D( FT x3 = b*sin(v)*cos(u/2); FT x4 = b*sin(v)*sin(u/2); FT x5 = x1 + x2 + x3 + x4; - - points.push_back(Kernel().construct_point_d_object()(x1, x2, x3, x4, x5) ); + + Point p = Kernel().construct_point_d_object()(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; } From 7a05ab7424a596bbea42cd603e72c82e32120a16 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 10:39:35 +0100 Subject: [PATCH 078/269] Faster "star_sphere" test --- .../include/CGAL/Tangential_complex.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 23d78d93c1c..4759c665cae 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,6 +23,7 @@ #define TANGENTIAL_COMPLEX_H #include +const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; #include #include @@ -715,7 +716,6 @@ private: // and which contains all the // circumspheres of the star of "center_vertex" boost::optional star_sphere_squared_radius; - FT star_sphere_squared_radius_plus_margin = 0; // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; @@ -732,7 +732,7 @@ private: if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > star_sphere_squared_radius_plus_margin) + > *star_sphere_squared_radius + SQ_HALF_SPARSITY) break; Tr_point proj_pt = project_point_and_compute_weight( @@ -746,7 +746,7 @@ private: // CJTODO TEMP TEST /*if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > star_sphere_squared_radius_plus_margin) + > *star_sphere_squared_radius + SQ_HALF_SPARSITY) std::cout << "ARGGGGGGGH" << std::endl;*/ vh->data() = neighbor_point_idx; @@ -784,10 +784,6 @@ private: || sq_power_sphere_diam > *star_sphere_squared_radius) { star_sphere_squared_radius = sq_power_sphere_diam; - star_sphere_squared_radius_plus_margin = - CGAL::sqrt(sq_power_sphere_diam) + 0.5*INPUT_SPARSITY; - star_sphere_squared_radius_plus_margin *= - star_sphere_squared_radius_plus_margin; // squared } } } @@ -1085,8 +1081,7 @@ private: CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) { - m_weights[*it] = - rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); } refresh_tangential_complex(); @@ -1157,8 +1152,7 @@ private: it != neighbors.end() ; ++it) { - m_weights[*it] = - rng.get_double(0., (0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY)); + m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); } refresh_tangential_complex(); From 1f4015aedf84bf7681c9b3fd5588190209e60456 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 16:36:27 +0100 Subject: [PATCH 079/269] Added a function to help estimating the intrinsic dimension --- .../include/CGAL/Tangential_complex.h | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 4759c665cae..c74e3fcc64d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -230,6 +230,70 @@ public: << " seconds." << std::endl; #endif } + + void estimate_intrinsic_dimension() + { + const int amb_dim = m_k.point_dimension_d_object()(*m_points.begin()); + + // Kernel functors + typename Kernel::Construct_vector_d constr_vec = + m_k.construct_vector_d_object(); + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename Kernel::Squared_length_d sqlen = + m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Scalar_product_d inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Difference_of_vectors_d diff_vec = + m_k.difference_of_vectors_d_object(); + + std::vector sum_eigen_values(amb_dim, FT(0)); + + Points::const_iterator it_p = m_points.begin(); + Points::const_iterator it_p_end = m_points.end(); + // For each point p + for ( ; it_p != it_p_end ; ++it_p) + { + const Point &p = *it_p; + + KNS_range kns_range = m_points_ds.query_ANN( + p, NUM_POINTS_FOR_PCA, false); + + //******************************* PCA ************************************* + + // One row = one point + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); + KNS_iterator nn_it = kns_range.begin(); + for (int j = 0 ; + j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + ++j, ++nn_it) + { + for (int i = 0 ; i < amb_dim ; ++i) + mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); + } + Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver eig(cov); + + // The eigenvectors are sorted in increasing order of their corresponding + // eigenvalues + Tangent_space_basis ts; + for (int i = 0 ; i < amb_dim ; ++i) + sum_eigen_values[i] += eig.eigenvalues()[i]; + + //************************************************************************* + } + + // CJTODO: replace this by an actual estimation + for (FT v : sum_eigen_values) // CJTODO C++11 + { + std::cout << v << " "; + } + std::cout << "\n"; + } + void refresh_tangential_complex() { From f9bef00845fcf80ddf05238b0d904d867dc233ae Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 16:37:09 +0100 Subject: [PATCH 080/269] Added load_points_from_file --- .../test/Tangential_complex/test_utilities.h | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 53f6e11980e..6499ef9e207 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -144,6 +144,27 @@ sparsify_point_set( return output; } +template +bool load_points_from_file( + const std::string &filename, OutputIterator points) +{ + std::ifstream in(filename); + if (!in.is_open()) + { + std::cerr << "Could not open '" << filename << "'" << std::endl; + return false; + } + + Point p; + int dim_from_file; + in >> dim_from_file; + + while(in >> p) + *points++ = p; + + return true; +} + template std::vector generate_points_on_plane(std::size_t num_points) { From 8b0993375203c227db2004a86a179ae7bd84757e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 16:39:15 +0100 Subject: [PATCH 081/269] Forgot to add the StdAfx files --- .../test/Tangential_complex/StdAfx.cpp | 2 ++ Tangential_complex/test/Tangential_complex/StdAfx.h | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 Tangential_complex/test/Tangential_complex/StdAfx.cpp create mode 100644 Tangential_complex/test/Tangential_complex/StdAfx.h diff --git a/Tangential_complex/test/Tangential_complex/StdAfx.cpp b/Tangential_complex/test/Tangential_complex/StdAfx.cpp new file mode 100644 index 00000000000..15668dcadef --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/StdAfx.cpp @@ -0,0 +1,2 @@ +// Build the precompiled headers. +#include "StdAfx.h" \ No newline at end of file diff --git a/Tangential_complex/test/Tangential_complex/StdAfx.h b/Tangential_complex/test/Tangential_complex/StdAfx.h new file mode 100644 index 00000000000..221d2a763cd --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/StdAfx.h @@ -0,0 +1,13 @@ +#ifndef STDAFX_H +#define STDAFX_H + +// CGAL +#include +#include +#include +#include +#include +#include +#include + +#endif //STDAFX_H \ No newline at end of file From 3557c382458a00a3603f125bc8397d331d092a69 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Dec 2014 16:41:00 +0100 Subject: [PATCH 082/269] Remove unused variables --- Tangential_complex/include/CGAL/Tangential_complex.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c74e3fcc64d..51dc9a41639 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -236,18 +236,8 @@ public: const int amb_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors - typename Kernel::Construct_vector_d constr_vec = - m_k.construct_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = + typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - typename Kernel::Squared_length_d sqlen = - m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = - m_k.scaled_vector_d_object(); - typename Kernel::Scalar_product_d inner_pdct = - m_k.scalar_product_d_object(); - typename Kernel::Difference_of_vectors_d diff_vec = - m_k.difference_of_vectors_d_object(); std::vector sum_eigen_values(amb_dim, FT(0)); From 68a4eb92af1702ea556e64338f6568e1e8232ca1 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 09:21:28 +0100 Subject: [PATCH 083/269] Added the ability to limit the number of points loaded from a file --- .../test/Tangential_complex/test_utilities.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 6499ef9e207..9ada2a42ce9 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -146,7 +146,8 @@ sparsify_point_set( template bool load_points_from_file( - const std::string &filename, OutputIterator points) + const std::string &filename, OutputIterator points, + std::size_t only_first_n_points = std::numeric_limits::max()) { std::ifstream in(filename); if (!in.is_open()) @@ -159,8 +160,12 @@ bool load_points_from_file( int dim_from_file; in >> dim_from_file; - while(in >> p) + std::size_t i = 0; + while(i < only_first_n_points && in >> p) + { *points++ = p; + ++i; + } return true; } From b11c4cc8ffae1a8bcdbcc0c51e4c086cc2dcc0a6 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 20:26:02 +0100 Subject: [PATCH 084/269] Add a benchmark --- .../Tangential_complex/CMakeLists.txt | 77 ++++++ .../benchmark/Tangential_complex/StdAfx.cpp | 2 + .../benchmark/Tangential_complex/StdAfx.h | 14 ++ .../Tangential_complex/XML_exporter.h | 236 ++++++++++++++++++ .../Tangential_complex/benchmark_tc.cpp | 216 ++++++++++++++++ 5 files changed, 545 insertions(+) create mode 100644 Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt create mode 100644 Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp create mode 100644 Tangential_complex/benchmark/Tangential_complex/StdAfx.h create mode 100644 Tangential_complex/benchmark/Tangential_complex/XML_exporter.h create mode 100644 Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp diff --git a/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt new file mode 100644 index 00000000000..7155f246c2b --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt @@ -0,0 +1,77 @@ +# 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} ) + + 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() + diff --git a/Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp b/Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp new file mode 100644 index 00000000000..15668dcadef --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp @@ -0,0 +1,2 @@ +// Build the precompiled headers. +#include "StdAfx.h" \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/StdAfx.h b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h new file mode 100644 index 00000000000..df71d9a8260 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h @@ -0,0 +1,14 @@ +#ifndef STDAFX_H +#define STDAFX_H + +// CGAL +#include +#include +//#include +//#include +//#include +//#include +//#include +#include + +#endif //STDAFX_H \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/XML_exporter.h b/Tangential_complex/benchmark/Tangential_complex/XML_exporter.h new file mode 100644 index 00000000000..158d3d648d4 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/XML_exporter.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 +#include +#include +#include +#include + +template +class Simple_XML_exporter +{ +public: + typedef value_type Value_type; + typedef std::vector Element; + typedef std::map Element_with_map; + typedef std::vector List_of_elements; + + Simple_XML_exporter( + const std::string &list_name, + const std::string &element_name, + const std::vector &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::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::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 << "" << 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::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::const_iterator + it_subelement_name_end = m_subelement_names.end(); + + if (m_add_timestamp) + xmlfile << " " << time(NULL) << " " << std::endl; + + for (int i = 0 ; + it_subelement_name != it_subelement_name_end ; + ++it_subelement_name, ++i) + { + xmlfile + << " <" << *it_subelement_name << "> " + << (*it_element)[i] + << " " << std::endl; + } + xmlfile << " " << std::endl; + } + + xmlfile << "" << std::endl; + xmlfile.close(); + return 0; + + } + +protected: + std::string m_list_name; + std::string m_element_name; + std::vector m_subelement_names; + List_of_elements m_list_of_elements; + bool m_add_timestamp; +}; + + + + + +template +class Streaming_XML_exporter +{ +public: + typedef value_type Value_type; + typedef std::vector Element; + typedef std::map Element_with_map; + typedef std::vector List_of_elements; + + Streaming_XML_exporter( + const std::string &filename, + const std::string &list_name, + const std::string &element_name, + const std::vector &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 << "" << 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::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::const_iterator + it_subelement_name_end = m_subelement_names.end(); + + if (m_add_timestamp) + { + m_xml_fstream << " " << time(NULL) << " " << 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] + << " " << std::endl; + } + m_xml_fstream << " " << 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 << "" << 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::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::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 m_subelement_names; + bool m_add_timestamp; +}; diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp new file mode 100644 index 00000000000..391d5162155 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -0,0 +1,216 @@ +#include +#include +#include +#include + +#include "../../test/Tangential_complex/test_utilities.h" + + +#include +#include + +#ifdef CGAL_LINKED_WITH_TBB +# include +#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); + +class XML_perf_data +{ +public: + typedef Streaming_XML_exporter 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 + 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 << "Performance_log_" << time(0) << ".xml"; + return sstr.str(); + } + + static std::vector construct_subelements_names() + { + std::vector subelements; + subelements.push_back("Name"); + subelements.push_back("Intrinsic_dim"); + subelements.push_back("Ambient_dim"); + subelements.push_back("Num_points"); + subelements.push_back("Noise"); + subelements.push_back("Init_time"); + subelements.push_back("Comput_time"); + subelements.push_back("Fix_time"); + + return subelements; + } + + void set_data(const std::string &name, const std::string &value) + { + m_current_element[name] = value; + } + + template + 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; +}; + +#ifdef _DEBUG + const int NUM_POINTS = 50; +#else + const int NUM_POINTS = 30000; +#endif + +int main() +{ +#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 = 2; + const int AMBIENT_DIMENSION = 4; + + typedef CGAL::Epick_d > Kernel; + typedef Kernel::FT FT; + typedef Kernel::Point_d Point; + + 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 points; + //load_points_from_file( + // "data/points_10_10k.cin", std::back_inserter(points)/*, 600*/); + + std::vector points = + //generate_points_on_circle_2(NUM_POINTS, 3.); + //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); + //generate_points_on_plane(NUM_POINTS); + //generate_points_on_sphere_3(NUM_POINTS, 3.0); + //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); + //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); + generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + + + CGAL_TC_SET_PERFORMANCE_DATA("Name", "Klein bottle 4D"); + CGAL_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", INTRINSIC_DIMENSION); + CGAL_TC_SET_PERFORMANCE_DATA("Ambient_dim", AMBIENT_DIMENSION); + CGAL_TC_SET_PERFORMANCE_DATA("Noise", 0.01); + +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set generated in " << t_gen.elapsed() + << " seconds." << std::endl; +#endif + + std::cerr << "Number of points before sparsification: " + << points.size() << std::endl; + //points = sparsify_point_set( + // k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + std::cerr << "Number of points after sparsification: " + << points.size() << std::endl; + + CGAL::Tangential_complex< + Kernel, + INTRINSIC_DIMENSION, + CGAL::Parallel_tag> tc(points.begin(), points.end(), k); + double init_time = t.elapsed(); t.reset(); + + //tc.estimate_intrinsic_dimension(); + tc.compute_tangential_complex(); + double computation_time = t.elapsed(); t.reset(); + + std::set > incorrect_simplices; + //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + + t.reset(); + tc.fix_inconsistencies(); + double fix_time = t.elapsed(); t.reset(); + + double export_time = -1.; + if (INTRINSIC_DIMENSION <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION + << "_in_R" << AMBIENT_DIMENSION << ".off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + double export_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 + << " * Fix inconsistencies: " << fix_time << std::endl + << " * Export to OFF: " << export_time << std::endl + << "================================================" << std::endl + << std::endl; + + CGAL_TC_SET_PERFORMANCE_DATA("Num_points", tc.number_of_vertices()); + CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); + CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); + CGAL_TC_SET_PERFORMANCE_DATA("Fix_time", fix_time); + } + + return 0; +} From dfbf8877514edba2cd53eaf6f54725072af69a88 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 20:29:19 +0100 Subject: [PATCH 085/269] Add TBB_USE_THREADING_TOOL in debug mode --- .../include/CGAL/Tangential_complex/config.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index ba34aaf568e..0715205be72 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -23,6 +23,14 @@ #include +// 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 + + //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE From 248c4b915da5c63fcfe83fc2b98bbfa60c709634 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 20:46:30 +0100 Subject: [PATCH 086/269] Comment mutexes out since we don't use them for now --- Tangential_complex/include/CGAL/Tangential_complex.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 51dc9a41639..abdca05b836 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -58,7 +58,7 @@ const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; #ifdef CGAL_LINKED_WITH_TBB # include -# include +//# include #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) @@ -165,7 +165,7 @@ class Tangential_complex #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - typedef tbb::queuing_mutex Tr_mutex; + //typedef tbb::queuing_mutex Tr_mutex; #endif #ifdef CGAL_TC_EXPORT_NORMALS typedef typename std::vector Normals; @@ -201,7 +201,7 @@ public: // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); #ifdef CGAL_LINKED_WITH_TBB - m_tr_mutexes.resize(m_points.size()); + //m_tr_mutexes.resize(m_points.size()); #endif m_tangent_spaces.resize(m_points.size()); m_weights.resize(m_points.size(), FT(0)); @@ -1102,7 +1102,7 @@ private: std::size_t tr_index) { #ifdef CGAL_LINKED_WITH_TBB - Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); + //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif Triangulation const& tr = m_triangulations[tr_index].tr(); @@ -1400,7 +1400,7 @@ private: Tr_container m_triangulations; // Contains the triangulations // and their center vertex #ifdef CGAL_LINKED_WITH_TBB - std::vector m_tr_mutexes; + //std::vector m_tr_mutexes; #endif #ifdef CGAL_TC_EXPORT_NORMALS Normals m_normals; From 785ac9690ce2be5b475494526219d32dbe2f5374 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 21:58:06 +0100 Subject: [PATCH 087/269] Update PCH --- .../benchmark/Tangential_complex/StdAfx.h | 10 +++++----- Tangential_complex/test/Tangential_complex/StdAfx.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/StdAfx.h b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h index df71d9a8260..573345d0022 100644 --- a/Tangential_complex/benchmark/Tangential_complex/StdAfx.h +++ b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h @@ -4,11 +4,11 @@ // CGAL #include #include -//#include -//#include -//#include -//#include -//#include +#include +#include +#include +#include +#include #include #endif //STDAFX_H \ No newline at end of file diff --git a/Tangential_complex/test/Tangential_complex/StdAfx.h b/Tangential_complex/test/Tangential_complex/StdAfx.h index 221d2a763cd..573345d0022 100644 --- a/Tangential_complex/test/Tangential_complex/StdAfx.h +++ b/Tangential_complex/test/Tangential_complex/StdAfx.h @@ -2,6 +2,7 @@ #define STDAFX_H // CGAL +#include #include #include #include From 035f87a65f6a606645e75a5b2caf0da274041790 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 21:58:34 +0100 Subject: [PATCH 088/269] Minor optimizations + comments --- Triangulation/include/CGAL/Triangulation_data_structure.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index bdbc16e7ad0..76c1ff84445 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -713,7 +713,9 @@ Triangulation_data_structure } } } - 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; } @@ -999,7 +1001,7 @@ Triangulation_data_structure associate_vertex_with_full_cell(new_s, facet_index, v); set_neighbors(new_s, facet_index, - neighbor(old_s, facet_index), + outside_neighbor, mirror_index(old_s, facet_index)); // add the new full_cell to the list of new full_cells From 7bcf0e6e3bfb3c98df1301d4fe76ebc836bd3cd7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 Dec 2014 22:00:26 +0100 Subject: [PATCH 089/269] Add sparsification to the benchmark --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 391d5162155..ad910233802 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -156,8 +156,8 @@ int main() std::cerr << "Number of points before sparsification: " << points.size() << std::endl; - //points = sparsify_point_set( - // k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + points = sparsify_point_set( + k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); std::cerr << "Number of points after sparsification: " << points.size() << std::endl; From 786f40d3769b66229268088d78d78ebf62c46e77 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 19 Dec 2014 07:16:31 +0100 Subject: [PATCH 090/269] "fix_inconsistencies" now returns the number of steps it took --- Tangential_complex/include/CGAL/Tangential_complex.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index abdca05b836..c5259f7eb8c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -318,7 +318,7 @@ public: #endif } - void fix_inconsistencies() + unsigned int fix_inconsistencies() { typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); typename Kernel::Construct_weighted_point_d cwp = @@ -341,10 +341,11 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Nothing to fix." << std::endl; #endif - return; + return 0; } bool done = false; + unsigned int num_steps = 0; while (!done) { // CJTODO: the parallel version is not working for now @@ -395,7 +396,10 @@ public: #endif done = (stats_after.second == 0); stats_before = stats_after; + ++num_steps; } + + return num_steps; } From 1885d666c751c7a1b48b51056691f90d0fbe3708 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 19 Dec 2014 12:04:56 +0100 Subject: [PATCH 091/269] Added new refresh strategy + better benchmark --- .../Tangential_complex/benchmark_tc.cpp | 33 ++++++++++++++----- .../include/CGAL/Tangential_complex.h | 12 +++++-- .../include/CGAL/Tangential_complex/config.h | 8 ++++- .../test/Tangential_complex/test_utilities.h | 10 +++--- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ad910233802..26606958ab2 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -52,7 +52,7 @@ protected: static std::string build_filename() { std::stringstream sstr; - sstr << "Performance_log_" << time(0) << ".xml"; + sstr << "perf_logs/Performance_log_" << time(0) << ".xml"; return sstr.str(); } @@ -64,9 +64,11 @@ protected: subelements.push_back("Ambient_dim"); subelements.push_back("Num_points"); subelements.push_back("Noise"); + subelements.push_back("Info"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); subelements.push_back("Fix_time"); + subelements.push_back("Fix_steps"); return subelements; } @@ -94,6 +96,7 @@ protected: XML_exporter::Element_with_map m_current_element; }; +const double NOISE = 0.01; #ifdef _DEBUG const int NUM_POINTS = 50; #else @@ -117,9 +120,11 @@ int main() typedef Kernel::FT FT; typedef Kernel::Point_d Point; - int i = 0; bool stop = false; - //for ( ; !stop ; ++i) + //for (int i = 0, NUM_POINTS = 10000 ; + // NUM_POINTS <= 50000 && !stop ; + // ++i, NUM_POINTS += (i%3 == 0 ? 5000 : 0)) + for (int i = 0 ; i < 5 && !stop ; ++i) { Kernel k; Wall_clock_timer t; @@ -140,14 +145,22 @@ int main() //generate_points_on_sphere_3(NUM_POINTS, 3.0); //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3., NOISE); //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); CGAL_TC_SET_PERFORMANCE_DATA("Name", "Klein bottle 4D"); CGAL_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", INTRINSIC_DIMENSION); CGAL_TC_SET_PERFORMANCE_DATA("Ambient_dim", AMBIENT_DIMENSION); - CGAL_TC_SET_PERFORMANCE_DATA("Noise", 0.01); + CGAL_TC_SET_PERFORMANCE_DATA("Noise", NOISE); + XML_perf_data::set("Info", "" +#ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS + "ONLY_CHANGE_SIMPLEX_WEIGHTS " +#endif +#ifdef CGAL_TC_GLOBAL_REFRESH + "GLOBAL_REFRESH " +#endif + ); #ifdef CGAL_TC_PROFILING std::cerr << "Point set generated in " << t_gen.elapsed() @@ -175,7 +188,7 @@ int main() //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); t.reset(); - tc.fix_inconsistencies(); + unsigned int num_fix_steps = tc.fix_inconsistencies(); double fix_time = t.elapsed(); t.reset(); double export_time = -1.; @@ -197,11 +210,11 @@ int main() << "================================================" << std::endl << "Number of vertices: " << tc.number_of_vertices() << std::endl << "Computation times (seconds): " << std::endl - << " * Tangential complex: " << init_time + computation_time - << std::endl + << " * Tangential complex: " << init_time + computation_time < stats_after = number_of_inconsistent_simplices(false); @@ -1141,8 +1145,10 @@ private: { m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); } - + +#if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); +#endif // We will try the other cells next time (incident_cells is not // valid anymore here) @@ -1212,8 +1218,10 @@ private: { m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); } - + +#if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); +#endif // We will try the other cells next time (incident_cells is not // valid anymore here) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 0715205be72..87e009191b7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -45,9 +45,15 @@ const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN //#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 //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 50; -const double INPUT_SPARSITY = 0.1; +const double INPUT_SPARSITY = 0.05; #endif // CGAL_TC_CONFIG_H diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 9ada2a42ce9..95a4a9d20e7 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -357,7 +357,7 @@ std::vector generate_points_on_klein_bottle_3D( // a = big radius, b = small radius template std::vector generate_points_on_klein_bottle_4D( - std::size_t num_points, double a, double b, bool uniform = false) + 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; @@ -389,10 +389,10 @@ std::vector generate_points_on_klein_bottle_4D( } Point p = Kernel().construct_point_d_object()( Kernel().construct_point_d_object()( - (a + b*cos(v))*cos(u) /*+ rng.get_double(0, 0.01)*/, - (a + b*cos(v))*sin(u) /*+ rng.get_double(0, 0.01)*/, - b*sin(v)*cos(u/2) /*+ rng.get_double(0, 0.01)*/, - b*sin(v)*sin(u/2) /*+ rng.get_double(0, 0.01)*/) ); + (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; From e301781a26c3abde8c9b38aee13d6f2366c5a9c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 2 Jan 2015 17:35:36 +0100 Subject: [PATCH 092/269] Fixed TDS's incident_faces() using the wrong index for the first vertex (and added consts) (cherry picked from commit e312d7ddae0188ed0d99b4247f73871a57124f41) --- Triangulation/include/CGAL/Triangulation.h | 2 +- .../include/CGAL/Triangulation_data_structure.h | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index db57b817ddc..2dee695b77a 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -567,7 +567,7 @@ public: } template< typename OutputIterator > - OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) + OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) const { return tds().incident_faces(v, d, out); } diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 76c1ff84445..94818cc4627 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -624,10 +624,10 @@ public: return incident_faces(v, dim, out, std::less(), true); } template< typename OutputIterator, typename Comparator > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); + OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false) const; template< typename OutputIterator > OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, - std::less = std::less(), bool = false); + std::less = std::less(), bool = false) const; #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INPUT / OUTPUT @@ -725,7 +725,7 @@ template< typename OutputIterator > OutputIterator Triangulation_data_structure ::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, - std::less cmp, bool upper_faces) + std::less cmp, bool upper_faces) const { return incident_faces >(v, dim, out, cmp, upper_faces); } @@ -735,7 +735,7 @@ template< class Dim, class Vb, class Fcb > template< typename OutputIterator, typename Comparator > OutputIterator Triangulation_data_structure -::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp, bool upper_faces) +::incident_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp, bool upper_faces) const { CGAL_precondition( 0 < dim ); if( dim >= current_dimension() ) @@ -789,13 +789,13 @@ Triangulation_data_structure // init state for enumerating all candidate faces: internal::Combination_enumerator f_idx(dim, v_idx + 1, current_dimension()); Face f(*s); - f.set_index(0, v_idx); + f.set_index(0, sorted_idx[v_idx]); while( ! f_idx.end() ) { - // check if face has already been found for( int i = 0; i < dim; ++i ) f.set_index(1 + i, sorted_idx[f_idx[i]]); - face_set.insert(f); + face_set.insert(f); // checks if face has already been found + // compute next sorted face (lexicographic enumeration) ++f_idx; } From 0b33b86e99a10818b1a4d4ebb69e00b1a7511498 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 08:49:47 +0100 Subject: [PATCH 093/269] Fix the FIXMEs: "infinite vertex is NOT at index 0 a priori" (cherry picked from commit bb654aec952f98e71a47cd9221fd06e9f0d3c02f) --- Triangulation/include/CGAL/Regular_triangulation.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 2755add7ab1..9b84a1d80d1 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -799,8 +799,9 @@ Regular_triangulation reset_flat_orientation(); if( 1 <= current_dimension() ) { - // FIXME: infinite vertex is NOT at index 0 a priori. - Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); Orientation o = orientation(s); CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) @@ -858,8 +859,9 @@ Regular_triangulation v->set_point(p); if( current_dimension() >= 1 ) { - // FIXME: infinite vertex is NOT at index 0 a priori. - Full_cell_handle s = infinite_vertex()->full_cell()->neighbor(0); + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); Orientation o = orientation(s); CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) From dfc8038579d976685cf4af20e8059dc9de7daaf0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 12 Jan 2015 17:57:29 +0100 Subject: [PATCH 094/269] Add code to load points from a file (commented) --- .../test/Tangential_complex/test_tangential_complex.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 77102284fbd..ed25c17c1f1 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -55,6 +55,7 @@ int main() #ifdef CGAL_TC_PROFILING Wall_clock_timer t_gen; #endif + std::vector points = //generate_points_on_circle_2(NUM_POINTS, 3.); //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); @@ -64,7 +65,12 @@ int main() //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); - + + // LOAD FROM A FILE + //std::vector points; + //load_points_from_file( + // "data/points_10_10k.cin", std::back_inserter(points)); + #ifdef CGAL_TC_PROFILING std::cerr << "Point set generated in " << t_gen.elapsed() << " seconds." << std::endl; From 614add44becd8412afe91c82c2f4e293cc80fa00 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 13 Jan 2015 15:27:21 +0100 Subject: [PATCH 095/269] Added a trace in verbose mode --- Tangential_complex/test/Tangential_complex/test_utilities.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 95a4a9d20e7..9ed98fa4c20 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -167,6 +167,10 @@ bool load_points_from_file( ++i; } +#ifdef CGAL_TC_VERBOSE + std::cerr << "'" << filename << "' loaded." << std::endl; +#endif + return true; } From a2423310b170e1a0f77f0bf0c20c9c3d2f39659d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 15 Jan 2015 15:39:25 +0100 Subject: [PATCH 096/269] Handles the case when the local triangulation has a dimension < intrinsic dim --- .../include/CGAL/Tangential_complex.h | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 1959d0270f2..0f007443c75 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -439,7 +439,7 @@ public: if (tr.is_infinite(*it_c)) // Don't check infinite cells continue; - if (!is_simplex_consistent(*it_c)) + if (!is_simplex_consistent(*it_c, tr.current_dimension())) ++num_inconsistent_simplices; ++num_simplices; } @@ -596,7 +596,7 @@ public: continue; } Indexed_simplex simplex; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) simplex.insert((*it_c)->vertex(i)->data()); stars_simplices.insert(simplex); @@ -1029,10 +1029,10 @@ private: } // A simplex here is a local tri's full cell handle - bool is_simplex_consistent(Tr_full_cell_handle fch) + bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) { std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < cur_dim + 1 ; ++i) { std::size_t data = fch->vertex(i)->data(); c.insert(data); @@ -1043,6 +1043,8 @@ private: // A simplex here is a list of point indices bool is_simplex_consistent(std::set const& simplex) { + int cur_dim_plus_1 = static_cast(simplex.size()); + // Check if the simplex is in the stars of all its vertices std::set::const_iterator it_point_idx = simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p @@ -1065,7 +1067,7 @@ private: for ( ; !found && it_c != it_c_end ; ++it_c) { std::set cell; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < cur_dim_plus_1 ; ++i) cell.insert((*it_c)->vertex(i)->data()); if (cell == simplex) found = true; @@ -1116,6 +1118,7 @@ private: Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); const Tr_traits &local_tr_traits = tr.geom_traits(); + int cur_dim = tr.current_dimension(); std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); @@ -1127,11 +1130,10 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { - #ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS std::set c; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) { std::size_t data = (*it_c)->vertex(i)->data(); c.insert(data); @@ -1140,6 +1142,8 @@ private: // Inconsistent? if (!is_simplex_consistent(c)) { + //m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); + //break; // CJTODO TEMP CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) { @@ -1156,7 +1160,7 @@ private: } #else // Inconsistent? - if (!is_simplex_consistent(*it_c)) + if (!is_simplex_consistent(*it_c, cur_dim)) { // Get the k + 2 closest points @@ -1175,7 +1179,7 @@ private: Point global_center(center.begin(), center.end());*/ std::vector simplex_pts; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < cur_dim + 1 ; ++i) simplex_pts.push_back((*it_c)->vertex(i)->point()); //typename Tr_traits::Power_center_d power_center = From c4820faa1b0cd56092112df585d657d1de49c0da Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 15 Jan 2015 15:46:00 +0100 Subject: [PATCH 097/269] Restore original code --- .../include/CGAL/Tangential_complex/Point_cloud.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 1e466d65049..4c6c2904003 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -141,12 +141,9 @@ public: size_t *neighbor_indices, FT *squared_distance) const { - /*std::vector sp_vec( + std::vector sp_vec( m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), - m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));*/ // CJTODO remettre - std::vector sp_vec; - for (int i = 0 ; i < 4 ; ++i) - sp_vec.push_back(sp[i]); + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0)); nanoflann::KNNResultSet result_set(k); result_set.init(neighbor_indices, squared_distance); m_kd_tree.findNeighbors(result_set, @@ -167,12 +164,9 @@ public: std::vector > &neighbors, bool sort_output = true) { - /*std::vector sp_vec( + std::vector sp_vec( m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp), - m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));*/ // CJTODO remettre - std::vector sp_vec; - for (int i = 0 ; i < 4 ; ++i) - sp_vec.push_back(sp[i]); + m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0)); m_kd_tree.radiusSearch(&sp_vec[0], radius, neighbors, From dd869507608ecc7038206c10971beead4b8949c3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 16 Jan 2015 16:53:40 +0100 Subject: [PATCH 098/269] Improve code using a transform_iterator --- .../include/CGAL/Tangential_complex.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 0f007443c75..fc6e21699a7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -47,6 +47,7 @@ const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; #include #include +#include #include #include @@ -171,6 +172,12 @@ class Tangential_complex typedef typename std::vector Normals; #endif + // For transform_iterator + static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) + { + return vh->point(); + } + public: /// Constructor for a range of points @@ -833,13 +840,12 @@ private: } else { - std::vector cell_pts; - cell_pts.reserve(Intrinsic_dimension + 1); - // For each point p - for (int ii = 0 ; ii <= Intrinsic_dimension ; ++ii) - cell_pts.push_back(cell->vertex(ii)->point()); + Tr_point c = power_center( + boost::make_transform_iterator( + cell->vertices_begin(), vertex_handle_to_point), + boost::make_transform_iterator( + cell->vertices_end(), vertex_handle_to_point)); - Tr_point c = power_center(cell_pts.begin(), cell_pts.end()); FT sq_power_sphere_diam = 4*point_weight(c); if (!star_sphere_squared_radius From 751f592f44afbe354628793cb5ec8586e894af75 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 19 Jan 2015 15:52:03 +0100 Subject: [PATCH 099/269] Added an option to perturb point positions instead of weights --- .../include/CGAL/Tangential_complex.h | 131 ++++++++++++++---- .../include/CGAL/Tangential_complex/config.h | 4 + 2 files changed, 106 insertions(+), 29 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fc6e21699a7..b7e4f30960f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,7 +23,8 @@ #define TANGENTIAL_COMPLEX_H #include -const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; +const double HALF_SPARSITY = 0.5*INPUT_SPARSITY; +const double SQ_HALF_SPARSITY = HALF_SPARSITY*HALF_SPARSITY; #include #include @@ -36,6 +37,7 @@ const double SQ_HALF_SPARSITY = 0.5*0.5*INPUT_SPARSITY*INPUT_SPARSITY; #include #include #include +#include #ifdef CGAL_TC_PROFILING # include @@ -114,6 +116,7 @@ class Tangential_complex typedef typename Triangulation::Bare_point Tr_bare_point; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; + typedef typename Tr_traits::Vector_d Tr_vector; typedef std::vector Tangent_space_basis; @@ -163,14 +166,12 @@ class Tangential_complex typedef typename std::vector TS_container; typedef typename std::vector Tr_container; + typedef typename std::vector Vectors; #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm //typedef tbb::queuing_mutex Tr_mutex; #endif -#ifdef CGAL_TC_EXPORT_NORMALS - typedef typename std::vector Normals; -#endif // For transform_iterator static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) @@ -186,7 +187,8 @@ public: const Kernel &k = Kernel()) : m_k(k), m_points(first, last), - m_points_ds(m_points) + m_points_ds(m_points), + m_ambiant_dim(k.point_dimension_d_object()(*first)) {} /// Destructor @@ -211,7 +213,12 @@ public: //m_tr_mutexes.resize(m_points.size()); #endif m_tangent_spaces.resize(m_points.size()); +#ifdef CGAL_TC_PERTURB_WEIGHT m_weights.resize(m_points.size(), FT(0)); +#endif +#ifdef CGAL_TC_PERTURB_POSITION + m_translations.resize(m_points.size()); +#endif #ifdef CGAL_TC_EXPORT_NORMALS m_normals.resize(m_points.size()); #endif @@ -240,13 +247,11 @@ public: void estimate_intrinsic_dimension() { - const int amb_dim = m_k.point_dimension_d_object()(*m_points.begin()); - // Kernel functors typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - std::vector sum_eigen_values(amb_dim, FT(0)); + std::vector sum_eigen_values(m_ambiant_dim, FT(0)); Points::const_iterator it_p = m_points.begin(); Points::const_iterator it_p_end = m_points.end(); @@ -261,13 +266,13 @@ public: //******************************* PCA ************************************* // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { - for (int i = 0 ; i < amb_dim ; ++i) + for (int i = 0 ; i < m_ambiant_dim ; ++i) mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); @@ -277,7 +282,7 @@ public: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = 0 ; i < amb_dim ; ++i) + for (int i = 0 ; i < m_ambiant_dim ; ++i) sum_eigen_values[i] += eig.eigenvalues()[i]; //************************************************************************* @@ -327,9 +332,8 @@ public: unsigned int fix_inconsistencies() { - typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); - typename Kernel::Construct_weighted_point_d cwp = - m_k.construct_weighted_point_d_object(); + typename Kernel::Point_drop_weight_d drop_w = + m_k.point_drop_weight_d_object(); #ifdef CGAL_TC_VERBOSE std::cerr << "Fixing inconsistencies..." << std::endl; @@ -741,6 +745,8 @@ private: m_k.difference_of_points_d_object(); typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); // Triangulation's traits functor & objects typename Tr_traits::Squared_distance_d sqdist = @@ -753,8 +759,13 @@ private: local_tr_traits.power_center_d_object();*/ // CJTODO typename Get_functor::type power_center(local_tr_traits); - // Estimate the tangent space +#ifdef CGAL_TC_PERTURB_POSITION + const Point center_pt = k_transl(m_points[i], m_translations[i]); +#else const Point ¢er_pt = m_points[i]; +#endif + + // Estimate the tangent space if (!tangent_spaces_are_already_computed) { #ifdef CGAL_TC_EXPORT_NORMALS @@ -772,7 +783,12 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(Intrinsic_dimension, ORIGIN), - m_weights[i]); +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[i] +#else + 0 +#endif + ); center_vertex = local_tr.insert(wp); center_vertex->data() = i; @@ -796,12 +812,21 @@ private: // ith point = p, which is already inserted if (neighbor_point_idx != i) { +#ifdef CGAL_TC_PERTURB_POSITION + const Point neighbor_pt = k_transl( + m_points[neighbor_point_idx], m_translations[neighbor_point_idx]); +#else const Point &neighbor_pt = m_points[neighbor_point_idx]; +#endif +#ifdef CGAL_TC_PERTURB_WEIGHT FT neighbor_weight = m_weights[neighbor_point_idx]; +#else + FT neighbor_weight = 0; +#endif if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + SQ_HALF_SPARSITY) + > *star_sphere_squared_radius + 4*SQ_HALF_SPARSITY) // CJTODO: why is "4*" needed? break; Tr_point proj_pt = project_point_and_compute_weight( @@ -815,7 +840,7 @@ private: // CJTODO TEMP TEST /*if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + SQ_HALF_SPARSITY) + > *star_sphere_squared_radius + 4*SQ_HALF_SPARSITY) std::cout << "ARGGGGGGGH" << std::endl;*/ vh->data() = neighbor_point_idx; @@ -897,15 +922,14 @@ private: //******************************* PCA ************************************* - const int amb_dim = m_k.point_dimension_d_object()(p); // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, amb_dim); + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { - for (int i = 0 ; i < amb_dim ; ++i) + for (int i = 0 ; i < m_ambiant_dim ; ++i) mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); @@ -915,18 +939,20 @@ private: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = amb_dim - 1 ; i >= amb_dim - Intrinsic_dimension ; --i) + for (int i = m_ambiant_dim - 1 ; + i >= m_ambiant_dim - Intrinsic_dimension ; + --i) { ts.push_back(constr_vec( - amb_dim, + m_ambiant_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + amb_dim)); + eig.eigenvectors().col(i).data() + m_ambiant_dim)); } #ifdef CGAL_TC_EXPORT_NORMALS *p_normal = constr_vec( - amb_dim, - eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data(), - eig.eigenvectors().col(amb_dim - Intrinsic_dimension - 1).data() + amb_dim); + m_ambiant_dim, + eig.eigenvectors().col(m_ambiant_dim - Intrinsic_dimension - 1).data(), + eig.eigenvectors().col(m_ambiant_dim - Intrinsic_dimension - 1).data() + m_ambiant_dim); #endif //************************************************************************* @@ -1120,6 +1146,16 @@ private: #ifdef CGAL_LINKED_WITH_TBB //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif + +#ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator(m_ambiant_dim, 1); +# else + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator(Intrinsic_dimension, 1); +# endif +#endif Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); @@ -1193,11 +1229,21 @@ private: typename Get_functor::type power_center(local_tr_traits); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); + typename Tr_traits::Construct_weighted_point_d cwp = + local_tr_traits.construct_weighted_point_d_object(); + //typename Tr_traits::Point_to_vector_d pt_to_vec = + // local_tr_traits.construct_point_to_vector_d_object(); typename Kernel::Translated_point_d k_transl = m_k.translated_point_d_object(); typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); +#if defined(CGAL_TC_PERTURB_POSITION) && defined(CGAL_TC_PERTURB_POSITION_GLOBAL) + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); +#endif Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; @@ -1226,7 +1272,28 @@ private: it != neighbors.end() ; ++it) { +#ifdef CGAL_TC_PERTURB_WEIGHT m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); +#endif + +#ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + m_translations[*it] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + Tr_point local_random_transl = + cwp(*tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[*it]; + global_transl = k_constr_vec(m_ambiant_dim); + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +#endif } #if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -1263,7 +1330,7 @@ private: int num_coords = min(ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS - Normals::const_iterator it_n = m_normals.begin(); + Vectors::const_iterator it_n = m_normals.begin(); #endif typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -1413,9 +1480,15 @@ private: private: const Kernel m_k; + const int m_ambiant_dim; Points m_points; +#ifdef CGAL_TC_PERTURB_WEIGHT Weights m_weights; +#endif +#ifdef CGAL_TC_PERTURB_POSITION + Vectors m_translations; +#endif Points_ds m_points_ds; TS_container m_tangent_spaces; @@ -1425,7 +1498,7 @@ private: //std::vector m_tr_mutexes; #endif #ifdef CGAL_TC_EXPORT_NORMALS - Normals m_normals; + Vectors m_normals; #endif }; // /class Tangential_complex diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 87e009191b7..7e424afbb55 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -51,6 +51,10 @@ const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; // 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 //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 50; From ef3c9f951d2b692d70b46811fed2662fca56f6ac Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 19 Jan 2015 15:53:07 +0100 Subject: [PATCH 100/269] Fix sparsify_point_set --- .../test/Tangential_complex/test_utilities.h | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 9ed98fa4c20..f953736efd7 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -105,6 +105,8 @@ sparsify_point_set( Points_ds points_ds(input_pts); + std::vector dropped_points(input_pts.size(), false); + // Parse the following points, and add them if they are not too close to // the other points std::size_t pt_idx = 0; @@ -112,6 +114,11 @@ sparsify_point_set( 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); // Drop it if there is another point that: @@ -123,16 +130,11 @@ sparsify_point_set( { std::size_t neighbor_point_idx = nn_it->first; typename Kernel::FT sq_dist = nn_it->second; - // The neighbor is further, we keep the point - if (sq_dist >= min_squared_dist) - { - output.push_back(*it_pt); + // The neighbor is too close, we drop the neighbor + if (sq_dist < min_squared_dist) + dropped_points[neighbor_point_idx] = true; + else break; - } - // The neighbor is close and it has a higher index - else if (neighbor_point_idx > pt_idx) - break; // We drop the point - // Otherwise, we go the next closest point } } From 928d249c96dd9b06d45acf5a816967f03a0710bd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 19 Jan 2015 15:54:00 +0100 Subject: [PATCH 101/269] Improved test file --- .../test_tangential_complex.cpp | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index ed25c17c1f1..4acbb1a0843 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -23,7 +23,7 @@ #ifdef _DEBUG const int NUM_POINTS = 50; #else - const int NUM_POINTS = 10000; + const int NUM_POINTS = 30000; #endif int main() @@ -36,8 +36,8 @@ int main() # endif #endif - const int INTRINSIC_DIMENSION = 2; - const int AMBIENT_DIMENSION = 4; + const int INTRINSIC_DIMENSION = 3; + const int AMBIENT_DIMENSION = 9; typedef CGAL::Epick_d > Kernel; typedef Kernel::FT FT; @@ -56,7 +56,7 @@ int main() Wall_clock_timer t_gen; #endif - std::vector points = + /*std::vector points = //generate_points_on_circle_2(NUM_POINTS, 3.); //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); //generate_points_on_plane(NUM_POINTS); @@ -64,22 +64,23 @@ int main() //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); - //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.);*/ // LOAD FROM A FILE - //std::vector points; - //load_points_from_file( - // "data/points_10_10k.cin", std::back_inserter(points)); + std::vector points; + load_points_from_file( + "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 after sparsification: " - << points.size() << std::endl; + std::cerr << "Number of points before/after sparsification: " + << num_points_before << " / " << points.size() << std::endl; CGAL::Tangential_complex< Kernel, @@ -89,24 +90,37 @@ int main() tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - + std::set > incorrect_simplices; //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + 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, &incorrect_simplices, true); + export_before_time = t.elapsed(); t.reset(); + } + + t.reset(); tc.fix_inconsistencies(); double fix_time = t.elapsed(); t.reset(); - double export_time = -1.; + double export_after_time = -1.; if (INTRINSIC_DIMENSION <= 3) { t.reset(); std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION - << "_in_R" << AMBIENT_DIMENSION << ".off"; + 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, &incorrect_simplices, true); - double export_time = t.elapsed(); t.reset(); + export_after_time = t.elapsed(); t.reset(); } /*else tc.number_of_inconsistent_simplices();*/ @@ -120,8 +134,9 @@ int main() << 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 << std::endl - << " * Export to OFF: " << export_time << std::endl + << " * Export to OFF (after fix): " << export_after_time << std::endl << "================================================" << std::endl << std::endl; } From cc1379396c2b7513beb05680a80b0c84d271461b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jan 2015 12:32:36 +0100 Subject: [PATCH 102/269] Improved output --- .../include/CGAL/Tangential_complex.h | 88 ++++++++++++++----- .../include/CGAL/Tangential_complex/config.h | 3 +- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b7e4f30960f..d8e70f08b2a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -339,26 +339,29 @@ public: std::cerr << "Fixing inconsistencies..." << std::endl; #endif +#ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES std::pair stats_before = number_of_inconsistent_simplices(false); -#ifdef CGAL_TC_VERBOSE +# ifdef CGAL_TC_VERBOSE std::cerr << "Initial number of inconsistencies: " << stats_before.second << std::endl; -#endif +# endif if (stats_before.second == 0) { -#ifdef CGAL_TC_VERBOSE +# ifdef CGAL_TC_VERBOSE std::cerr << "Nothing to fix." << std::endl; -#endif +# endif return 0; } +#endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES bool done = false; unsigned int num_steps = 0; while (!done) { + std::size_t num_inconsistent_local_tr = 0; // CJTODO: the parallel version is not working for now /*#ifdef CGAL_LINKED_WITH_TBB // Parallel @@ -373,45 +376,76 @@ public: else #endif // CGAL_LINKED_WITH_TBB*/ { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) - try_to_solve_inconsistencies_in_a_local_triangulation(i); + { + num_inconsistent_local_tr += + (try_to_solve_inconsistencies_in_a_local_triangulation(i) ? 1 : 0); + } +#ifdef CGAL_TC_PROFILING + std::cerr << "Attempt to fix inconsistencies: " << t.elapsed() + << " seconds." << std::endl; +#endif } #ifdef CGAL_TC_GLOBAL_REFRESH refresh_tangential_complex(); #endif +#ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES std::pair stats_after = number_of_inconsistent_simplices(false); -#ifdef CGAL_TC_VERBOSE std::cerr << std::endl - << "================================================" << std::endl - << "Inconsistencies:\n" + << "==========================================================" + << std::endl + << "Inconsistencies (detailed stats):\n" << " * Number of vertices: " << m_points.size() << std::endl << std::endl << " * BEFORE fix_inconsistencies:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_before.first << std::endl - << " - Number of inconsistent simplices in stars (incl. duplicates): " - << stats_before.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_before.second / stats_before.first << "%" + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_before.second + << " (" << 100. * stats_before.second / stats_before.first << "%)" + << std::endl + << " * Num inconsistent local triangulations: " + << num_inconsistent_local_tr + << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl << std::endl << " * AFTER fix_inconsistencies:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_after.first << std::endl - << " - Number of inconsistent simplices in stars (incl. duplicates): " + << " - Num inconsistent simplices in stars (incl. duplicates): " << stats_after.second << std::endl << " - Percentage of inconsistencies: " << 100. * stats_after.second / stats_before.first << "%" << std::endl - << "================================================" << std::endl; -#endif - done = (stats_after.second == 0); + << "==========================================================" + << std::endl; + stats_before = stats_after; + +#else // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES +# ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "==========================================================" + << std::endl + << "fix_inconsistencies():\n" + << " * " << m_points.size() << " vertices" << std::endl + << " * " << num_inconsistent_local_tr + << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" + << " inconsistent triangulations encountered" << std::endl + << "==========================================================" + << std::endl; +# endif +#endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES + ++num_steps; + done = (num_inconsistent_local_tr == 0); } return num_steps; @@ -459,7 +493,8 @@ public: if (verbose) { std::cerr << std::endl - << "================================================" << std::endl + << "==========================================================" + << std::endl << "Inconsistencies:\n" << " * Number of vertices: " << m_points.size() << std::endl << " * Total number of simplices in stars (incl. duplicates): " @@ -468,7 +503,8 @@ public: << num_inconsistent_simplices << std::endl << " * Percentage of inconsistencies: " << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl - << "================================================" << std::endl; + << "==========================================================" + << std::endl; } return std::make_pair(num_simplices, num_inconsistent_simplices); @@ -1140,9 +1176,11 @@ private: }; #endif // CGAL_LINKED_WITH_TBB - void try_to_solve_inconsistencies_in_a_local_triangulation( + bool try_to_solve_inconsistencies_in_a_local_triangulation( std::size_t tr_index) { + bool is_inconsistent = false; + #ifdef CGAL_LINKED_WITH_TBB //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif @@ -1184,6 +1222,8 @@ private: // Inconsistent? if (!is_simplex_consistent(c)) { + is_inconsistent = true; + //m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); //break; // CJTODO TEMP CGAL::Random rng; @@ -1204,6 +1244,8 @@ private: // Inconsistent? if (!is_simplex_consistent(*it_c, cur_dim)) { + is_inconsistent = true; + // Get the k + 2 closest points /*int point_dim = m_k.point_dimension_d_object()(*m_points.begin()); @@ -1307,6 +1349,8 @@ private: #endif } + + return is_inconsistent; } std::ostream &export_vertices_to_off( @@ -1461,7 +1505,8 @@ private: #ifdef CGAL_TC_VERBOSE std::cerr << std::endl - << "================================================" << std::endl + << "==========================================================" + << std::endl << "Export to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl << " * Total number of simplices in stars (incl. duplicates): " @@ -1472,7 +1517,8 @@ private: << (num_simplices > 0 ? 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" << std::endl - << "================================================" << std::endl; + << "==========================================================" + << std::endl; #endif return os; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 7e424afbb55..3b696b146fa 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -34,6 +34,7 @@ //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE +//#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES // Solving inconsistencies: only change the weights of the inconsistent simplex // or more? @@ -57,7 +58,7 @@ const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; //#define CGAL_TC_PERTURB_WEIGHT //========================= Parameters ======================================== -const std::size_t NUM_POINTS_FOR_PCA = 50; +const std::size_t NUM_POINTS_FOR_PCA = 30; const double INPUT_SPARSITY = 0.05; #endif // CGAL_TC_CONFIG_H From 9255141ae7fb47b8e48cce83291a1e70893e2ff8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jan 2015 12:34:37 +0100 Subject: [PATCH 103/269] Rename macro --- Tangential_complex/include/CGAL/Tangential_complex.h | 2 +- Tangential_complex/include/CGAL/Tangential_complex/config.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d8e70f08b2a..97d6005b825 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1210,7 +1210,7 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { -#ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS +#ifdef CGAL_TC_PERTURB_THE_SIMPLEX_ONLY std::set c; for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 3b696b146fa..2d5f4b6e96d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -36,9 +36,8 @@ #define CGAL_TC_VERBOSE //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES -// Solving inconsistencies: only change the weights of the inconsistent simplex -// or more? -//#define CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS +// Solving inconsistencies: only perturb the inconsistent simplex or more? +//#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY // Otherwise... const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; From be21ff3dc1beab9cd260351d0d3ed9ece79ca1ef Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jan 2015 19:49:32 +0100 Subject: [PATCH 104/269] Added another strategy to perturb the points --- .../include/CGAL/Tangential_complex.h | 159 ++++++++++++++---- .../include/CGAL/Tangential_complex/config.h | 8 +- 2 files changed, 131 insertions(+), 36 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 97d6005b825..c916b61a2f1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1210,6 +1210,9 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { +//***************************************************************************** +// STRATEGY 1: perturb all the points of the first inconsistent simplex +//***************************************************************************** #ifdef CGAL_TC_PERTURB_THE_SIMPLEX_ONLY std::set c; @@ -1223,44 +1226,130 @@ private: if (!is_simplex_consistent(c)) { is_inconsistent = true; + +# ifdef CGAL_TC_PERTURB_POSITION + typename Tr_traits::Construct_weighted_point_d cwp = + local_tr_traits.construct_weighted_point_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); +# endif +# endif - //m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); - //break; // CJTODO TEMP CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) { +# ifdef CGAL_TC_PERTURB_WEIGHT m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); +# endif + +# ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + m_translations[*it] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + Tr_point local_random_transl = + cwp(*tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[*it]; + global_transl = k_constr_vec(m_ambiant_dim); + const Tangent_space_basis &tsb = m_tangent_spaces[*it]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +# endif } -#if !defined(CGAL_TC_GLOBAL_REFRESH) +# if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); -#endif +# endif // We will try the other cells next time (incident_cells is not // valid anymore here) break; } -#else + +//***************************************************************************** +// STRATEGY 2: perturb the center point only +//***************************************************************************** +#elif defined(CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY) + if (!is_simplex_consistent(*it_c, cur_dim)) + { + is_inconsistent = true; +# ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); +# endif + +# ifdef CGAL_TC_PERTURB_POSITION + typename Tr_traits::Construct_weighted_point_d cwp = + local_tr_traits.construct_weighted_point_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); + +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); + m_translations[tr_index] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + Tr_point local_random_transl = + cwp(*tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[tr_index]; + //Vector &global_transl = m_translations[ + // (*it_c)->vertex(rand()%tr.current_dimension())->data()]; + global_transl = k_constr_vec(m_ambiant_dim); + const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +# endif + +# if !defined(CGAL_TC_GLOBAL_REFRESH) + refresh_tangential_complex(); +# endif + + // We will try the other cells next time (incident_cells is not + // valid anymore here) + break; + } + +//***************************************************************************** +// STRATEGY 3: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS +// closest points (to the power center of first the inconsistent cell) +//***************************************************************************** +#else // Inconsistent? if (!is_simplex_consistent(*it_c, cur_dim)) { is_inconsistent = true; - // Get the k + 2 closest points - - /*int point_dim = m_k.point_dimension_d_object()(*m_points.begin()); - std::vector center(point_dim, FT(0)); - for (int i = 0 ; i < point_dim ; ++i) - { - for (int j = 0 ; j < Intrinsic_dimension + 1 ; ++j) - { - std::size_t data = (*it_c)->vertex(j)->data(); - const Point &p = m_points[data]; - center[i] += p[i]; - } - center[i] /= (Intrinsic_dimension + 1); - } - Point global_center(center.begin(), center.end());*/ + // Get the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS + // closest points std::vector simplex_pts; for (int i = 0 ; i < cur_dim + 1 ; ++i) @@ -1280,12 +1369,16 @@ private: m_k.translated_point_d_object(); typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); -#if defined(CGAL_TC_PERTURB_POSITION) && defined(CGAL_TC_PERTURB_POSITION_GLOBAL) + +# ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); -#endif +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); +# endif +# endif Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; @@ -1314,15 +1407,15 @@ private: it != neighbors.end() ; ++it) { -#ifdef CGAL_TC_PERTURB_WEIGHT +# ifdef CGAL_TC_PERTURB_WEIGHT m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); -#endif +# endif -#ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL +# ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL m_translations[*it] = k_scaled_vec(k_pt_to_vec( *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL Tr_point local_random_transl = cwp(*tr_point_on_sphere_generator++, 0); Vector &global_transl = m_translations[*it]; @@ -1334,20 +1427,20 @@ private: k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) ); } +# endif # endif -#endif } -#if !defined(CGAL_TC_GLOBAL_REFRESH) +# if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); -#endif +# endif // We will try the other cells next time (incident_cells is not // valid anymore here) break; } -#endif +#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY } return is_inconsistent; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 2d5f4b6e96d..c2c54be63a8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -36,11 +36,13 @@ #define CGAL_TC_VERBOSE //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES -// Solving inconsistencies: only perturb the inconsistent simplex or more? +// 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 -// Otherwise... -const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1; +// Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS +// closest points +const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = -2; //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN From 499b702e9b3baaa8aaea6d599b9dd1046a74099f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 21 Jan 2015 13:40:48 +0100 Subject: [PATCH 105/269] Added the CGAL_TC_PERTURB_THE_1_STAR strategy --- .../include/CGAL/Tangential_complex.h | 90 ++++++++++++++++++- .../include/CGAL/Tangential_complex/config.h | 1 + 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c916b61a2f1..8fdac3e0795 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1315,8 +1315,13 @@ private: Tr_point local_random_transl = cwp(*tr_point_on_sphere_generator++, 0); Vector &global_transl = m_translations[tr_index]; - //Vector &global_transl = m_translations[ - // (*it_c)->vertex(rand()%tr.current_dimension())->data()]; + /*int idx; + do + { + idx = rand() % tr.current_dimension(); + } while ((*it_c)->vertex(idx) == center_vh); + Vector &global_transl = m_translations[ + (*it_c)->vertex(idx)->data()];*/ global_transl = k_constr_vec(m_ambiant_dim); const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; for (int i = 0 ; i < Intrinsic_dimension ; ++i) @@ -1329,6 +1334,85 @@ private: # endif # endif +# if !defined(CGAL_TC_GLOBAL_REFRESH) + refresh_tangential_complex(); +# endif + + // We will try the other cells next time (incident_cells is not + // valid anymore here) + break; + } + +//***************************************************************************** +// STRATEGY 3: perturb all the points of the 1-star +//***************************************************************************** +#elif defined(CGAL_TC_PERTURB_THE_1_STAR) + + // Inconsistent? + if (!is_simplex_consistent(*it_c, cur_dim)) + { + is_inconsistent = true; + + std::set c; + + typename std::vector::const_iterator it_c2 = + incident_cells.begin(); + // For each cell + for ( ; it_c2 != it_c_end ; ++it_c2) + { + for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) + { + std::size_t data = (*it_c2)->vertex(i)->data(); + c.insert(data); + } + } + +# ifdef CGAL_TC_PERTURB_POSITION + typename Tr_traits::Construct_weighted_point_d cwp = + local_tr_traits.construct_weighted_point_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); +# endif +# endif + + CGAL::Random rng; + for (std::set::iterator it=c.begin(); it!=c.end(); ++it) + { +# ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); +# endif + +# ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + m_translations[*it] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + Tr_point local_random_transl = + cwp(*tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[*it]; + global_transl = k_constr_vec(m_ambiant_dim); + const Tangent_space_basis &tsb = m_tangent_spaces[*it]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +# endif + } + # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif @@ -1339,7 +1423,7 @@ private: } //***************************************************************************** -// STRATEGY 3: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS +// STRATEGY 4: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points (to the power center of first the inconsistent cell) //***************************************************************************** #else diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index c2c54be63a8..baa361b3d39 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -39,6 +39,7 @@ // 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 // Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points From 68b0f5839c5e7a50cbdef2f416006fb43f209fd6 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 13:20:59 +0100 Subject: [PATCH 106/269] Added time limit to fix_inconsistencies() --- .../include/CGAL/Tangential_complex.h | 19 ++++++++++++++--- .../test_tangential_complex.cpp | 21 +++++++++++-------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8fdac3e0795..81d9e5cadc7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -70,6 +70,8 @@ namespace CGAL { using namespace Tangential_complex_; +enum Fix_inconsistencies_status { TC_FIXED = 0, TIME_LIMIT_REACHED }; + class Vertex_data { public: @@ -330,8 +332,12 @@ public: #endif } - unsigned int fix_inconsistencies() + // time_limit in seconds + Fix_inconsistencies_status fix_inconsistencies( + unsigned int &num_steps, double time_limit = 0.) { + Wall_clock_timer t; + typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); @@ -358,7 +364,7 @@ public: #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES bool done = false; - unsigned int num_steps = 0; + num_steps = 0; while (!done) { std::size_t num_inconsistent_local_tr = 0; @@ -446,9 +452,16 @@ public: ++num_steps; done = (num_inconsistent_local_tr == 0); + if (time_limit != 0 && t.elapsed() > time_limit) + { +#ifdef CGAL_TC_VERBOSE + std::cerr << "Time limit reached." << std::endl; +#endif + return TIME_LIMIT_REACHED; + } } - return num_steps; + return TC_FIXED; } diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 4acbb1a0843..5303a737c33 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -39,9 +39,11 @@ int main() const int INTRINSIC_DIMENSION = 3; const int AMBIENT_DIMENSION = 9; - typedef CGAL::Epick_d > Kernel; - typedef Kernel::FT FT; - typedef Kernel::Point_d Point; + typedef CGAL::Epick_d > Kernel; + typedef Kernel::FT FT; + typedef Kernel::Point_d Point; + typedef CGAL::Tangential_complex< + Kernel, INTRINSIC_DIMENSION, CGAL::Parallel_tag> TC; int i = 0; bool stop = false; @@ -82,10 +84,7 @@ int main() std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; - CGAL::Tangential_complex< - Kernel, - INTRINSIC_DIMENSION, - CGAL::Parallel_tag> tc(points.begin(), points.end(), k); + TC tc(points.begin(), points.end(), k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); @@ -108,7 +107,9 @@ int main() t.reset(); - tc.fix_inconsistencies(); + unsigned int num_fix_steps; + CGAL::Fix_inconsistencies_status fix_ret = + tc.fix_inconsistencies(num_fix_steps, 3000.); double fix_time = t.elapsed(); t.reset(); double export_after_time = -1.; @@ -135,7 +136,9 @@ int main() << " - 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 << std::endl + << " * Fix inconsistencies: " + << (fix_ret == CGAL::TC_FIXED ? "FIXED / " : "NOT fixed / ") << fix_time + << " (" << num_fix_steps << " steps)" << std::endl << " * Export to OFF (after fix): " << export_after_time << std::endl << "================================================" << std::endl << std::endl; From 7ae8a6a4cc5f07693ab88a5394767cafeec7fb70 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 13:32:34 +0100 Subject: [PATCH 107/269] Better output --- .../test/Tangential_complex/test_tangential_complex.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 5303a737c33..5a5f82b25a5 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -136,9 +136,9 @@ int main() << " - 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_ret == CGAL::TC_FIXED ? "FIXED / " : "NOT fixed / ") << fix_time - << " (" << num_fix_steps << " steps)" << 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; From 0c876e6ba692870b43923b9eea70f7daa972a5c8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 14:00:33 +0100 Subject: [PATCH 108/269] Refactored try_to_solve function --- .../include/CGAL/Tangential_complex.h | 239 +++++------------- 1 file changed, 63 insertions(+), 176 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 81d9e5cadc7..1178ad84df8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1189,6 +1189,57 @@ private: }; #endif // CGAL_LINKED_WITH_TBB + void perturb(std::size_t point_idx) + { + CGAL::Random rng; + + // Perturb the weight? +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[point_idx] = rng.get_double(0., SQ_HALF_SPARSITY); +#endif + + // Perturb the position? +#ifdef CGAL_TC_PERTURB_POSITION +# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL + typename Kernel::Point_to_vector_d k_pt_to_vec = + m_k.point_to_vector_d_object(); + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator(m_ambiant_dim, 1); + + m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), HALF_SPARSITY); +# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL + const Tr_traits &local_tr_traits = + m_triangulations[point_idx].tr().geom_traits(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Construct_vector_d k_constr_vec = + m_k.construct_vector_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator(Intrinsic_dimension, 1); + + Tr_point local_random_transl = + local_tr_traits.construct_weighted_point_d_object()( + *tr_point_on_sphere_generator++, 0); + Vector &global_transl = m_translations[point_idx]; + global_transl = k_constr_vec(m_ambiant_dim); + const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; + for (int i = 0 ; i < Intrinsic_dimension ; ++i) + { + global_transl = k_transl( + global_transl, + k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + ); + } +# endif +#endif // CGAL_TC_PERTURB_POSITION + } + bool try_to_solve_inconsistencies_in_a_local_triangulation( std::size_t tr_index) { @@ -1198,16 +1249,6 @@ private: //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif -#ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(m_ambiant_dim, 1); -# else - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(Intrinsic_dimension, 1); -# endif -#endif - Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); const Tr_traits &local_tr_traits = tr.geom_traits(); @@ -1240,51 +1281,8 @@ private: { is_inconsistent = true; -# ifdef CGAL_TC_PERTURB_POSITION - typename Tr_traits::Construct_weighted_point_d cwp = - local_tr_traits.construct_weighted_point_d_object(); - typename Tr_traits::Compute_coordinate_d coord = - local_tr_traits.compute_coordinate_d_object(); - - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = - m_k.scaled_vector_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = - m_k.point_to_vector_d_object(); -# endif -# endif - - CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) - { -# ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); -# endif - -# ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - m_translations[*it] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - Tr_point local_random_transl = - cwp(*tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[*it]; - global_transl = k_constr_vec(m_ambiant_dim); - const Tangent_space_basis &tsb = m_tangent_spaces[*it]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - global_transl = k_transl( - global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) - ); - } -# endif -# endif - } + perturb(*it); # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); @@ -1302,50 +1300,16 @@ private: if (!is_simplex_consistent(*it_c, cur_dim)) { is_inconsistent = true; -# ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[tr_index] = rng.get_double(0., SQ_HALF_SPARSITY); -# endif - -# ifdef CGAL_TC_PERTURB_POSITION - typename Tr_traits::Construct_weighted_point_d cwp = - local_tr_traits.construct_weighted_point_d_object(); - typename Tr_traits::Compute_coordinate_d coord = - local_tr_traits.compute_coordinate_d_object(); - - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = - m_k.scaled_vector_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); - -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = - m_k.point_to_vector_d_object(); - m_translations[tr_index] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - Tr_point local_random_transl = - cwp(*tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[tr_index]; - /*int idx; + + std::size_t idx = tr_index; + /*int k; do { - idx = rand() % tr.current_dimension(); - } while ((*it_c)->vertex(idx) == center_vh); - Vector &global_transl = m_translations[ - (*it_c)->vertex(idx)->data()];*/ - global_transl = k_constr_vec(m_ambiant_dim); - const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - global_transl = k_transl( - global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) - ); - } -# endif -# endif + k = rand() % tr.current_dimension(); + } while ((*it_c)->vertex(k) == center_vh); + std::size_t idx = (*it_c)->vertex(k)->data();*/ + + perturb(idx); # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); @@ -1369,7 +1333,7 @@ private: std::set c; typename std::vector::const_iterator it_c2 = - incident_cells.begin(); + incident_cells.begin(); // For each cell for ( ; it_c2 != it_c_end ; ++it_c2) { @@ -1380,51 +1344,8 @@ private: } } -# ifdef CGAL_TC_PERTURB_POSITION - typename Tr_traits::Construct_weighted_point_d cwp = - local_tr_traits.construct_weighted_point_d_object(); - typename Tr_traits::Compute_coordinate_d coord = - local_tr_traits.compute_coordinate_d_object(); - - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = - m_k.scaled_vector_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = - m_k.point_to_vector_d_object(); -# endif -# endif - - CGAL::Random rng; for (std::set::iterator it=c.begin(); it!=c.end(); ++it) - { -# ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); -# endif - -# ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - m_translations[*it] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - Tr_point local_random_transl = - cwp(*tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[*it]; - global_transl = k_constr_vec(m_ambiant_dim); - const Tangent_space_basis &tsb = m_tangent_spaces[*it]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - global_transl = k_transl( - global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) - ); - } -# endif -# endif - } + perturb(*it); # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); @@ -1457,25 +1378,12 @@ private: typename Get_functor::type power_center(local_tr_traits); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); - typename Tr_traits::Construct_weighted_point_d cwp = - local_tr_traits.construct_weighted_point_d_object(); - //typename Tr_traits::Point_to_vector_d pt_to_vec = - // local_tr_traits.construct_point_to_vector_d_object(); typename Kernel::Translated_point_d k_transl = m_k.translated_point_d_object(); typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); -# ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = - m_k.point_to_vector_d_object(); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - typename Kernel::Construct_vector_d k_constr_vec = - m_k.construct_vector_d_object(); -# endif -# endif Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; @@ -1504,28 +1412,7 @@ private: it != neighbors.end() ; ++it) { -# ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[*it] = rng.get_double(0., SQ_HALF_SPARSITY); -# endif - -# ifdef CGAL_TC_PERTURB_POSITION -# ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - m_translations[*it] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); -# else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - Tr_point local_random_transl = - cwp(*tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[*it]; - global_transl = k_constr_vec(m_ambiant_dim); - for (int i = 0 ; i < Intrinsic_dimension ; ++i) - { - global_transl = k_transl( - global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) - ); - } -# endif -# endif + perturb(*it); } # if !defined(CGAL_TC_GLOBAL_REFRESH) From b6a4f6d6008fdf3e197114f98f37d32a7f684fd3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 17:58:19 +0100 Subject: [PATCH 109/269] Dimensions can now be set at runtime by using Dynamic_dimension_tag --- .../include/CGAL/Tangential_complex.h | 81 ++++++++++--------- .../CGAL/Tangential_complex/Point_cloud.h | 5 +- .../CGAL/Tangential_complex/utilities.h | 2 - 3 files changed, 45 insertions(+), 43 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 1178ad84df8..fbe98160738 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -88,21 +88,21 @@ private: /// The class Tangential_complex represents a tangential complex template < typename Kernel, - int Intrinsic_dimension, + typename DimensionTag, typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Regular_triangulation < Regular_triangulation_euclidean_traits< - Epick_d > >, + Epick_d >, Triangulation_data_structure < typename Regular_triangulation_euclidean_traits< - Epick_d > >::Dimension, + Epick_d >::Dimension, Triangulation_vertex > >, Vertex_data >, + Epick_d >, Vertex_data >, Triangulation_full_cell > > > + Epick_d > > > > > @@ -186,8 +186,10 @@ public: /// Constructor for a range of points template Tangential_complex(InputIterator first, InputIterator last, + int intrinsic_dimension, const Kernel &k = Kernel()) : m_k(k), + m_intrinsic_dimension(intrinsic_dimension), m_points(first, last), m_points_ds(m_points), m_ambiant_dim(k.point_dimension_d_object()(*first)) @@ -219,10 +221,12 @@ public: m_weights.resize(m_points.size(), FT(0)); #endif #ifdef CGAL_TC_PERTURB_POSITION - m_translations.resize(m_points.size()); + m_translations.resize(m_points.size(), + m_k.construct_vector_d_object()(m_ambiant_dim)); #endif #ifdef CGAL_TC_EXPORT_NORMALS - m_normals.resize(m_points.size()); + m_normals.resize(m_points.size(), + m_k.construct_vector_d_object()(m_ambiant_dim)); #endif #ifdef CGAL_LINKED_WITH_TBB @@ -548,7 +552,7 @@ public: << std::endl; } - if (Intrinsic_dimension < 1 || Intrinsic_dimension > 3) + if (m_intrinsic_dimension < 1 || m_intrinsic_dimension > 3) { std::cerr << "Error: export_to_off => intrinsic dimension should be " "between 1 and 3." @@ -614,12 +618,12 @@ public: cit != ambient_dt.finite_full_cells_end() ; ++cit ) { CGAL::Combination_enumerator combi( - Intrinsic_dimension + 1, 0, ambient_dim + 1); + m_intrinsic_dimension + 1, 0, ambient_dim + 1); for ( ; !combi.finished() ; ++combi) { Indexed_simplex simplex; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) simplex.insert(cit.base()->vertex(combi[i])->data()); amb_dt_simplices.insert(simplex); @@ -785,7 +789,7 @@ private: { //std::cerr << "***********************************************" << std::endl; Triangulation &local_tr = - m_triangulations[i].construct_triangulation(Intrinsic_dimension); + m_triangulations[i].construct_triangulation(m_intrinsic_dimension); const Tr_traits &local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); @@ -831,7 +835,7 @@ private: // Insert p Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(Intrinsic_dimension, ORIGIN), + local_tr_traits.construct_point_d_object()(m_intrinsic_dimension, ORIGIN), #ifdef CGAL_TC_PERTURB_WEIGHT m_weights[i] #else @@ -895,7 +899,7 @@ private: vh->data() = neighbor_point_idx; // Let's recompute star_sphere_squared_radius - if (local_tr.current_dimension() >= Intrinsic_dimension) + if (local_tr.current_dimension() >= m_intrinsic_dimension) { star_sphere_squared_radius = 0; // Get the incident cells and look for the biggest circumsphere @@ -989,7 +993,7 @@ private: // eigenvalues Tangent_space_basis ts; for (int i = m_ambiant_dim - 1 ; - i >= m_ambiant_dim - Intrinsic_dimension ; + i >= m_ambiant_dim - m_intrinsic_dimension ; --i) { ts.push_back(constr_vec( @@ -1000,8 +1004,8 @@ private: #ifdef CGAL_TC_EXPORT_NORMALS *p_normal = constr_vec( m_ambiant_dim, - eig.eigenvectors().col(m_ambiant_dim - Intrinsic_dimension - 1).data(), - eig.eigenvectors().col(m_ambiant_dim - Intrinsic_dimension - 1).data() + m_ambiant_dim); + eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data(), + eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data() + m_ambiant_dim); #endif //************************************************************************* @@ -1024,7 +1028,7 @@ private: typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts; - ts.reserve(Intrinsic_dimension); + ts.reserve(m_intrinsic_dimension); ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); @@ -1037,7 +1041,7 @@ private: //Vector t1(12., 15., 65.); //Vector t2(32., 5., 85.); //Tangent_space_basis ts; - //ts.reserve(Intrinsic_dimension); + //ts.reserve(m_intrinsic_dimension); //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); //return compute_gram_schmidt_basis(ts, m_k); @@ -1056,8 +1060,8 @@ private: std::vector coords; // Ambiant-space coords of the projected point - coords.reserve(Intrinsic_dimension); - for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) + coords.reserve(m_intrinsic_dimension); + for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { // Compute the inner product p * ts[i] Vector v = diff_points(p, origin); @@ -1065,7 +1069,7 @@ private: coords.push_back(coord); } - return Tr_bare_point(Intrinsic_dimension, coords.begin(), coords.end()); + return Tr_bare_point(m_intrinsic_dimension, coords.begin(), coords.end()); } // Project the point in the tangent space @@ -1087,8 +1091,8 @@ private: std::vector coords; // Ambiant-space coords of the projected point std::vector p_proj(ccci(origin), ccci(origin, 0)); - coords.reserve(Intrinsic_dimension); - for (std::size_t i = 0 ; i < Intrinsic_dimension ; ++i) + coords.reserve(m_intrinsic_dimension); + for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { // Compute the inner product p * ts[i] FT coord = inner_pdct(v, ts[i]); @@ -1104,7 +1108,7 @@ private: return tr_traits.construct_weighted_point_d_object() ( tr_traits.construct_point_d_object()( - Intrinsic_dimension, coords.begin(), coords.end()), + m_intrinsic_dimension, coords.begin(), coords.end()), w - m_k.squared_distance_d_object()(p, projected_pt) ); } @@ -1221,7 +1225,7 @@ private: m_k.scaled_vector_d_object(); CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(Intrinsic_dimension, 1); + tr_point_on_sphere_generator(m_intrinsic_dimension, 1); Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( @@ -1229,7 +1233,7 @@ private: Vector &global_transl = m_translations[point_idx]; global_transl = k_constr_vec(m_ambiant_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_transl = k_transl( global_transl, @@ -1388,7 +1392,7 @@ private: Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); Point global_center = m_points[tr_index]; const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; - for (int i = 0 ; i < Intrinsic_dimension ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_center = k_transl( global_center, @@ -1397,7 +1401,7 @@ private: KNS_range kns_range = m_points_ds.query_ANN( global_center, - Intrinsic_dimension + 1 + m_intrinsic_dimension + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; @@ -1439,10 +1443,10 @@ private: return os; } - // If Intrinsic_dimension = 1, we output each point two times + // If m_intrinsic_dimension = 1, we output each point two times // to be able to export each segment as a flat triangle with 3 different // indices (otherwise, Meshlab detects degenerated simplices) - const int N = (Intrinsic_dimension == 1 ? 2 : 1); + const int N = (m_intrinsic_dimension == 1 ? 2 : 1); const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors @@ -1487,11 +1491,11 @@ private: std::set > const* excluded_simplices = NULL, bool show_excluded_vertices_in_color = false) { - // If Intrinsic_dimension = 1, each point is output two times + // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) - int factor = (Intrinsic_dimension == 1 ? 2 : 1); + int factor = (m_intrinsic_dimension == 1 ? 2 : 1); int OFF_simplices_dim = - (Intrinsic_dimension == 1 ? 3 : Intrinsic_dimension + 1); + (m_intrinsic_dimension == 1 ? 3 : m_intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; typename Tr_container::const_iterator it_tr = m_triangulations.begin(); @@ -1502,7 +1506,7 @@ private: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - if (tr.current_dimension() < Intrinsic_dimension) + if (tr.current_dimension() < m_intrinsic_dimension) continue; // Color for this star @@ -1526,14 +1530,14 @@ private: std::set c; std::stringstream sstr_c; std::size_t data; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) { data = (*it_c)->vertex(i)->data(); sstr_c << data*factor << " "; c.insert(data); } // See export_vertices_to_off - if (Intrinsic_dimension == 1) + if (m_intrinsic_dimension == 1) sstr_c << (data*factor + 1) << " "; bool excluded = @@ -1564,13 +1568,13 @@ private: { os << OFF_simplices_dim << " "; std::size_t data; - for (int i = 0 ; i < Intrinsic_dimension + 1 ; ++i) + for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) { data = (*it_c)->vertex(i)->data(); os << data*factor << " "; } // See export_vertices_to_off - if (Intrinsic_dimension == 1) + if (m_intrinsic_dimension == 1) os << (data*factor + 1) << " "; ++num_simplices; @@ -1603,6 +1607,7 @@ private: private: const Kernel m_k; + const int m_intrinsic_dimension; const int m_ambiant_dim; Points m_points; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 4c6c2904003..0ea59a5f208 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -117,9 +117,10 @@ public: static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar /// Constructor + /// "points" must not be empty Point_cloud_data_structure(Point_container_ &points, Kernel const& k) : m_adaptor(points, k), - m_kd_tree(AMB_DIM, + m_kd_tree(k.point_dimension_d_object()(*points.begin()), m_adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) ) { @@ -243,8 +244,6 @@ public: typedef typename Incremental_neighbor_search::iterator INS_iterator; typedef Incremental_neighbor_search INS_range; - static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar - /// Constructor Point_cloud_data_structure(Point_container_ const& points) : m_points(points), diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 3797268d6ae..fa55b4f332c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -39,8 +39,6 @@ namespace Tangential_complex_ { typedef typename K::Vector_d Vector; typedef std::vector Basis; - const int D = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar - // Kernel functors typename K::Squared_length_d sqlen = kernel.squared_length_d_object(); typename K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); From d4c289daee925b52ad9b1451dce2ddb1da246d4c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 26 Jan 2015 18:09:20 +0100 Subject: [PATCH 110/269] Better benchmark: scripts, logs --- .../Tangential_complex/benchmark_tc.cpp | 350 ++++++++++++------ 1 file changed, 238 insertions(+), 112 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 26606958ab2..cc788b7152d 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -1,3 +1,12 @@ +//#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 #include #include #include @@ -17,6 +26,15 @@ #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 Kernel; +typedef Kernel::FT FT; +typedef Kernel::Point_d Point; +typedef CGAL::Tangential_complex< + Kernel, CGAL::Dynamic_dimension_tag, + CGAL::Parallel_tag> TC; + class XML_perf_data { public: @@ -59,16 +77,17 @@ protected: static std::vector construct_subelements_names() { std::vector subelements; - subelements.push_back("Name"); + subelements.push_back("Input"); subelements.push_back("Intrinsic_dim"); subelements.push_back("Ambient_dim"); subelements.push_back("Num_points"); - subelements.push_back("Noise"); - subelements.push_back("Info"); + subelements.push_back("Sparsity"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); + subelements.push_back("Fix_successful"); subelements.push_back("Fix_time"); subelements.push_back("Fix_steps"); + subelements.push_back("Info"); return subelements; } @@ -103,128 +122,235 @@ const double NOISE = 0.01; const int NUM_POINTS = 30000; #endif +void make_tc(std::vector &points, int intrinsic_dim, + double sparsity = 0., double time_limit_for_fix = 0.) +{ + Kernel k; + Wall_clock_timer t; + + int ambient_dim = k.point_dimension_d_object()(*points.begin()); + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_gen; +#endif + +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set generated in " << t_gen.elapsed() + << " seconds." << std::endl; +#endif + + if (sparsity != 0.) + { + 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; + } + + CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); + CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); + + TC tc(points.begin(), points.end(), intrinsic_dim, k); + double init_time = t.elapsed(); t.reset(); + + tc.compute_tangential_complex(); + double computation_time = t.elapsed(); t.reset(); + + std::set > incorrect_simplices; + //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + + double export_before_time = -1.; + if (intrinsic_dim <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "output/test_tc_" << intrinsic_dim + << "_in_R" << ambient_dim << "_BEFORE_FIX.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + export_before_time = t.elapsed(); t.reset(); + } + + + t.reset(); + unsigned int num_fix_steps; + CGAL::Fix_inconsistencies_status fix_ret = + tc.fix_inconsistencies(num_fix_steps, time_limit_for_fix); + double fix_time = t.elapsed(); t.reset(); + + double export_after_time = -1.; + if (intrinsic_dim <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "output/test_tc_" << intrinsic_dim + << "_in_R" << ambient_dim << "_AFTER_FIX.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, 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; + + CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); + CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); + CGAL_TC_SET_PERFORMANCE_DATA("Fix_successful", + (fix_ret == CGAL::TC_FIXED ? "Y" : "N")); + CGAL_TC_SET_PERFORMANCE_DATA("Fix_time", fix_time); + CGAL_TC_SET_PERFORMANCE_DATA("Fix_steps", num_fix_steps); + CGAL_TC_SET_PERFORMANCE_DATA("Info", ""); +} + int main() { #ifdef CGAL_LINKED_WITH_TBB # ifdef _DEBUG - tbb::task_scheduler_init init(1); + int num_threads = 1; # else - tbb::task_scheduler_init init(10); + int num_threads = 10; # endif #endif - const int INTRINSIC_DIMENSION = 2; - const int AMBIENT_DIMENSION = 4; - - typedef CGAL::Epick_d > Kernel; - typedef Kernel::FT FT; - typedef Kernel::Point_d Point; - - bool stop = false; - //for (int i = 0, NUM_POINTS = 10000 ; - // NUM_POINTS <= 50000 && !stop ; - // ++i, NUM_POINTS += (i%3 == 0 ? 5000 : 0)) - for (int i = 0 ; i < 5 && !stop ; ++i) + int seed = CGAL::default_random.get_int(0, 1<<30); + CGAL::default_random = CGAL::Random(); + std::cerr << "Random seed = " << seed << std::endl; + + 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()) { - 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; + 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 - //std::vector points; - //load_points_from_file( - // "data/points_10_10k.cin", std::back_inserter(points)/*, 600*/); - - std::vector points = - //generate_points_on_circle_2(NUM_POINTS, 3.); - //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); - //generate_points_on_plane(NUM_POINTS); - //generate_points_on_sphere_3(NUM_POINTS, 3.0); - //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); - //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3., NOISE); - //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); - - - CGAL_TC_SET_PERFORMANCE_DATA("Name", "Klein bottle 4D"); - CGAL_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", INTRINSIC_DIMENSION); - CGAL_TC_SET_PERFORMANCE_DATA("Ambient_dim", AMBIENT_DIMENSION); - CGAL_TC_SET_PERFORMANCE_DATA("Noise", NOISE); - XML_perf_data::set("Info", "" -#ifdef CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS - "ONLY_CHANGE_SIMPLEX_WEIGHTS " -#endif -#ifdef CGAL_TC_GLOBAL_REFRESH - "GLOBAL_REFRESH " -#endif - ); - -#ifdef CGAL_TC_PROFILING - std::cerr << "Point set generated in " << t_gen.elapsed() - << " seconds." << std::endl; -#endif - - std::cerr << "Number of points before sparsification: " - << points.size() << std::endl; - points = sparsify_point_set( - k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); - std::cerr << "Number of points after sparsification: " - << points.size() << std::endl; - - CGAL::Tangential_complex< - Kernel, - INTRINSIC_DIMENSION, - CGAL::Parallel_tag> tc(points.begin(), points.end(), k); - double init_time = t.elapsed(); t.reset(); - - //tc.estimate_intrinsic_dimension(); - tc.compute_tangential_complex(); - double computation_time = t.elapsed(); t.reset(); - - std::set > incorrect_simplices; - //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); - - t.reset(); - unsigned int num_fix_steps = tc.fix_inconsistencies(); - double fix_time = t.elapsed(); t.reset(); - - double export_time = -1.; - if (INTRINSIC_DIMENSION <= 3) + /*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)*/ { - t.reset(); - std::stringstream output_filename; - output_filename << "data/test_tc_" << INTRINSIC_DIMENSION - << "_in_R" << AMBIENT_DIMENSION << ".off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); - double export_time = t.elapsed(); t.reset(); +#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." << std::endl; + script_file.seekg(0); + while (script_file.good()) + { + std::string line; + std::getline(script_file, line); + if (line.size() > 1 && line[0] != '#') + { + std::cerr << std::endl << std::endl; + std::cerr << "*****************************************" << std::endl; + std::cerr << "******* " << line << std::endl; + std::cerr << "*****************************************" << std::endl; + std::stringstream sstr(line); + + std::string input; + int ambient_dim; + int intrinsic_dim; + double sparsity; + double time_limit_for_fix; + int num_iteration; + sstr >> input; + sstr >> ambient_dim; + sstr >> intrinsic_dim; + sstr >> sparsity; + sstr >> time_limit_for_fix; + 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 << std::endl << "TC #" << i << "..." << std::endl; + + std::vector points; + + + //points = + //generate_points_on_circle_2(NUM_POINTS, 3.); + //generate_points_on_moment_curve(NUM_POINTS, ambient_dim, 0., 1.); + //generate_points_on_plane(NUM_POINTS); + //generate_points_on_sphere_3(NUM_POINTS, 3.0); + //generate_points_on_sphere_d(NUM_POINTS, ambient_dim, 3.0); + //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3., NOISE); + //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + + /*if (input == "Klein_function") + make_mesh_implicit(facet_approx, facet_sizing, cell_sizing, Klein_function(), input); + else*/ + { + load_points_from_file( + input, std::back_inserter(points)/*, 600*/); + make_tc(points, intrinsic_dim, sparsity, time_limit_for_fix); + } + + std::cerr << "TC #" << i++ << " done." << std::endl; + std::cerr << std::endl << "---------------------------------" << std::endl << std::endl; + + XML_perf_data::commit(); + } + } + } + script_file.seekg(0); + script_file.clear(); } - /*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 < Date: Mon, 26 Jan 2015 18:10:28 +0100 Subject: [PATCH 111/269] Script --- .../benchmark/Tangential_complex/benchmark_script.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt new file mode 100644 index 00000000000..5dde2a2a389 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -0,0 +1,2 @@ +#Input AMB INTR SPARSITY TIME_LIMIT NUM_ITERATIONS +data/SO3_10000.txt 9 3 0.05 60 5 \ No newline at end of file From bb8d57583889018a0fb01dbdf7d6aea07f7dd845 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Jan 2015 16:28:22 +0100 Subject: [PATCH 112/269] Updated test according to the latest changes in the TC --- .../Tangential_complex/test_tangential_complex.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 5a5f82b25a5..f9f359ec450 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -6,6 +6,7 @@ # define TBB_USE_THREADING_TOOL #endif +#include #include #include #include @@ -28,6 +29,11 @@ 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); @@ -43,7 +49,8 @@ int main() typedef Kernel::FT FT; typedef Kernel::Point_d Point; typedef CGAL::Tangential_complex< - Kernel, INTRINSIC_DIMENSION, CGAL::Parallel_tag> TC; + Kernel, CGAL::Dimension_tag, + CGAL::Parallel_tag> TC; int i = 0; bool stop = false; @@ -84,7 +91,7 @@ int main() std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; - TC tc(points.begin(), points.end(), k); + TC tc(points.begin(), points.end(), INTRINSIC_DIMENSION, k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); From 0f0228cf5f08c5f37b56d951605d069d100504a6 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 14:39:29 +0100 Subject: [PATCH 113/269] The benchmark can now generate points --- .../Tangential_complex/benchmark_script.txt | 14 ++- .../Tangential_complex/benchmark_tc.cpp | 84 +++++++++---- .../test/Tangential_complex/test_utilities.h | 115 +++++++++--------- 3 files changed, 130 insertions(+), 83 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 5dde2a2a389..cf2e5e11f60 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -1,2 +1,12 @@ -#Input AMB INTR SPARSITY TIME_LIMIT NUM_ITERATIONS -data/SO3_10000.txt 9 3 0.05 60 5 \ No newline at end of file +#Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY TIME_LIMIT NUM_ITERATIONS +#data/SO3_10000.txt - - - 0 9 3 0.05 60 1 + +############### Generated point sets ################### +#generate_sphere_d 3 - - 30000 3 2 0.05 60 1 +#generate_moment_curve 0 1 - 30000 6 1 0.05 60 1 +#generate_plane - - - 30000 3 2 0.05 60 1 +#generate_sphere_d 3 - - 30000 3 2 0.05 60 1 +#generate_sphere_d 3 - - 1000 6 5 0.05 60 1 +generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 +generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 +generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index cc788b7152d..b0fec26cdca 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -14,7 +14,10 @@ #include "../../test/Tangential_complex/test_utilities.h" +#include +#include +#include #include #include @@ -115,13 +118,6 @@ protected: XML_exporter::Element_with_map m_current_element; }; -const double NOISE = 0.01; -#ifdef _DEBUG - const int NUM_POINTS = 50; -#else - const int NUM_POINTS = 30000; -#endif - void make_tc(std::vector &points, int intrinsic_dim, double sparsity = 0., double time_limit_for_fix = 0.) { @@ -267,6 +263,8 @@ int main() std::getline(script_file, line); if (line.size() > 1 && line[0] != '#') { + boost::replace_all(line, "\t", " "); + boost::trim_all(line); std::cerr << std::endl << std::endl; std::cerr << "*****************************************" << std::endl; std::cerr << "******* " << line << std::endl; @@ -274,12 +272,20 @@ int main() 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; double sparsity; double time_limit_for_fix; int num_iteration; sstr >> input; + sstr >> param1; + sstr >> param2; + sstr >> param3; + sstr >> num_points; sstr >> ambient_dim; sstr >> intrinsic_dim; sstr >> sparsity; @@ -313,29 +319,59 @@ int main() std::cerr << std::endl << "TC #" << i << "..." << std::endl; std::vector points; - - //points = - //generate_points_on_circle_2(NUM_POINTS, 3.); - //generate_points_on_moment_curve(NUM_POINTS, ambient_dim, 0., 1.); - //generate_points_on_plane(NUM_POINTS); - //generate_points_on_sphere_3(NUM_POINTS, 3.0); - //generate_points_on_sphere_d(NUM_POINTS, ambient_dim, 3.0); - //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); - //generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3., NOISE); - //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); - - /*if (input == "Klein_function") - make_mesh_implicit(facet_approx, facet_sizing, cell_sizing, Klein_function(), input); - else*/ + if (input == "generate_moment_curve") + { + points = generate_points_on_moment_curve( + num_points, ambient_dim, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else if (input == "generate_plane") + { + points = generate_points_on_plane(num_points); + } + else if (input == "generate_sphere_d") + { + points = generate_points_on_sphere_d( + num_points, ambient_dim, + std::atof(param1.c_str())); + } + else if (input == "generate_klein_bottle_3D") + { + points = generate_points_on_klein_bottle_3D( + 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( + 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( + num_points, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else { load_points_from_file( input, std::back_inserter(points)/*, 600*/); - make_tc(points, intrinsic_dim, sparsity, time_limit_for_fix); } - std::cerr << "TC #" << i++ << " done." << std::endl; - std::cerr << std::endl << "---------------------------------" << std::endl << std::endl; + if (!points.empty()) + { + make_tc(points, intrinsic_dim, sparsity, time_limit_for_fix); + + std::cerr << "TC #" << i++ << " done." << std::endl; + std::cerr << std::endl << "---------------------------------" + << std::endl << std::endl; + } + else + { + std::cerr << "TC #" << i++ << ": no points loaded." << std::endl; + } XML_perf_data::commit(); } diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index f953736efd7..4e05725c991 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -30,6 +30,7 @@ #include #include #include +#include #include // Actually, this is very slow because the "m_points_ds->insert" @@ -82,6 +83,52 @@ private: }; #endif +// construct_point: dim 2 +template +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::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::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::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]); +} + template std::vector sparsify_point_set( @@ -181,6 +228,7 @@ std::vector generate_points_on_plane(std::size_t num_p { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; std::vector points; points.reserve(num_points); @@ -191,7 +239,7 @@ std::vector generate_points_on_plane(std::size_t num_p { FT x = rng.get_double(0, 5); FT y = rng.get_double(0, 5); - Point p = Kernel().construct_point_d_object()(x, y, 0); + Point p = construct_point(k, x, y, FT(0)); #ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER if (sparsifier.try_to_insert_point(p)) ++i; @@ -210,6 +258,7 @@ std::vector generate_points_on_moment_curve( { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; std::vector points; points.reserve(num_points); @@ -223,7 +272,7 @@ std::vector generate_points_on_moment_curve( coords.reserve(dim); for (int p = 1 ; p <= dim ; ++p) coords.push_back(std::pow(CGAL::to_double(x), p)); - Point p = Kernel().construct_point_d_object()( + 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)) @@ -236,56 +285,6 @@ std::vector generate_points_on_moment_curve( return points; } -template -std::vector generate_points_on_circle_2( - std::size_t num_points, double radius) -{ - typedef typename Kernel::Point_d Point; - CGAL::Random_points_on_circle_2 generator(radius); - std::vector points; - points.reserve(num_points); -#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER - Point_sparsifier > sparsifier(points); -#endif - for (std::size_t i = 0 ; i < num_points ; ) - { - Point p = *generator++; -#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 -std::vector generate_points_on_sphere_3( - std::size_t num_points, double radius) -{ - typedef typename Kernel::Point_d Point; - CGAL::Random_points_on_sphere_3 generator(radius); - std::vector points; - points.reserve(num_points); -#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER - Point_sparsifier > sparsifier(points); -#endif - for (std::size_t i = 0 ; i < num_points ; ) - { - Point p = *generator++; -#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 std::vector generate_points_on_sphere_d( std::size_t num_points, int dim, double radius) @@ -318,6 +317,7 @@ std::vector generate_points_on_klein_bottle_3D( { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; // if uniform @@ -345,7 +345,7 @@ std::vector generate_points_on_klein_bottle_3D( v = rng.get_double(0, 6.2832); } double tmp = cos(u/2)*sin(v) - sin(u/2)*sin(2.*v); - Point p = Kernel().construct_point_d_object()( + 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))); @@ -367,6 +367,7 @@ std::vector generate_points_on_klein_bottle_4D( { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; // if uniform @@ -393,12 +394,11 @@ std::vector generate_points_on_klein_bottle_4D( u = rng.get_double(0, 6.2832); v = rng.get_double(0, 6.2832); } - Point p = Kernel().construct_point_d_object()( - Kernel().construct_point_d_object()( + 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)))); + 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; @@ -419,6 +419,7 @@ generate_points_on_klein_bottle_variant_5D( { typedef typename Kernel::Point_d Point; typedef typename Kernel::FT FT; + Kernel k; CGAL::Random rng; // if uniform @@ -451,7 +452,7 @@ generate_points_on_klein_bottle_variant_5D( FT x4 = b*sin(v)*sin(u/2); FT x5 = x1 + x2 + x3 + x4; - Point p = Kernel().construct_point_d_object()(x1, x2, x3, x4, x5); + 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; From b42bdf8c3c79612da5c38832a0f07cfaeccd2c6e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 14:41:00 +0100 Subject: [PATCH 114/269] Change CGAL_TC_NUMBER_OF_PERTURBED_POINTS => macro --- Tangential_complex/include/CGAL/Tangential_complex.h | 3 +-- Tangential_complex/include/CGAL/Tangential_complex/config.h | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fbe98160738..7308a1a144e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1401,8 +1401,7 @@ private: KNS_range kns_range = m_points_ds.query_ANN( global_center, - m_intrinsic_dimension + 1 - + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS); + CGAL_TC_NUMBER_OF_PERTURBED_POINTS(m_intrinsic_dimension)); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; nn_it != kns_range.end() ; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index baa361b3d39..09abb486a95 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -37,13 +37,14 @@ //#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_CENTER_VERTEX_ONLY //#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY //#define CGAL_TC_PERTURB_THE_1_STAR // Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points -const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = -2; +//#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) +#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN From 19a229254a6cda7275afafa5caad1c96bb955dcd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:06:36 +0100 Subject: [PATCH 115/269] More stats + fixed a bug when there are infinite cells in the star --- .../Tangential_complex/benchmark_tc.cpp | 31 ++++++++++++++----- .../include/CGAL/Tangential_complex.h | 13 +++++++- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index b0fec26cdca..28fb56d5ae4 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -83,8 +83,11 @@ protected: subelements.push_back("Input"); subelements.push_back("Intrinsic_dim"); subelements.push_back("Ambient_dim"); - subelements.push_back("Num_points"); 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("Init_time"); subelements.push_back("Comput_time"); subelements.push_back("Fix_successful"); @@ -119,7 +122,8 @@ protected: }; void make_tc(std::vector &points, int intrinsic_dim, - double sparsity = 0., double time_limit_for_fix = 0.) + double sparsity = 0., double time_limit_for_fix = 0., + const char *input_name = "tc") { Kernel k; Wall_clock_timer t; @@ -134,6 +138,8 @@ void make_tc(std::vector &points, int intrinsic_dim, std::cerr << "Point set generated in " << t_gen.elapsed() << " seconds." << std::endl; #endif + + CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); if (sparsity != 0.) { @@ -144,8 +150,8 @@ void make_tc(std::vector &points, int intrinsic_dim, << num_points_before << " / " << points.size() << std::endl; } - CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); + CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); TC tc(points.begin(), points.end(), intrinsic_dim, k); double init_time = t.elapsed(); t.reset(); @@ -161,7 +167,7 @@ void make_tc(std::vector &points, int intrinsic_dim, { t.reset(); std::stringstream output_filename; - output_filename << "output/test_tc_" << intrinsic_dim + output_filename << "output/" << input_name << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_BEFORE_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); @@ -171,16 +177,24 @@ void make_tc(std::vector &points, int intrinsic_dim, t.reset(); unsigned int num_fix_steps; - CGAL::Fix_inconsistencies_status fix_ret = - tc.fix_inconsistencies(num_fix_steps, time_limit_for_fix); + std::size_t initial_num_inconsistent_local_tr; + std::size_t best_num_inconsistent_local_tr; + CGAL::Fix_inconsistencies_status fix_ret = tc.fix_inconsistencies( + num_fix_steps, initial_num_inconsistent_local_tr, + best_num_inconsistent_local_tr, time_limit_for_fix); double fix_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); double export_after_time = -1.; if (intrinsic_dim <= 3) { t.reset(); std::stringstream output_filename; - output_filename << "output/test_tc_" << intrinsic_dim + output_filename << "output/" << input_name << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_AFTER_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); @@ -362,7 +376,8 @@ int main() if (!points.empty()) { - make_tc(points, intrinsic_dim, sparsity, time_limit_for_fix); + make_tc(points, intrinsic_dim, sparsity, + time_limit_for_fix, input.c_str()); std::cerr << "TC #" << i++ << " done." << std::endl; std::cerr << std::endl << "---------------------------------" diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7308a1a144e..c2ce1049c88 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -338,7 +338,8 @@ public: // time_limit in seconds Fix_inconsistencies_status fix_inconsistencies( - unsigned int &num_steps, double time_limit = 0.) + unsigned int &num_steps, std::size_t &initial_num_inconsistent_local_tr, + std::size_t &best_num_inconsistent_local_tr, double time_limit = 0.) { Wall_clock_timer t; @@ -368,6 +369,7 @@ public: #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES bool done = false; + best_num_inconsistent_local_tr = m_triangulations.size(); num_steps = 0; while (!done) { @@ -454,6 +456,12 @@ public: # endif #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES + if (num_steps == 0) + initial_num_inconsistent_local_tr = num_inconsistent_local_tr; + + if (num_inconsistent_local_tr < best_num_inconsistent_local_tr) + best_num_inconsistent_local_tr = num_inconsistent_local_tr; + ++num_steps; done = (num_inconsistent_local_tr == 0); if (time_limit != 0 && t.elapsed() > time_limit) @@ -1268,6 +1276,9 @@ private: // For each cell for ( ; it_c != it_c_end ; ++it_c) { + if (tr.is_infinite(*it_c)) // Don't check infinite cells + continue; + //***************************************************************************** // STRATEGY 1: perturb all the points of the first inconsistent simplex //***************************************************************************** From 7c1978e42592bb724840f75ece33280502bce46b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:06:51 +0100 Subject: [PATCH 116/269] Updated script --- .../Tangential_complex/benchmark_script.txt | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index cf2e5e11f60..f2d7fefd45e 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -1,12 +1,25 @@ -#Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY TIME_LIMIT NUM_ITERATIONS -#data/SO3_10000.txt - - - 0 9 3 0.05 60 1 +#--------------------------------------------------------------------------------------------------------------------------------------------------------- +# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY FIX_TIME_LIMIT NUM_ITERATIONS +#--------------------------------------------------------------------------------------------------------------------------------------------------------- -############### Generated point sets ################### -#generate_sphere_d 3 - - 30000 3 2 0.05 60 1 -#generate_moment_curve 0 1 - 30000 6 1 0.05 60 1 -#generate_plane - - - 30000 3 2 0.05 60 1 -#generate_sphere_d 3 - - 30000 3 2 0.05 60 1 -#generate_sphere_d 3 - - 1000 6 5 0.05 60 1 -generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 -generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 -generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file +#------------------------------------------------------------------ From files --------------------------------------------------------------------------- +data/SO3_10000.txt - - - 0 9 3 0.05 60 1 +data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 +#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 60 1 +#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 60 1 +data/Cy8.txt - - - 0 24 2 0.1 60 1 +data/Kl.txt - - - 0 5 2 0.05 60 1 +data/S3.txt - - - 0 4 3 0.05 60 1 +data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 +data/fandisk.txt - - - 0 3 2 0.001 60 1 + + +#----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ +generate_sphere_d 3 - - 30000 2 1 0.05 60 1 +generate_sphere_d 3 - - 30000 3 2 0.05 60 1 +generate_sphere_d 3 - - 30000 4 3 0.05 60 1 +generate_plane - - - 30000 3 2 0.05 60 1 +generate_moment_curve 0 1 - 30000 6 1 0.05 60 1 +generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 +generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 +generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file From 69b9e2b4429aa1acf41b11f217196c3cef45eb95 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:19:33 +0100 Subject: [PATCH 117/269] Make "sparsity" a parameter --- .../Tangential_complex/benchmark_tc.cpp | 2 +- .../include/CGAL/Tangential_complex.h | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 28fb56d5ae4..f33c1ab443d 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -153,7 +153,7 @@ void make_tc(std::vector &points, int intrinsic_dim, CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); - TC tc(points.begin(), points.end(), intrinsic_dim, k); + TC tc(points.begin(), points.end(), sparsity, intrinsic_dim, k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c2ce1049c88..fa8d91fe235 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,8 +23,6 @@ #define TANGENTIAL_COMPLEX_H #include -const double HALF_SPARSITY = 0.5*INPUT_SPARSITY; -const double SQ_HALF_SPARSITY = HALF_SPARSITY*HALF_SPARSITY; #include #include @@ -186,13 +184,15 @@ public: /// Constructor for a range of points template Tangential_complex(InputIterator first, InputIterator last, - int intrinsic_dimension, + double sparsity, int intrinsic_dimension, const Kernel &k = Kernel()) : m_k(k), m_intrinsic_dimension(intrinsic_dimension), + m_half_sparsity(0.5*sparsity), + m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), + m_ambiant_dim(k.point_dimension_d_object()(*first)), m_points(first, last), - m_points_ds(m_points), - m_ambiant_dim(k.point_dimension_d_object()(*first)) + m_points_ds(m_points) {} /// Destructor @@ -887,7 +887,7 @@ private: if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*SQ_HALF_SPARSITY) // CJTODO: why is "4*" needed? + > *star_sphere_squared_radius + 4*m_sq_half_sparsity) // CJTODO: why is "4*" needed? break; Tr_point proj_pt = project_point_and_compute_weight( @@ -901,7 +901,7 @@ private: // CJTODO TEMP TEST /*if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*SQ_HALF_SPARSITY) + > *star_sphere_squared_radius + 4*m_sq_half_sparsity) std::cout << "ARGGGGGGGH" << std::endl;*/ vh->data() = neighbor_point_idx; @@ -1207,7 +1207,7 @@ private: // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] = rng.get_double(0., SQ_HALF_SPARSITY); + m_weights[point_idx] = rng.get_double(0., m_sq_half_sparsity); #endif // Perturb the position? @@ -1219,7 +1219,7 @@ private: tr_point_on_sphere_generator(m_ambiant_dim, 1); m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), HALF_SPARSITY); + *tr_point_on_sphere_generator++), m_half_sparsity); # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL const Tr_traits &local_tr_traits = m_triangulations[point_idx].tr().geom_traits(); @@ -1245,7 +1245,7 @@ private: { global_transl = k_transl( global_transl, - k_scaled_vec(tsb[i], HALF_SPARSITY*coord(local_random_transl, i)) + k_scaled_vec(tsb[i], m_half_sparsity*coord(local_random_transl, i)) ); } # endif @@ -1618,6 +1618,8 @@ private: private: const Kernel m_k; const int m_intrinsic_dimension; + const double m_half_sparsity; + const double m_sq_half_sparsity; const int m_ambiant_dim; Points m_points; From 32484161a665cdd4d18a76ff39a740f429cf968b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:22:28 +0100 Subject: [PATCH 118/269] Update test according to last changes --- .../test/Tangential_complex/test_tangential_complex.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index f9f359ec450..be393b70f9a 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -91,7 +91,7 @@ int main() std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; - TC tc(points.begin(), points.end(), INTRINSIC_DIMENSION, k); + TC tc(points.begin(), points.end(), INPUT_SPARSITY, INTRINSIC_DIMENSION, k); double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); @@ -115,8 +115,11 @@ int main() t.reset(); unsigned int num_fix_steps; - CGAL::Fix_inconsistencies_status fix_ret = - tc.fix_inconsistencies(num_fix_steps, 3000.); + std::size_t initial_num_inconsistent_local_tr; + std::size_t best_num_inconsistent_local_tr; + CGAL::Fix_inconsistencies_status fix_ret = tc.fix_inconsistencies( + num_fix_steps, initial_num_inconsistent_local_tr, + best_num_inconsistent_local_tr, 3000.); double fix_time = t.elapsed(); t.reset(); double export_after_time = -1.; From 40981e372d538d4c439176466e960f34e9934209 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 16:37:26 +0100 Subject: [PATCH 119/269] INPUT_SPARSITY constant is for test only --- .../Tangential_complex/benchmark_script.txt | 18 +++++++++--------- .../Tangential_complex/benchmark_tc.cpp | 3 +-- .../include/CGAL/Tangential_complex/config.h | 1 - .../test_tangential_complex.cpp | 3 +++ .../test/Tangential_complex/test_utilities.h | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index f2d7fefd45e..01831bfcad4 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -3,23 +3,23 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- #------------------------------------------------------------------ From files --------------------------------------------------------------------------- -data/SO3_10000.txt - - - 0 9 3 0.05 60 1 -data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.05 60 1 +#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 #data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 60 1 #data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 60 1 -data/Cy8.txt - - - 0 24 2 0.1 60 1 -data/Kl.txt - - - 0 5 2 0.05 60 1 -data/S3.txt - - - 0 4 3 0.05 60 1 +#data/Cy8.txt - - - 0 24 2 0.1 60 1 +#data/Kl.txt - - - 0 5 2 0.05 60 1 +#data/S3.txt - - - 0 4 3 0.05 60 1 data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 data/fandisk.txt - - - 0 3 2 0.001 60 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ -generate_sphere_d 3 - - 30000 2 1 0.05 60 1 -generate_sphere_d 3 - - 30000 3 2 0.05 60 1 +generate_sphere_d 3 - - 30000 2 1 0.005 60 1 +generate_sphere_d 3 - - 30000 3 2 0.005 60 1 generate_sphere_d 3 - - 30000 4 3 0.05 60 1 -generate_plane - - - 30000 3 2 0.05 60 1 -generate_moment_curve 0 1 - 30000 6 1 0.05 60 1 +generate_plane - - - 30000 3 2 0.005 60 1 +generate_moment_curve 0 1 - 30000 6 1 0.005 60 1 generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index f33c1ab443d..aaec0eccaeb 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -144,8 +144,7 @@ void make_tc(std::vector &points, int intrinsic_dim, if (sparsity != 0.) { std::size_t num_points_before = points.size(); - points = sparsify_point_set( - k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + points = sparsify_point_set(k, points, sparsity*sparsity); std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 09abb486a95..4e9b096cd55 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -62,6 +62,5 @@ //========================= Parameters ======================================== const std::size_t NUM_POINTS_FOR_PCA = 30; -const double INPUT_SPARSITY = 0.05; #endif // CGAL_TC_CONFIG_H diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index be393b70f9a..92588529562 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -21,11 +21,14 @@ # include #endif +//=============== Constants ================= +const double INPUT_SPARSITY = 0.05; #ifdef _DEBUG const int NUM_POINTS = 50; #else const int NUM_POINTS = 30000; #endif +//=========================================== int main() { diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 4e05725c991..1eb2e3ad57d 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -49,7 +49,7 @@ public: // 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(INPUT_SPARSITY*INPUT_SPARSITY)) + FT sparsity = FT(0.05*0.05)) : m_points(points), m_sparsity(sparsity), m_points_ds(NULL) {} From 0e41484487b572a7b54425c68c8f7c8ba48d41f0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 18:16:15 +0100 Subject: [PATCH 120/269] Added Final_num_inconsistent_local_tr + bugfix --- .../Tangential_complex/benchmark_tc.cpp | 22 ++++++++++++++++--- .../include/CGAL/Tangential_complex.h | 9 ++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index aaec0eccaeb..57feead3808 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -88,6 +88,7 @@ protected: 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("Fix_successful"); @@ -128,6 +129,17 @@ void make_tc(std::vector &points, int intrinsic_dim, Kernel k; Wall_clock_timer t; + 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_PROFILING @@ -166,7 +178,7 @@ void make_tc(std::vector &points, int intrinsic_dim, { t.reset(); std::stringstream output_filename; - output_filename << "output/" << input_name << "_" << intrinsic_dim + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_BEFORE_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); @@ -178,22 +190,26 @@ void make_tc(std::vector &points, int intrinsic_dim, 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( num_fix_steps, initial_num_inconsistent_local_tr, - best_num_inconsistent_local_tr, time_limit_for_fix); + best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, + time_limit_for_fix); double fix_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); double export_after_time = -1.; if (intrinsic_dim <= 3) { t.reset(); std::stringstream output_filename; - output_filename << "output/" << input_name << "_" << intrinsic_dim + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_AFTER_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); tc.export_to_off(off_stream, true, &incorrect_simplices, true); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fa8d91fe235..3922b17800f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -338,8 +338,11 @@ public: // time_limit in seconds Fix_inconsistencies_status fix_inconsistencies( - unsigned int &num_steps, std::size_t &initial_num_inconsistent_local_tr, - std::size_t &best_num_inconsistent_local_tr, double time_limit = 0.) + unsigned int &num_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, + double time_limit = 0.) { Wall_clock_timer t; @@ -462,6 +465,8 @@ public: if (num_inconsistent_local_tr < best_num_inconsistent_local_tr) best_num_inconsistent_local_tr = num_inconsistent_local_tr; + final_num_inconsistent_local_tr = num_inconsistent_local_tr; + ++num_steps; done = (num_inconsistent_local_tr == 0); if (time_limit != 0 && t.elapsed() > time_limit) From 712ba3fc11a5e7c54ffa0ae2476f5f6366a0fb94 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 18:18:33 +0100 Subject: [PATCH 121/269] Updated script --- .../Tangential_complex/benchmark_script.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 01831bfcad4..a8b37db1bbb 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -3,15 +3,15 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- #------------------------------------------------------------------ From files --------------------------------------------------------------------------- -#data/SO3_10000.txt - - - 0 9 3 0.05 60 1 -#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 +data/SO3_10000.txt - - - 0 9 3 0.05 60 1 +data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 #data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 60 1 #data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 60 1 -#data/Cy8.txt - - - 0 24 2 0.1 60 1 -#data/Kl.txt - - - 0 5 2 0.05 60 1 -#data/S3.txt - - - 0 4 3 0.05 60 1 +data/Cy8.txt - - - 0 24 2 0.1 60 1 +data/Kl.txt - - - 0 5 2 0.05 60 1 +data/S3.txt - - - 0 4 3 0.05 60 1 data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 -data/fandisk.txt - - - 0 3 2 0.001 60 1 +data/fandisk.txt - - - 0 3 2 0.01 60 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ From 2cec91f5f5864a04e2bf4d828bbc88a7cba619f3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 28 Jan 2015 18:31:08 +0100 Subject: [PATCH 122/269] Try another technique --- Tangential_complex/include/CGAL/Tangential_complex/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 4e9b096cd55..99700380d61 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -43,8 +43,8 @@ // Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points -//#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) -#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) +#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) +//#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN From 4a588310d9faac9851e48061f628621613789cd4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 2 Feb 2015 10:18:39 +0100 Subject: [PATCH 123/269] Unused variable --- Tangential_complex/include/CGAL/Tangential_complex.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3922b17800f..58501ed0f7c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1426,7 +1426,6 @@ private: neighbors.push_back(nn_it->first); } - CGAL::Random rng; for (std::vector::iterator it = neighbors.begin(); it != neighbors.end() ; ++it) From 6012256fc17b103190b786a0ee2b9d162304c605 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Feb 2015 15:01:41 +0100 Subject: [PATCH 124/269] Updated comment --- Tangential_complex/include/CGAL/Tangential_complex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 58501ed0f7c..f58170d6e27 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -890,9 +890,10 @@ private: FT neighbor_weight = 0; #endif + // "4*m_sq_half_sparsity" because both points can be perturbed if (star_sphere_squared_radius && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*m_sq_half_sparsity) // CJTODO: why is "4*" needed? + > *star_sphere_squared_radius + 4*m_sq_half_sparsity) break; Tr_point proj_pt = project_point_and_compute_weight( From 875a33fef12f6a202836d9e88d9c08b1fb5c7acc Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Feb 2015 18:10:34 +0100 Subject: [PATCH 125/269] Avoid to export duplicate simplices --- .../include/CGAL/Tangential_complex.h | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f58170d6e27..e01778c7c2c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1301,7 +1301,7 @@ private: if (!is_simplex_consistent(c)) { is_inconsistent = true; - + for (std::set::iterator it=c.begin(); it!=c.end(); ++it) perturb(*it); @@ -1516,7 +1516,7 @@ private: typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for ( ; it_tr != it_tr_end ; ++it_tr) + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); @@ -1555,6 +1555,11 @@ private: if (m_intrinsic_dimension == 1) sstr_c << (data*factor + 1) << " "; + // In order to have only one time each simplex, we only keep it + // if the lowest index is the index of the center vertex + if (*c.begin() != idx) + continue; + bool excluded = (excluded_simplices && excluded_simplices->find(c) != excluded_simplices->end()); @@ -1582,16 +1587,27 @@ private: else { os << OFF_simplices_dim << " "; + std::size_t min_index = std::numeric_limits::max(); std::size_t data; + std::stringstream sstr_c; for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) { data = (*it_c)->vertex(i)->data(); - os << data*factor << " "; + if (data < min_index) + min_index = data; + sstr_c << data*factor << " "; } + + // In order to have only one time each simplex, we only keep it + // if the lowest index is the index of the center vertex + if (min_index != idx) + continue; + // See export_vertices_to_off if (m_intrinsic_dimension == 1) - os << (data*factor + 1) << " "; + sstr_c << (data*factor + 1) << " "; + os << sstr_c.str(); ++num_simplices; } From 39524b21ebd2a5f945443e66430544fba9cf5331 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Feb 2015 18:32:23 +0100 Subject: [PATCH 126/269] Fixed debug code (2-sphere normal computation) --- .../include/CGAL/Tangential_complex.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index e01778c7c2c..d1898215b90 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -970,6 +970,8 @@ private: #endif ) const { + //******************************* PCA ************************************* + // Kernel functors typename Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); @@ -987,8 +989,6 @@ private: KNS_range kns_range = m_points_ds.query_ANN( p, NUM_POINTS_FOR_PCA, false); - //******************************* PCA ************************************* - // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); KNS_iterator nn_it = kns_range.begin(); @@ -1030,12 +1030,14 @@ private: return compute_gram_schmidt_basis(ts, m_k); - /* + // CJTODO: this is only for a sphere in R^3 - Vector t1(-p[1] - p[2], p[0], p[0]); - Vector t2(p[1] * t1[2] - p[2] * t1[1], - p[2] * t1[0] - p[0] * t1[2], - p[0] * t1[1] - p[1] * t1[0]); + /*double tt1[3] = {-p[1] - p[2], p[0], p[0]}; + double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], + p[2] * tt1[0] - p[0] * tt1[2], + p[0] * tt1[1] - p[1] * tt1[0]}; + Vector t1(3, &tt1[0], &tt1[3]); + Vector t2(3, &tt2[0], &tt2[3]); // Normalize t1 and t2 typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); From a9c27d8db6bd7047e50254447665470e5e4a0753 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 5 Feb 2015 11:53:28 +0100 Subject: [PATCH 127/269] Added option USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + fix export --- .../Tangential_complex/benchmark_tc.cpp | 12 +++- .../include/CGAL/Tangential_complex.h | 56 +++++++++++++++---- .../include/CGAL/Tangential_complex/config.h | 1 + 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 57feead3808..a1877f69dd5 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -152,6 +152,10 @@ void make_tc(std::vector &points, int intrinsic_dim, #endif CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); + +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + std::vector points_not_sparse = points; +#endif if (sparsity != 0.) { @@ -163,8 +167,14 @@ void make_tc(std::vector &points, int intrinsic_dim, CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); - + +#ifdef 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 + double init_time = t.elapsed(); t.reset(); tc.compute_tangential_complex(); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d1898215b90..9b928710272 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -185,7 +185,11 @@ public: template Tangential_complex(InputIterator first, InputIterator last, double sparsity, int intrinsic_dimension, - const Kernel &k = Kernel()) +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + InputIterator first_for_tse, InputIterator last_for_tse, +#endif + const Kernel &k = Kernel() + ) : m_k(k), m_intrinsic_dimension(intrinsic_dimension), m_half_sparsity(0.5*sparsity), @@ -193,6 +197,10 @@ public: m_ambiant_dim(k.point_dimension_d_object()(*first)), m_points(first, last), m_points_ds(m_points) +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + , m_points_for_tse(first_for_tse, last_for_tse) + , m_points_ds_for_tse(m_points_for_tse) +#endif {} /// Destructor @@ -985,9 +993,15 @@ private: m_k.scalar_product_d_object(); typename Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - - KNS_range kns_range = m_points_ds.query_ANN( + +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + KNS_range kns_range = m_points_ds_for_tse.query_ANN( p, NUM_POINTS_FOR_PCA, false); + const Points &points_for_pca = m_points_for_tse; +#else + KNS_range kns_range = m_points_ds.query_ANN(p, NUM_POINTS_FOR_PCA, false); + const Points &points_for_pca = m_points; +#endif // One row = one point Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); @@ -997,7 +1011,7 @@ private: ++j, ++nn_it) { for (int i = 0 ; i < m_ambiant_dim ; ++i) - mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); + mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -1515,11 +1529,14 @@ private: (m_intrinsic_dimension == 1 ? 3 : m_intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; + std::size_t num_inconsistent_stars = 0; typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { + bool is_star_inconsistent = false; + Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); @@ -1553,13 +1570,18 @@ private: sstr_c << data*factor << " "; c.insert(data); } + + bool is_simpl_consistent = is_simplex_consistent(c); + if (!is_simpl_consistent) + is_star_inconsistent = true; + // See export_vertices_to_off if (m_intrinsic_dimension == 1) sstr_c << (data*factor + 1) << " "; // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != idx) + if (*c.begin() != idx && is_simpl_consistent) continue; bool excluded = @@ -1569,7 +1591,7 @@ private: if (!excluded) { os << OFF_simplices_dim << " " << sstr_c.str() << " "; - if (color_inconsistencies && is_simplex_consistent(c)) + if (color_inconsistencies && is_simpl_consistent) os << color.str(); else { @@ -1615,6 +1637,8 @@ private: os << std::endl; } + if (is_star_inconsistent) + ++num_inconsistent_stars; } #ifdef CGAL_TC_VERBOSE @@ -1623,13 +1647,16 @@ private: << std::endl << "Export to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices in stars (incl. duplicates): " - << num_simplices << std::endl - << " * Number of inconsistent simplices in stars (incl. duplicates): " - << num_inconsistent_simplices << std::endl - << " * Percentage of inconsistencies: " + << " * Total number of simplices: " << num_simplices << std::endl + << " * Number of inconsistent stars: " + << num_inconsistent_stars << " (" + << (m_points.size() > 0 ? + 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)" + << std::endl + << " * Number of inconsistent simplices: " + << num_inconsistent_simplices << " (" << (num_simplices > 0 ? - 100. * num_inconsistent_simplices / num_simplices : 0.) << "%" + 100. * num_inconsistent_simplices / num_simplices : 0.) << "%)" << std::endl << "==========================================================" << std::endl; @@ -1664,6 +1691,11 @@ private: Vectors m_normals; #endif +#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + Points m_points_for_tse; + Points_ds m_points_ds_for_tse; +#endif + }; // /class Tangential_complex } // end namespace CGAL diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 99700380d61..871b8fb5ef4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -35,6 +35,7 @@ #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES +#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM // Solving inconsistencies: only perturb the vertex, the simplex or more? //#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY From 0ed94233cb55c0fd726f850cae49706e6d7987ff Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 10 Feb 2015 13:11:23 +0100 Subject: [PATCH 128/269] Add a cache to store stars (uses std::set) --- .../include/CGAL/Tangential_complex.h | 60 +++++++++++++++---- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 9b928710272..ae02c0914e7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -122,6 +122,7 @@ class Tangential_complex typedef std::vector Points; typedef std::vector Weights; + typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; @@ -167,6 +168,13 @@ class Tangential_complex typedef typename std::vector TS_container; typedef typename std::vector Tr_container; typedef typename std::vector Vectors; + + // An Incident_simplex is the list of the verter indices + // except the center vertex + typedef std::set Incident_simplex; + typedef std::vector Star; + typedef std::vector Stars_container; + #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm @@ -221,6 +229,7 @@ public: // already-computed triangulations (while resizing) since it would // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); + m_stars.resize(m_points.size()); #ifdef CGAL_LINKED_WITH_TBB //m_tr_mutexes.resize(m_points.size()); #endif @@ -962,6 +971,34 @@ private: } + + //*************************************************** + // Update the associated star (in m_stars) + //*************************************************** + Star &star = m_stars[i]; + int cur_dim_plus_1 = local_tr.current_dimension() + 1; + star.clear(); + + std::vector incident_cells; + local_tr.incident_full_cells( + center_vertex, std::back_inserter(incident_cells)); + + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + // Will contain all indices except center_vertex + Incident_simplex inc_simplex; + for (int j = 0 ; j < cur_dim_plus_1 ; ++j) + { + std::size_t index = (*it_c)->vertex(j)->data(); + if (index != i) + inc_simplex.insert(index); + } + star.push_back(inc_simplex); + } + // CJTODO DEBUG //std::cerr << "\nChecking topology and geometry..." // << (local_tr.is_valid(true) ? "OK.\n" : "Error.\n"); @@ -1169,23 +1206,23 @@ private: std::size_t point_idx = *it_point_idx; if (point_idx == std::numeric_limits::max()) continue; - Triangulation const& tr = m_triangulations[point_idx].tr(); - Tr_vertex_handle center_vh = m_triangulations[point_idx].center_vertex(); + Star const& star = m_stars[point_idx]; - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + // What we're looking for is "simplex" \ point_idx + Incident_simplex ic_to_find = simplex; + ic_to_find.erase(point_idx); - typename std::vector::const_iterator it_c = incident_cells.begin(); - typename std::vector::const_iterator it_c_end= incident_cells.end(); // For each cell bool found = false; - for ( ; !found && it_c != it_c_end ; ++it_c) + Star::const_iterator it_inc_simplex = star.begin(); + Star::const_iterator it_inc_simplex_end = star.end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - std::set cell; - for (int i = 0 ; i < cur_dim_plus_1 ; ++i) - cell.insert((*it_c)->vertex(i)->data()); - if (cell == simplex) + if (*it_inc_simplex == ic_to_find) + { found = true; + break; + } } if (!found) @@ -1684,6 +1721,7 @@ private: TS_container m_tangent_spaces; Tr_container m_triangulations; // Contains the triangulations // and their center vertex + Stars_container m_stars; #ifdef CGAL_LINKED_WITH_TBB //std::vector m_tr_mutexes; #endif From 039af01fe505f07a1bd7b790724a46c8e30cae01 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 10 Feb 2015 16:34:22 +0100 Subject: [PATCH 129/269] Optimize functions thanks to the cache "m_stars" Most calls to incident_full_cells can be avoided --- .../include/CGAL/Tangential_complex.h | 157 ++++++++++-------- .../include/CGAL/Tangential_complex/config.h | 8 +- 2 files changed, 97 insertions(+), 68 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ae02c0914e7..a3a59df54fe 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -518,6 +518,7 @@ public: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); + // CJTODO: use m_stars[...] std::vector incident_cells; tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); @@ -970,8 +971,6 @@ private: } } - - //*************************************************** // Update the associated star (in m_stars) //*************************************************** @@ -1262,11 +1261,9 @@ private: void perturb(std::size_t point_idx) { - CGAL::Random rng; - // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] = rng.get_double(0., m_sq_half_sparsity); + m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); #endif // Perturb the position? @@ -1320,50 +1317,46 @@ private: //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif + Star const& star = m_stars[tr_index]; Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); const Tr_traits &local_tr_traits = tr.geom_traits(); int cur_dim = tr.current_dimension(); - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - typename std::vector::const_iterator it_c = - incident_cells.begin(); - typename std::vector::const_iterator it_c_end= - incident_cells.end(); - // For each cell - for ( ; it_c != it_c_end ; ++it_c) + // For each incident simplex + Star::const_iterator it_inc_simplex = star.begin(); + Star::const_iterator it_inc_simplex_end = star.end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - if (tr.is_infinite(*it_c)) // Don't check infinite cells + const Incident_simplex &inc_simplex = *it_inc_simplex; + + // Don't check infinite cells + if (*inc_simplex.rbegin() == std::numeric_limits::max()) continue; + std::set c = inc_simplex; + c.insert(tr_index); // Add the missing index + //***************************************************************************** // STRATEGY 1: perturb all the points of the first inconsistent simplex //***************************************************************************** #ifdef CGAL_TC_PERTURB_THE_SIMPLEX_ONLY - - std::set c; - for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) - { - std::size_t data = (*it_c)->vertex(i)->data(); - c.insert(data); - } - // Inconsistent? if (!is_simplex_consistent(c)) { is_inconsistent = true; - for (std::set::iterator it=c.begin(); it!=c.end(); ++it) + for (std::set::const_iterator it = c.begin(); + it != c.end() ; ++it) + { perturb(*it); + } # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif - // We will try the other cells next time (incident_cells is not - // valid anymore here) + // We will try the other cells next time break; } @@ -1371,7 +1364,7 @@ private: // STRATEGY 2: perturb the center point only //***************************************************************************** #elif defined(CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY) - if (!is_simplex_consistent(*it_c, cur_dim)) + if (!is_simplex_consistent(c)) { is_inconsistent = true; @@ -1389,8 +1382,7 @@ private: refresh_tangential_complex(); # endif - // We will try the other cells next time (incident_cells is not - // valid anymore here) + // We will try the other cells next time break; } @@ -1400,43 +1392,68 @@ private: #elif defined(CGAL_TC_PERTURB_THE_1_STAR) // Inconsistent? - if (!is_simplex_consistent(*it_c, cur_dim)) + if (!is_simplex_consistent(c)) { is_inconsistent = true; - std::set c; + std::set the_1_star; - typename std::vector::const_iterator it_c2 = - incident_cells.begin(); - // For each cell - for ( ; it_c2 != it_c_end ; ++it_c2) + Star::const_iterator it_inc_simplex = star.begin(); + Star::const_iterator it_inc_simplex_end = star.end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) - { - std::size_t data = (*it_c2)->vertex(i)->data(); - c.insert(data); - } + the_1_star.insert(it_inc_simplex->begin(), it_inc_simplex ->end()); } - for (std::set::iterator it=c.begin(); it!=c.end(); ++it) + for (std::set::iterator it = the_1_star.begin() ; + it != the_1_star.end() ; ++it) + { perturb(*it); + } # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif - // We will try the other cells next time (incident_cells is not - // valid anymore here) + // We will try the other cells next time break; } +//***************************************************************************** +// STRATEGY 4: perturb one random point of the simplex +//***************************************************************************** +#else + // Inconsistent? + if (!is_simplex_consistent(c)) + { + is_inconsistent = true; + int rnd = m_random_generator.get_int(0, static_cast(c.size())); + if (rnd == 0) + perturb(tr_index); + else + { + std::set::const_iterator it_idx = c.begin(); + std::advance(it_idx, rnd - 1); + perturb(*it_idx); + } + +# if !defined(CGAL_TC_GLOBAL_REFRESH) + refresh_tangential_complex(); +# endif + + // We will try the other cells next time + break; + } + +#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY + //***************************************************************************** // STRATEGY 4: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points (to the power center of first the inconsistent cell) //***************************************************************************** -#else +/*#else // Inconsistent? - if (!is_simplex_consistent(*it_c, cur_dim)) + if (!is_simplex_consistent(c)) { is_inconsistent = true; @@ -1444,8 +1461,13 @@ private: // closest points std::vector simplex_pts; - for (int i = 0 ; i < cur_dim + 1 ; ++i) - simplex_pts.push_back((*it_c)->vertex(i)->point()); + + Incident_simplex::const_iterator it_point_idx = c.begin(); + Incident_simplex::const_iterator it_point_idx_end = c.end(); + // For each point p of the simplex, we parse the incidents cells of p + // and we check if "simplex" is among them + for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) + simplex_pts.push_back(m_points[*it_point_idx]); //typename Tr_traits::Power_center_d power_center = // local_tr_traits.power_center_d_object(); // CJTODO @@ -1491,12 +1513,11 @@ private: refresh_tangential_complex(); # endif - // We will try the other cells next time (incident_cells is not - // valid anymore here) + // We will try the other cells next time break; } -#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY +#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY*/ } return is_inconsistent; @@ -1584,28 +1605,29 @@ private: std::stringstream color; //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; color << 128 << " " << 128 << " " << 128; - - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - typename std::vector::const_iterator it_c = incident_cells.begin(); - typename std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell - for ( ; it_c != it_c_end ; ++it_c) + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - if (tr.is_infinite(*it_c)) // Don't export infinite cells + // Don't export infinite cells + if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; + + std::set c = *it_inc_simplex; + c.insert(idx); if (color_inconsistencies || excluded_simplices) { - std::set c; std::stringstream sstr_c; std::size_t data; - for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) + + std::set::const_iterator it_point_idx = c.begin(); + for ( ; it_point_idx != c.end() ; ++it_point_idx) { - data = (*it_c)->vertex(i)->data(); + data = *it_point_idx; sstr_c << data*factor << " "; - c.insert(data); } bool is_simpl_consistent = is_simplex_consistent(c); @@ -1651,11 +1673,11 @@ private: std::size_t min_index = std::numeric_limits::max(); std::size_t data; std::stringstream sstr_c; - for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) + std::set::const_iterator it_point_idx = c.begin(); + min_index = *it_point_idx; + for ( ; it_point_idx != c.end() ; ++it_point_idx) { - data = (*it_c)->vertex(i)->data(); - if (data < min_index) - min_index = data; + data = *it_point_idx; sstr_c << data*factor << " "; } @@ -1734,6 +1756,9 @@ private: Points_ds m_points_ds_for_tse; #endif + + CGAL::Random m_random_generator; + }; // /class Tangential_complex } // end namespace CGAL diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 871b8fb5ef4..0c38e13ad8b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -35,17 +35,21 @@ #define CGAL_TC_PROFILING #define CGAL_TC_VERBOSE //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES -#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +//#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM // 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 +// Otherwise, perturb one random point of the simplex + +/* // Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points #define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1) //#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2) +*/ //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN @@ -62,6 +66,6 @@ //#define CGAL_TC_PERTURB_WEIGHT //========================= Parameters ======================================== -const std::size_t NUM_POINTS_FOR_PCA = 30; +const std::size_t NUM_POINTS_FOR_PCA = 20; #endif // CGAL_TC_CONFIG_H From c73b9c3316e50b6f256e4fb1ddab9465f2e80ef7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 10 Feb 2015 19:33:07 +0100 Subject: [PATCH 130/269] Added the ability to perturb tangent spaces + fix Compute_tangent_triangulation constructor --- .../include/CGAL/Tangential_complex.h | 45 +++++++++++++++++-- .../include/CGAL/Tangential_complex/config.h | 1 + 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index a3a59df54fe..55fb8e26167 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -241,6 +241,9 @@ public: m_translations.resize(m_points.size(), m_k.construct_vector_d_object()(m_ambiant_dim)); #endif +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + m_perturb_tangent_space.resize(m_points.size(), false); +#endif #ifdef CGAL_TC_EXPORT_NORMALS m_normals.resize(m_points.size(), m_k.construct_vector_d_object()(m_ambiant_dim)); @@ -800,7 +803,9 @@ private: // Constructor Compute_tangent_triangulation(const Compute_tangent_triangulation &ctt) - : m_tc(ctt.m_tc) + : m_tc(ctt.m_tc), + m_tangent_spaces_are_already_computed( + ctt.m_tangent_spaces_are_already_computed) {} // operator() @@ -858,6 +863,17 @@ private: m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif } +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + else if (m_perturb_tangent_space[i]) + { +#ifdef CGAL_TC_EXPORT_NORMALS + m_tangent_spaces[i] = compute_tangent_space(center_pt,&m_normals[i],true); +#else + m_tangent_spaces[i] = compute_tangent_space(center_pt, true); +#endif + m_perturb_tangent_space[i] = false; + } +#endif //*************************************************** // Build a minimal triangulation in the tangent space @@ -1011,6 +1027,9 @@ private: Tangent_space_basis compute_tangent_space(const Point &p #ifdef CGAL_TC_EXPORT_NORMALS , Vector *p_normal +#endif +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + , bool perturb = false #endif ) const { @@ -1029,6 +1048,8 @@ private: m_k.scalar_product_d_object(); typename Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); + //typename Kernel::Translated_point_d transl = + // m_k.translated_point_d_object(); #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM KNS_range kns_range = m_points_ds_for_tse.query_ANN( @@ -1047,7 +1068,15 @@ private: ++j, ++nn_it) { for (int i = 0 ; i < m_ambiant_dim ; ++i) - mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i)); + { + //const Point p = transl( + // m_points[nn_it->first], m_translations[nn_it->first]); + mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + if (perturb) + mat_points(j, i) += m_random_generator.get_double(-0.3, 0.3); +#endif + } } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); Eigen::MatrixXd cov = centered.adjoint() * centered; @@ -1203,8 +1232,10 @@ private: for ( ; it_point_idx != simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; + // Don't check infinite simplices if (point_idx == std::numeric_limits::max()) continue; + Star const& star = m_stars[point_idx]; // What we're looking for is "simplex" \ point_idx @@ -1265,6 +1296,10 @@ private: #ifdef CGAL_TC_PERTURB_WEIGHT m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); #endif + +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + m_perturb_tangent_space[point_idx] = true; +#endif // Perturb the position? #ifdef CGAL_TC_PERTURB_POSITION @@ -1738,6 +1773,9 @@ private: #ifdef CGAL_TC_PERTURB_POSITION Vectors m_translations; #endif +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + std::vector m_perturb_tangent_space; +#endif Points_ds m_points_ds; TS_container m_tangent_spaces; @@ -1756,8 +1794,7 @@ private: Points_ds m_points_ds_for_tse; #endif - - CGAL::Random m_random_generator; + mutable CGAL::Random m_random_generator; }; // /class Tangential_complex diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 0c38e13ad8b..a5ed583a95d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -64,6 +64,7 @@ # 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 ======================================== const std::size_t NUM_POINTS_FOR_PCA = 20; From 643123afdac5e43122a4ad3f02fe5b569f64f83f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 11:47:08 +0100 Subject: [PATCH 131/269] Update test (new param) --- .../test/Tangential_complex/test_tangential_complex.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 92588529562..69f6f54f02e 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -120,9 +120,10 @@ int main() 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( num_fix_steps, initial_num_inconsistent_local_tr, - best_num_inconsistent_local_tr, 3000.); + best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, 1000.); double fix_time = t.elapsed(); t.reset(); double export_after_time = -1.; From f4496dfd7efb6f38a649a316bed6b97cc5316d42 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 11:52:07 +0100 Subject: [PATCH 132/269] Updated script --- .../Tangential_complex/benchmark_script.txt | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index a8b37db1bbb..ffcaec285e8 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -2,24 +2,33 @@ # Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- -#------------------------------------------------------------------ From files --------------------------------------------------------------------------- -data/SO3_10000.txt - - - 0 9 3 0.05 60 1 -data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 60 1 -#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 60 1 -#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 60 1 -data/Cy8.txt - - - 0 24 2 0.1 60 1 -data/Kl.txt - - - 0 5 2 0.05 60 1 -data/S3.txt - - - 0 4 3 0.05 60 1 -data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 -data/fandisk.txt - - - 0 3 2 0.01 60 1 +#---------------------------------------------------------- Very small cases for Debug mode ------------------------------------------------------------- +#generate_sphere_d 3 - - 20 3 2 0.05 3000 1 +#generate_klein_bottle_4D 4 3 - 20 4 2 1.5 3000 1 +#------------------------------------------------------------------ From files --------------------------------------------------------------------------- +#data/SO3_50000.txt - - - 0 9 3 0.2 3000 1 +data/SO3_10000.txt - - - 0 9 3 0.05 3000 1 +#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 3000 1 +#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 3000 1 +#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 3000 1 +#data/Cy8.txt - - - 0 24 2 0.1 3000 1 +#data/Kl.txt - - - 0 5 2 0.05 3000 1 +#data/S3.txt - - - 0 4 3 0.05 3000 1 +#data/buddha_100kv.txt - - - 0 3 2 0.005 3000 1 +#data/fandisk.txt - - - 0 3 2 0.01 3000 1 +#data/fertility.txt - - - 0 3 2 0.1 600 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ -generate_sphere_d 3 - - 30000 2 1 0.005 60 1 -generate_sphere_d 3 - - 30000 3 2 0.005 60 1 -generate_sphere_d 3 - - 30000 4 3 0.05 60 1 -generate_plane - - - 30000 3 2 0.005 60 1 -generate_moment_curve 0 1 - 30000 6 1 0.005 60 1 -generate_klein_bottle_3D 4 3 - 30000 3 2 0.05 60 1 -generate_klein_bottle_4D 4 3 - 10000 4 2 0.05 60 1 -generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 \ No newline at end of file +#generate_sphere_d 3 - - 4 3 2 0.05 3000 1 +#generate_sphere_d 3 - - 30000 2 1 0.005 3000 1 +#generate_sphere_d 3 - - 30000 3 2 0.005 3000 1 +#generate_sphere_d 3 - - 30000 4 3 0.05 3000 1 +#generate_plane - - - 30000 3 2 0.005 3000 1 +#generate_moment_curve 0 1 - 30000 6 1 0.005 3000 1 +#generate_klein_bottle_4D 4 3 - 10000 4 2 1.5 3000 1 +#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 3000 1 + +#----------------------------------------------------------- Performance testing ------------------------------------------------------------------------- +# TC: 5.55 / 1st fix step : 2.7 +data/fertility.txt - - - 0 3 2 0.1 600 1 \ No newline at end of file From 4035a51cf2a96d1e501afd1df863388246ca0cfb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 11:55:25 +0100 Subject: [PATCH 133/269] Temporary debug code --- Triangulation/include/CGAL/Triangulation_data_structure.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 94818cc4627..ef10428a5c3 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -664,6 +664,9 @@ Triangulation_data_structure { // 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); From d810bd58ee75ac42780dca6f0905d3571c032b47 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 15:56:43 +0100 Subject: [PATCH 134/269] Update number_of_inconsistent_simplices to use cache "m_stars" --- .../include/CGAL/Tangential_complex.h | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 55fb8e26167..f2b2c2dbfb8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -457,7 +457,7 @@ public: << " - Num inconsistent simplices in stars (incl. duplicates): " << stats_after.second << std::endl << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_before.first << "%" + << 100. * stats_after.second / stats_after.first << "%" << std::endl << "==========================================================" << std::endl; @@ -516,27 +516,26 @@ public: typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for ( ; it_tr != it_tr_end ; ++it_tr) + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - // CJTODO: use m_stars[...] - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - typename std::vector::const_iterator it_c = - incident_cells.begin(); - typename std::vector::const_iterator it_c_end = - incident_cells.end(); // For each cell - for ( ; it_c != it_c_end ; ++it_c) + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - if (tr.is_infinite(*it_c)) // Don't check infinite cells + // Don't export infinite cells + if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; + + std::set c = *it_inc_simplex; + c.insert(idx); // Add the missing index - if (!is_simplex_consistent(*it_c, tr.current_dimension())) + if (!is_simplex_consistent(c)) ++num_inconsistent_simplices; + ++num_simplices; } } From ed7fb72f117c310720c9f1dc5cd6017bbd8cca8e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 16:00:06 +0100 Subject: [PATCH 135/269] Added "unproject_point" + fixed export_simplices_to_off (multiple dimensions) --- .../include/CGAL/Tangential_complex.h | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f2b2c2dbfb8..28b35aef12f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1003,14 +1003,14 @@ private: for ( ; it_c != it_c_end ; ++it_c) { // Will contain all indices except center_vertex - Incident_simplex inc_simplex; + Incident_simplex incident_simplex; for (int j = 0 ; j < cur_dim_plus_1 ; ++j) { std::size_t index = (*it_c)->vertex(j)->data(); if (index != i) - inc_simplex.insert(index); + incident_simplex.insert(index); } - star.push_back(inc_simplex); + star.push_back(incident_simplex); } // CJTODO DEBUG @@ -1142,6 +1142,28 @@ private: */ } + Point unproject_point(const Tr_point &p, const Point &origin, + const Tangent_space_basis &tsb, + const Tr_traits &tr_traits) + { + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + tr_traits.compute_coordinate_d_object(); + + Point global_point = origin; + for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + { + global_point = k_transl( + global_point, + k_scaled_vec(tsb[i], coord(p, i))); + } + + return global_point; + } + // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p Tr_bare_point project_point(const Point &p, const Point &origin, @@ -1362,13 +1384,13 @@ private: Star::const_iterator it_inc_simplex_end = star.end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - const Incident_simplex &inc_simplex = *it_inc_simplex; + const Incident_simplex &incident_simplex = *it_inc_simplex; // Don't check infinite cells - if (*inc_simplex.rbegin() == std::numeric_limits::max()) + if (*incident_simplex.rbegin() == std::numeric_limits::max()) continue; - std::set c = inc_simplex; + std::set c = incident_simplex; c.insert(tr_index); // Add the missing index //***************************************************************************** @@ -1617,8 +1639,6 @@ private: // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) int factor = (m_intrinsic_dimension == 1 ? 2 : 1); - int OFF_simplices_dim = - (m_intrinsic_dimension == 1 ? 3 : m_intrinsic_dimension + 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; std::size_t num_inconsistent_stars = 0; @@ -1651,6 +1671,7 @@ private: std::set c = *it_inc_simplex; c.insert(idx); + std::size_t num_vertices = c.size(); if (color_inconsistencies || excluded_simplices) { @@ -1670,7 +1691,10 @@ private: // See export_vertices_to_off if (m_intrinsic_dimension == 1) + { sstr_c << (data*factor + 1) << " "; + ++num_vertices; + } // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex @@ -1683,7 +1707,7 @@ private: if (!excluded) { - os << OFF_simplices_dim << " " << sstr_c.str() << " "; + os << num_vertices << " " << sstr_c.str() << " "; if (color_inconsistencies && is_simpl_consistent) os << color.str(); else @@ -1695,7 +1719,7 @@ private: } else if (show_excluded_vertices_in_color) { - os << OFF_simplices_dim << " " + os << num_vertices << " " << sstr_c.str() << " " << "0 0 255"; ++num_simplices; @@ -1703,7 +1727,6 @@ private: } else { - os << OFF_simplices_dim << " "; std::size_t min_index = std::numeric_limits::max(); std::size_t data; std::stringstream sstr_c; @@ -1722,9 +1745,12 @@ private: // See export_vertices_to_off if (m_intrinsic_dimension == 1) + { sstr_c << (data*factor + 1) << " "; + ++num_vertices; + } - os << sstr_c.str(); + os << num_vertices << " " << sstr_c.str(); ++num_simplices; } From 7d928b4489782a2f305076a080c222631f00dbf8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Feb 2015 16:17:46 +0100 Subject: [PATCH 136/269] Re-added the ability to perturb the k + 1 + m closest points --- .../include/CGAL/Tangential_complex.h | 95 +++++++++---------- .../include/CGAL/Tangential_complex/config.h | 8 +- 2 files changed, 50 insertions(+), 53 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 28b35aef12f..fc20415870f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1475,39 +1475,12 @@ private: break; } -//***************************************************************************** -// STRATEGY 4: perturb one random point of the simplex -//***************************************************************************** -#else - // Inconsistent? - if (!is_simplex_consistent(c)) - { - is_inconsistent = true; - int rnd = m_random_generator.get_int(0, static_cast(c.size())); - if (rnd == 0) - perturb(tr_index); - else - { - std::set::const_iterator it_idx = c.begin(); - std::advance(it_idx, rnd - 1); - perturb(*it_idx); - } - -# if !defined(CGAL_TC_GLOBAL_REFRESH) - refresh_tangential_complex(); -# endif - - // We will try the other cells next time - break; - } - -#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY - //***************************************************************************** // STRATEGY 4: perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS // closest points (to the power center of first the inconsistent cell) //***************************************************************************** -/*#else +#elif defined(CGAL_TC_PERTURB_N_CLOSEST_POINTS) + // Inconsistent? if (!is_simplex_consistent(c)) { @@ -1517,35 +1490,36 @@ private: // closest points std::vector simplex_pts; + simplex_pts.reserve(c.size()); Incident_simplex::const_iterator it_point_idx = c.begin(); Incident_simplex::const_iterator it_point_idx_end = c.end(); - // For each point p of the simplex, we parse the incidents cells of p - // and we check if "simplex" is among them + // For each point p of the simplex, we reproject it onto the tangent + // space. Could be optimized since it's already been computed before. for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) - simplex_pts.push_back(m_points[*it_point_idx]); + { +#ifdef CGAL_TC_PERTURB_WEIGHT + FT w = m_weights[*it_point_idx]; +#else + FT w = 0; +#endif + simplex_pts.push_back(project_point_and_compute_weight( + m_points[*it_point_idx], w, + m_points[tr_index], m_tangent_spaces[tr_index], + local_tr_traits)); + } //typename Tr_traits::Power_center_d power_center = // local_tr_traits.power_center_d_object(); // CJTODO typename Get_functor::type power_center(local_tr_traits); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); - - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = - m_k.scaled_vector_d_object(); - - Tr_point local_center = power_center(simplex_pts.begin(), simplex_pts.end()); - Point global_center = m_points[tr_index]; - const Tangent_space_basis &tsb = m_tangent_spaces[tr_index]; - for (int i = 0 ; i < m_intrinsic_dimension ; ++i) - { - global_center = k_transl( - global_center, - k_scaled_vec(tsb[i], coord(local_center, i))); - } + Point global_center = unproject_point( + power_center(simplex_pts.begin(), simplex_pts.end()), + m_points[tr_index], + m_tangent_spaces[tr_index], + local_tr_traits); KNS_range kns_range = m_points_ds.query_ANN( global_center, @@ -1572,8 +1546,33 @@ private: // We will try the other cells next time break; } +//***************************************************************************** +// STRATEGY 5: perturb one random point of the simplex +//***************************************************************************** +#else + // Inconsistent? + if (!is_simplex_consistent(c)) + { + is_inconsistent = true; + int rnd = m_random_generator.get_int(0, static_cast(c.size())); + if (rnd == 0) + perturb(tr_index); + else + { + std::set::const_iterator it_idx = c.begin(); + std::advance(it_idx, rnd - 1); + perturb(*it_idx); + } -#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY*/ +# if !defined(CGAL_TC_GLOBAL_REFRESH) + refresh_tangential_complex(); +# endif + + // We will try the other cells next time + break; + } + +#endif // CGAL_TC_PERTURB_THE_SIMPLEX_ONLY } return is_inconsistent; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index a5ed583a95d..f9339340dbe 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -41,15 +41,13 @@ //#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 k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS closest points // Otherwise, perturb one random point of the simplex - -/* -// Otherwise, perturb the k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS -// closest points +// 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) -*/ + //========================= Strategy ========================================== //#define CGAL_TC_USE_NANOFLANN From e5b56dc50447cb62a84ccdb9dc5bda4661727c53 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 12 Feb 2015 00:09:55 +0100 Subject: [PATCH 137/269] Added a new way to fix inconsistencies + simpler export_simplices_to_off Remaining inconsistencies are fixed by adding higher-dim simplices. Future work: collapse them. --- .../Tangential_complex/benchmark_tc.cpp | 7 +- .../include/CGAL/Tangential_complex.h | 400 ++++++++++++++---- .../test_tangential_complex.cpp | 7 +- 3 files changed, 322 insertions(+), 92 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index a1877f69dd5..ed55aa637db 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -180,8 +180,7 @@ void make_tc(std::vector &points, int intrinsic_dim, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - std::set > incorrect_simplices; - //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); double export_before_time = -1.; if (intrinsic_dim <= 3) @@ -191,7 +190,7 @@ void make_tc(std::vector &points, int intrinsic_dim, output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_BEFORE_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); + tc.export_to_off(off_stream, true); export_before_time = t.elapsed(); t.reset(); } @@ -222,7 +221,7 @@ void make_tc(std::vector &points, int intrinsic_dim, output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim << "_in_R" << ambient_dim << "_AFTER_FIX.off"; std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true, &incorrect_simplices, true); + tc.export_to_off(off_stream, true); export_after_time = t.elapsed(); t.reset(); } /*else diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fc20415870f..52592f7a0bc 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -489,11 +489,13 @@ public: ++num_steps; done = (num_inconsistent_local_tr == 0); - if (time_limit != 0 && t.elapsed() > time_limit) + if (!done && time_limit != 0 && t.elapsed() > time_limit) { #ifdef CGAL_TC_VERBOSE std::cerr << "Time limit reached." << std::endl; #endif + check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); // CJTODO: make it optional? + return TIME_LIMIT_REACHED; } } @@ -561,10 +563,7 @@ public: } std::ostream &export_to_off( - std::ostream & os, - bool color_inconsistencies = false, - std::set > const* excluded_simplices = NULL, - bool show_excluded_vertices_in_color = false) + std::ostream & os, bool color_inconsistencies = false) { if (m_points.empty()) return os; @@ -600,8 +599,7 @@ public: std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); export_simplices_to_off( - output, num_simplices, color_inconsistencies, - excluded_simplices, show_excluded_vertices_in_color); + output, num_simplices, color_inconsistencies); #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; @@ -1629,15 +1627,245 @@ private: return os; } + void insert_higher_dim_simplex_into_star( + std::size_t index, + const std::set &simplex) + { + Incident_simplex incident_simplex = simplex; + incident_simplex.erase(index); // Remove the center index + + Star &star = m_stars[index]; + + std::set::const_iterator it_point_idx = simplex.begin(); + std::set::const_iterator it_point_idx_end = simplex.end(); + for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) + { + // Skip center index + if (*it_point_idx == index) + continue; + + // Temporarily remove this index + incident_simplex.erase(*it_point_idx); + // Erase incident_simplex from star + star.erase(std::remove(star.begin(), star.end(), incident_simplex), + star.end()); + incident_simplex.insert(*it_point_idx); + } + + star.push_back(incident_simplex); + } + + // Solves one inconsistency + // "inconsistent_simplex" must contain p_idx and q_idx + void solve_inconsistency_by_adding_higher_dimensional_simplices( + std::size_t p_idx, std::size_t q_idx, + const std::set &inconsistent_simplex) + { + typename Kernel::Translated_point_d k_transl = + m_k.translated_point_d_object(); + + const Tr_traits &q_tr_traits = m_triangulations[q_idx].tr().geom_traits(); + /*typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object();*/ // CJTODO + typename Get_functor::type tr_power_center(q_tr_traits); + typename Tr_traits::Point_weight_d tr_point_weight = + q_tr_traits.point_weight_d_object(); + + //------------------------------------------------------------------------- + //1. Compute power_center(p'q'r') in Tp => cp + //------------------------------------------------------------------------- + // CJTODO + + //------------------------------------------------------------------------- + //2. Compute power_center(inconsistent_simplex projected in Tq) + // => gives Cq and radius Rq + // Rq is also the radius of the ambient sphere S whose center is Cq and + // which goes through all the ambient points of "inconsistent_simplex" + //------------------------------------------------------------------------- + std::vector simplex_pts_in_Tq; + simplex_pts_in_Tq.reserve(inconsistent_simplex.size()); + +#ifdef CGAL_TC_PERTURB_POSITION + const Point center_pt = k_transl(m_points[q_idx], m_translations[q_idx]); +#else + const Point ¢er_pt = m_points[q_idx]; +#endif + + std::set::const_iterator it_point_idx = + inconsistent_simplex.begin(); + std::set::const_iterator it_point_idx_end = + inconsistent_simplex.end(); + // For each point p of the simplex, we reproject it onto the tangent + // space. Could be optimized since it's already been computed before. + for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) + { +#ifdef CGAL_TC_PERTURB_POSITION + const Point p = k_transl( + m_points[*it_point_idx], m_translations[*it_point_idx]); +#else + const Point &p = m_points[*it_point_idx]; +#endif +#ifdef CGAL_TC_PERTURB_WEIGHT + FT w = m_weights[*it_point_idx]; +#else + FT w = 0; +#endif + simplex_pts_in_Tq.push_back(project_point_and_compute_weight( + p, w, center_pt, m_tangent_spaces[q_idx], q_tr_traits)); + } + + Tr_point Cq = tr_power_center( + simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); + + //------------------------------------------------------------------------- + //3. Find points t1, t2... (in ambient space) which are inside S + //------------------------------------------------------------------------- + + // CJTODO: on prend le point le plus proche pour l'instant, mais il + // faudra changer ça (cf 4 5 6, ci dessous) + Point global_Cq = unproject_point(Cq, center_pt, + m_tangent_spaces[q_idx], q_tr_traits); + std::size_t inside_point_idx; + INS_range ins_range = m_points_ds.query_incremental_ANN(global_Cq); + 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 (inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) + { + inside_point_idx = neighbor_point_idx; + break; + } + } + + //std::size_t inside_point_idx = kns_range.begin()->first; + + //------------------------------------------------------------------------- + //4. S'il n'y a qu'un seul points ti, passer ŕ la derničre étape + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + //5. Pour chaque ti, calculer la sphčre qui passe par p, q, r, ti dont le centre est sur la droite (cq, cq) + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + //6. Conserver le point ti tel que dist(cp, ci) soit la plus petite + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + //7. Créer un k+1-simplex (inconsistent_simplex, ti) + //------------------------------------------------------------------------- + std::set new_simplex = inconsistent_simplex; + new_simplex.insert(inside_point_idx); + + it_point_idx = new_simplex.begin(); + it_point_idx_end = new_simplex.end(); + for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) + { + insert_higher_dim_simplex_into_star(*it_point_idx, new_simplex); + } + // CJTODO: call + // check_and_solve_inconsistencies_by_adding_higher_dim_simplices + // recursively? Not sure, since the star will be parsed again from + // the beginning + } + + // Test and solve inconsistencies of a simplex. + // Returns true if some inconsistencies were found. + bool check_and_solve_inconsistencies_by_adding_higher_dim_simplices( + std::size_t tr_index, const std::set &incident_simplex) + { + bool inconsistencies_found = false; + + std::set simplex = incident_simplex; + simplex.insert(tr_index); + + // Check if the simplex is in the stars of all its vertices + std::set::const_iterator it_point_idx = simplex.begin(); + // For each point p of the simplex, we parse the incidents cells of p + // and we check if "simplex" is among them + for ( ; it_point_idx != simplex.end() ; ++it_point_idx) + { + std::size_t point_idx = *it_point_idx; + // Don't check infinite simplices + if (point_idx == std::numeric_limits::max()) + continue; + + Star const& star = m_stars[point_idx]; + + // What we're looking for is "simplex" \ point_idx + Incident_simplex ic_to_find = simplex; + ic_to_find.erase(point_idx); + + // For each cell + bool found = false; + Star::const_iterator it_inc_simplex = star.begin(); + Star::const_iterator it_inc_simplex_end = star.end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + if (*it_inc_simplex == ic_to_find) + { + found = true; + break; + } + } + + if (!found) + { + solve_inconsistency_by_adding_higher_dimensional_simplices( + tr_index, *it_point_idx, simplex); + inconsistencies_found = true; + break; + } + } + + return inconsistencies_found; + } + + void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() + { + for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) + { + bool inconsistencies_found; + do + { + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + inconsistencies_found = + check_and_solve_inconsistencies_by_adding_higher_dim_simplices( + idx, *it_inc_simplex); + + // m_stars[idx] has been modified, let's start again + // CJTODO: optimize? + if (inconsistencies_found) + break; + } + } while (inconsistencies_found); + } + + // CJTODO TEMP + std::pair stats_after = + number_of_inconsistent_simplices(false); + std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_after.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_after.first << "%" + << std::endl; + } + std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_simplices, - bool color_inconsistencies = false, - std::set > const* excluded_simplices = NULL, - bool show_excluded_vertices_in_color = false) + bool color_inconsistencies = false) { // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) - int factor = (m_intrinsic_dimension == 1 ? 2 : 1); num_simplices = 0; std::size_t num_inconsistent_simplices = 0; std::size_t num_inconsistent_stars = 0; @@ -1659,100 +1887,104 @@ private: //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; color << 128 << " " << 128 << " " << 128; - // For each cell + // Gather the triangles here, with a bool saying if it's consistent + typedef std::vector, bool> > + Star_using_triangles; + Star_using_triangles star_using_triangles; + + // For each cell of the star Star::const_iterator it_inc_simplex = m_stars[idx].begin(); Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - // Don't export infinite cells - if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) - continue; - std::set c = *it_inc_simplex; c.insert(idx); std::size_t num_vertices = c.size(); - if (color_inconsistencies || excluded_simplices) + bool is_simpl_consistent = true; + if (color_inconsistencies) { - std::stringstream sstr_c; - std::size_t data; - - std::set::const_iterator it_point_idx = c.begin(); - for ( ; it_point_idx != c.end() ; ++it_point_idx) - { - data = *it_point_idx; - sstr_c << data*factor << " "; - } - - bool is_simpl_consistent = is_simplex_consistent(c); + is_simpl_consistent = is_simplex_consistent(c); if (!is_simpl_consistent) is_star_inconsistent = true; + } - // See export_vertices_to_off - if (m_intrinsic_dimension == 1) - { - sstr_c << (data*factor + 1) << " "; - ++num_vertices; - } + // If only 2 vertices, add a third one (each vertex is duplicated in + // the file when m_intrinsic dim = 2) + if (num_vertices == 2) + { + std::set tmp_c; + std::set::iterator it = c.begin(); + for ( ; it != c.end() ; ++it) + tmp_c.insert(*it * 2); + tmp_c.insert(*c.rbegin() + 1); + c = tmp_c; + } - // In order to have only one time each simplex, we only keep it - // if the lowest index is the index of the center vertex - if (*c.begin() != idx && is_simpl_consistent) - continue; - - bool excluded = - (excluded_simplices - && excluded_simplices->find(c) != excluded_simplices->end()); - - if (!excluded) - { - os << num_vertices << " " << sstr_c.str() << " "; - if (color_inconsistencies && is_simpl_consistent) - os << color.str(); - else - { - os << "255 0 0"; - ++num_inconsistent_simplices; - } - ++num_simplices; - } - else if (show_excluded_vertices_in_color) - { - os << num_vertices << " " - << sstr_c.str() << " " - << "0 0 255"; - ++num_simplices; - } + if (num_vertices <= 3) + { + star_using_triangles.push_back(std::make_pair(c, is_simpl_consistent)); } else { - std::size_t min_index = std::numeric_limits::max(); - std::size_t data; - std::stringstream sstr_c; - std::set::const_iterator it_point_idx = c.begin(); - min_index = *it_point_idx; - for ( ; it_point_idx != c.end() ; ++it_point_idx) + // num_vertices >= 4: decompose the simplex in triangles + std::vector booleans(num_vertices, false); + std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); + do { - data = *it_point_idx; - sstr_c << data*factor << " "; - } - - // In order to have only one time each simplex, we only keep it - // if the lowest index is the index of the center vertex - if (min_index != idx) - continue; + std::set triangle; + std::set::iterator it = c.begin(); + for (int i = 0; it != c.end() ; ++i, ++it) + { + if (booleans[i]) + triangle.insert(*it); + } + star_using_triangles.push_back( + std::make_pair(triangle, is_simpl_consistent)); + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + } - // See export_vertices_to_off - if (m_intrinsic_dimension == 1) - { - sstr_c << (data*factor + 1) << " "; - ++num_vertices; - } + // For each cell + Star_using_triangles::const_iterator it_simplex = + star_using_triangles.begin(); + Star_using_triangles::const_iterator it_simplex_end = + star_using_triangles.end(); + for ( ; it_simplex != it_simplex_end ; ++it_simplex) + { + // Don't export infinite cells + if (*it_simplex->first.rbegin() + == std::numeric_limits::max()) + continue; + + const std::set &c = it_simplex->first; + bool is_simpl_consistent = it_simplex->second; - os << num_vertices << " " << sstr_c.str(); - ++num_simplices; + std::stringstream sstr_c; + + std::set::const_iterator it_point_idx = c.begin(); + for ( ; it_point_idx != c.end() ; ++it_point_idx) + { + sstr_c << *it_point_idx << " "; } + // In order to have only one time each simplex, we only keep it + // if the lowest index is the index of the center vertex + if (*c.begin() != idx && is_simpl_consistent) + continue; + + os << 3 << " " << sstr_c.str(); + if (color_inconsistencies) + { + if (is_simpl_consistent) + os << " " << color.str(); + else + { + os << " 255 0 0"; + ++num_inconsistent_simplices; + } + } + ++num_simplices; os << std::endl; } if (is_star_inconsistent) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 69f6f54f02e..cc9536db937 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -100,8 +100,7 @@ int main() tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - std::set > incorrect_simplices; - //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + tc.check_if_all_simplices_are_in_the_ambient_delaunay(); double export_before_time = -1.; if (INTRINSIC_DIMENSION <= 3) @@ -111,7 +110,7 @@ int main() 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, &incorrect_simplices, true); + tc.export_to_off(off_stream, true); export_before_time = t.elapsed(); t.reset(); } @@ -134,7 +133,7 @@ int main() 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, &incorrect_simplices, true); + tc.export_to_off(off_stream, true); export_after_time = t.elapsed(); t.reset(); } /*else From 0029c57ab11151dee761d9afbfbf5f5c72414320 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 16 Feb 2015 18:39:09 +0100 Subject: [PATCH 138/269] Partially parallelized fix_inconsistencies Does not work for position perturbation for now. --- .../include/CGAL/Tangential_complex.h | 44 +++++++--- .../CGAL/Tangential_complex/utilities.h | 83 +++++++++++++++++++ 2 files changed, 116 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 52592f7a0bc..d2255884bd4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -56,9 +56,11 @@ #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB # include +# include //# include #endif @@ -123,6 +125,17 @@ class Tangential_complex typedef std::vector Points; typedef std::vector Weights; +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH)\ + && !defined(CGAL_TC_PERTURB_POSITION) // CJTODO TEMP + // C++11 + typedef Atomic_wrapper Translation_for_perturb; + typedef std::vector > Weights_for_perturb; +#else + typedef Vector Translation_for_perturb; + typedef std::vector Weights_for_perturb; +#endif + typedef std::vector Translations_for_perturb; + typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; @@ -398,18 +411,23 @@ public: { std::size_t num_inconsistent_local_tr = 0; // CJTODO: the parallel version is not working for now -/*#ifdef CGAL_LINKED_WITH_TBB +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) \ + && !defined(CGAL_TC_PERTURB_POSITION) // CJTODO TEMP // Parallel if (boost::is_convertible::value) { + tbb::combinable num_inconsistencies; tbb::parallel_for( tbb::blocked_range(0, m_triangulations.size()), - Try_to_solve_inconsistencies_in_a_local_triangulation(*this) + Try_to_solve_inconsistencies_in_a_local_triangulation( + *this, num_inconsistencies) ); + num_inconsistent_local_tr = + num_inconsistencies.combine(std::plus()); } // Sequential else -#endif // CGAL_LINKED_WITH_TBB*/ +#endif // CGAL_LINKED_WITH_TBB { #ifdef CGAL_TC_PROFILING Wall_clock_timer t; @@ -1286,25 +1304,29 @@ private: class Try_to_solve_inconsistencies_in_a_local_triangulation { Tangential_complex & m_tc; + tbb::combinable &m_num_inconsistencies; public: // Constructor Try_to_solve_inconsistencies_in_a_local_triangulation( - Tangential_complex &tc) - : m_tc(tc) + Tangential_complex &tc, tbb::combinable &num_inconsistencies) + : m_tc(tc), m_num_inconsistencies(num_inconsistencies) {} // Constructor Try_to_solve_inconsistencies_in_a_local_triangulation( const Compute_tangent_triangulation &ctt) - : m_tc(ctt.m_tc) + : m_tc(ctt.m_tc), m_num_inconsistencies(ctt.m_num_inc) {} // operator() void operator()( const tbb::blocked_range& r ) const { for( size_t i = r.begin() ; i != r.end() ; ++i) - m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(i); + { + m_num_inconsistencies.local() += + m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(i); + } } }; #endif // CGAL_LINKED_WITH_TBB @@ -1348,7 +1370,7 @@ private: Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( *tr_point_on_sphere_generator++, 0); - Vector &global_transl = m_translations[point_idx]; + Translation_for_perturb &global_transl = m_translations[point_idx]; global_transl = k_constr_vec(m_ambiant_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) @@ -2024,13 +2046,13 @@ private: Points m_points; #ifdef CGAL_TC_PERTURB_WEIGHT - Weights m_weights; + Weights_for_perturb m_weights; #endif #ifdef CGAL_TC_PERTURB_POSITION - Vectors m_translations; + Translations_for_perturb m_translations; #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE - std::vector m_perturb_tangent_space; + std::vector > m_perturb_tangent_space; #endif Points_ds m_points_ds; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index fa55b4f332c..6e7e3e6faff 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -25,10 +25,93 @@ #include #include +#include // C++11 namespace CGAL { namespace Tangential_complex_ { + // Provides copy constructors to std::atomic so that + // it can be used in a vector + template + struct Atomic_wrapper + : public std::atomic + { + typedef std::atomic Base; + + Atomic_wrapper() {} + Atomic_wrapper(const T &t) : Base(t) {} + Atomic_wrapper(const std::atomic &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 &other) + { + Base::store(other.load()); + return *this; + } + Atomic_wrapper &operator=(const Atomic_wrapper &other) + { + Base::store(other.load()); + return *this; + } + }; + + /*template + struct Atomic_wrapper + { + std::atomic _a; + + Atomic_wrapper() + :_a() + {} + + Atomic_wrapper(const std::atomic &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 &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() const + { + return _a; + } + };*/ + + template std::vector compute_gram_schmidt_basis( From c4bf91668663fda47d2069eb788792746e9cf7bb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Feb 2015 08:37:41 +0100 Subject: [PATCH 139/269] Position perturbation is now parallel And it's almost 10x faster on 10 cores --- .../include/CGAL/Tangential_complex.h | 82 ++++++++++++++----- .../CGAL/Tangential_complex/utilities.h | 3 +- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d2255884bd4..52dff2888c4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -61,7 +61,7 @@ #ifdef CGAL_LINKED_WITH_TBB # include # include -//# include +# include #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) @@ -125,10 +125,9 @@ class Tangential_complex typedef std::vector Points; typedef std::vector Weights; -#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH)\ - && !defined(CGAL_TC_PERTURB_POSITION) // CJTODO TEMP - // C++11 - typedef Atomic_wrapper Translation_for_perturb; +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + typedef tbb::mutex Mutex_for_perturb; + typedef Vector Translation_for_perturb; typedef std::vector > Weights_for_perturb; #else typedef Vector Translation_for_perturb; @@ -218,6 +217,9 @@ public: m_ambiant_dim(k.point_dimension_d_object()(*first)), m_points(first, last), m_points_ds(m_points) +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + , m_p_perturb_mutexes(NULL) +# endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) @@ -225,7 +227,12 @@ public: {} /// Destructor - ~Tangential_complex() {} + ~Tangential_complex() + { +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + delete [] m_p_perturb_mutexes; +#endif + } std::size_t number_of_vertices() { @@ -253,6 +260,10 @@ public: #ifdef CGAL_TC_PERTURB_POSITION m_translations.resize(m_points.size(), m_k.construct_vector_d_object()(m_ambiant_dim)); +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + delete [] m_p_perturb_mutexes; + m_p_perturb_mutexes = new Mutex_for_perturb[m_points.size()]; +# endif #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE m_perturb_tangent_space.resize(m_points.size(), false); @@ -410,10 +421,13 @@ public: while (!done) { std::size_t num_inconsistent_local_tr = 0; -// CJTODO: the parallel version is not working for now -#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) \ - && !defined(CGAL_TC_PERTURB_POSITION) // CJTODO TEMP + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_fix_step; +#endif + // Parallel +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) if (boost::is_convertible::value) { tbb::combinable num_inconsistencies; @@ -429,20 +443,18 @@ public: else #endif // CGAL_LINKED_WITH_TBB { -#ifdef CGAL_TC_PROFILING - Wall_clock_timer t; -#endif for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) { num_inconsistent_local_tr += (try_to_solve_inconsistencies_in_a_local_triangulation(i) ? 1 : 0); } -#ifdef CGAL_TC_PROFILING - std::cerr << "Attempt to fix inconsistencies: " << t.elapsed() - << " seconds." << std::endl; -#endif } +#ifdef CGAL_TC_PROFILING + std::cerr << "Attempt to fix inconsistencies: " << t_fix_step.elapsed() + << " seconds." << std::endl; +#endif + #ifdef CGAL_TC_GLOBAL_REFRESH refresh_tangential_complex(); #endif @@ -864,6 +876,8 @@ private: typename Get_functor::type power_center(local_tr_traits); #ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions const Point center_pt = k_transl(m_points[i], m_translations[i]); #else const Point ¢er_pt = m_points[i]; @@ -928,6 +942,8 @@ private: if (neighbor_point_idx != i) { #ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions const Point neighbor_pt = k_transl( m_points[neighbor_point_idx], m_translations[neighbor_point_idx]); #else @@ -1349,9 +1365,19 @@ private: m_k.point_to_vector_d_object(); CGAL::Random_points_on_sphere_d tr_point_on_sphere_generator(m_ambiant_dim, 1); - + // Parallel +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + Vector transl = k_scaled_vec(k_pt_to_vec( + *tr_point_on_sphere_generator++), m_half_sparsity); + m_p_perturb_mutexes[point_idx].lock(); + m_translations[point_idx] = transl; + m_p_perturb_mutexes[point_idx].unlock(); + // Sequential +# else m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( *tr_point_on_sphere_generator++), m_half_sparsity); +# endif + # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL const Tr_traits &local_tr_traits = m_triangulations[point_idx].tr().geom_traits(); @@ -1370,8 +1396,7 @@ private: Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( *tr_point_on_sphere_generator++, 0); - Translation_for_perturb &global_transl = m_translations[point_idx]; - global_transl = k_constr_vec(m_ambiant_dim); + Translation_for_perturb global_transl = k_constr_vec(m_ambiant_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { @@ -1380,7 +1405,17 @@ private: k_scaled_vec(tsb[i], m_half_sparsity*coord(local_random_transl, i)) ); } -# endif + // Parallel +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + m_p_perturb_mutexes[point_idx].lock(); + m_translations[point_idx] = global_transl; + m_p_perturb_mutexes[point_idx].unlock(); + // Sequential +# else + m_translations[point_idx] = global_transl; +# endif + +# endif // CGAL_TC_PERTURB_POSITION_TANGENTIAL #endif // CGAL_TC_PERTURB_POSITION } @@ -1708,6 +1743,8 @@ private: simplex_pts_in_Tq.reserve(inconsistent_simplex.size()); #ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions const Point center_pt = k_transl(m_points[q_idx], m_translations[q_idx]); #else const Point ¢er_pt = m_points[q_idx]; @@ -1722,6 +1759,8 @@ private: for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { #ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions const Point p = k_transl( m_points[*it_point_idx], m_translations[*it_point_idx]); #else @@ -2050,6 +2089,9 @@ private: #endif #ifdef CGAL_TC_PERTURB_POSITION Translations_for_perturb m_translations; +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + Mutex_for_perturb *m_p_perturb_mutexes; +# endif #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE std::vector > m_perturb_tangent_space; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 6e7e3e6faff..bf3e70cb7c1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -25,7 +25,8 @@ #include #include -#include // C++11 +#include // 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_ { From 5db662c0c2838bfc2a83ed9828c5e7e7dc6493cb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 17 Feb 2015 10:53:58 +0100 Subject: [PATCH 140/269] Fix order of initialization --- Tangential_complex/include/CGAL/Tangential_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 52dff2888c4..334e5d1a91f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -215,11 +215,11 @@ public: m_half_sparsity(0.5*sparsity), m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), m_ambiant_dim(k.point_dimension_d_object()(*first)), - m_points(first, last), - m_points_ds(m_points) + m_points(first, last) # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) # endif + , m_points_ds(m_points) #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) From f5c1e2a7e04f7c42b01556f1009d107ce18e1078 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Feb 2015 18:06:07 +0100 Subject: [PATCH 141/269] First try with complex collapsing --- .../include/CGAL/Tangential_complex.h | 158 +++++++++++++++- .../Tangential_complex/Simplicial_complex.h | 172 ++++++++++++++++++ .../CGAL/Tangential_complex/utilities.h | 24 +++ 3 files changed, 349 insertions(+), 5 deletions(-) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 334e5d1a91f..82006ec1156 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -23,6 +23,9 @@ #define TANGENTIAL_COMPLEX_H #include +#include +#include +#include #include #include @@ -32,8 +35,6 @@ #include #include #include -#include -#include #include #include @@ -57,6 +58,7 @@ #include #include #include +#include #ifdef CGAL_LINKED_WITH_TBB # include @@ -525,6 +527,13 @@ public: std::cerr << "Time limit reached." << std::endl; #endif check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); // CJTODO: make it optional? + Simplicial_complex complex; // CJTODO: don't do it here + int max_dim = export_TC(complex); + complex.collapse(max_dim); + complex.display_stats(); + + std::ofstream off_stream("output/test.off"); // CJTODO TEMP TEST + export_to_off(complex, off_stream); return TIME_LIMIT_REACHED; } @@ -592,8 +601,43 @@ public: return std::make_pair(num_simplices, num_inconsistent_simplices); } + // Return the max dimension of the simplices + int export_TC(Simplicial_complex &complex) + { + int max_dim = -1; + + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + { + Triangulation const& tr = it_tr->tr(); + + // For each cell of the star + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + std::set c = *it_inc_simplex; + if (static_cast(c.size()) > max_dim) + max_dim = static_cast(c.size()); + // Add the missing center vertex + c.insert(idx); + complex.add_simplex(c); + } + } + return max_dim; + } + std::ostream &export_to_off( - std::ostream & os, bool color_inconsistencies = false) + const Simplicial_complex &complex, std::ostream & os) + { + return export_to_off(os, false, &complex); + } + + std::ostream &export_to_off( + std::ostream & os, bool color_inconsistencies = false, + const Simplicial_complex *p_complex = NULL) { if (m_points.empty()) return os; @@ -628,8 +672,12 @@ public: std::stringstream output; std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); - export_simplices_to_off( - output, num_simplices, color_inconsistencies); + if (p_complex) + export_simplices_to_off( + *p_complex, output, num_simplices, color_inconsistencies); + else + export_simplices_to_off( + output, num_simplices, color_inconsistencies); #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; @@ -2076,6 +2124,106 @@ private: return os; } + + std::ostream &export_simplices_to_off( + const Simplicial_complex &complex, + std::ostream & os, std::size_t &num_simplices, + bool color_inconsistencies = false) + { + typedef Simplicial_complex::Simplex Simplex; + typedef Simplicial_complex::Simplex_range Simplex_range; + + // If m_intrinsic_dimension = 1, each point is output two times + // (see export_vertices_to_off) + num_simplices = 0; + typename Simplex_range::const_iterator it_s = + complex.simplex_range().begin(); + typename Simplex_range::const_iterator it_s_end = + complex.simplex_range().end(); + // For each triangulation + for ( ; it_s != it_s_end ; ++it_s) + { + Simplex c = *it_s; + + // Gather the triangles here, with a bool saying if it's consistent + typedef std::vector Triangles; + Triangles triangles; + + std::size_t num_vertices = c.size(); + // Do not export smaller dimension simplices + if (num_vertices < m_intrinsic_dimension + 1) + continue; + + // If only 2 vertices, add a third one (each vertex is duplicated in + // the file when m_intrinsic dim = 2) + if (num_vertices == 2) + { + std::set tmp_c; + std::set::iterator it = c.begin(); + for ( ; it != c.end() ; ++it) + tmp_c.insert(*it * 2); + tmp_c.insert(*c.rbegin() + 1); + c = tmp_c; + } + + if (num_vertices <= 3) + { + triangles.push_back(c); + } + else + { + // num_vertices >= 4: decompose the simplex in triangles + std::vector booleans(num_vertices, false); + std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); + do + { + std::set triangle; + std::set::iterator it = c.begin(); + for (int i = 0; it != c.end() ; ++i, ++it) + { + if (booleans[i]) + triangle.insert(*it); + } + triangles.push_back(triangle); + } + while (std::next_permutation(booleans.begin(), booleans.end())); + } + + // For each cell + Triangles::const_iterator it_tri = triangles.begin(); + Triangles::const_iterator it_tri_end = triangles.end(); + for ( ; it_tri != it_tri_end ; ++it_tri) + { + // Don't export infinite cells + if (*it_tri->rbegin() == std::numeric_limits::max()) + continue; + + os << 3 << " "; + std::set::const_iterator it_point_idx = it_tri->begin(); + for ( ; it_point_idx != it_tri->end() ; ++it_point_idx) + { + os << *it_point_idx << " "; + } + + ++num_simplices; + os << std::endl; + } + } + +#ifdef CGAL_TC_VERBOSE + std::cerr << std::endl + << "==========================================================" + << std::endl + << "Export to OFF:\n" + << " * Number of vertices: " << m_points.size() << std::endl + << " * Total number of simplices: " << num_simplices << std::endl + << "==========================================================" + << std::endl; +#endif + + return os; + } + private: const Kernel m_k; const int m_intrinsic_dimension; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h new file mode 100644 index 00000000000..1fbda4dd9a5 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -0,0 +1,172 @@ +// 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 +#include + +#include + +namespace CGAL { + +using namespace Tangential_complex_; + +class Simplicial_complex +{ +public: + typedef std::set Simplex; + typedef std::set Simplex_range; + + void add_simplex(const std::set &s) + { + m_complex.insert(s); + } + + const Simplex_range &simplex_range() const + { + return m_complex; + } + + void collapse(int max_simplex_dim) + { + // We note k = max_simplex_dim - 1 + int k = max_simplex_dim - 1; + + typedef Complex::iterator Simplex_iterator; + typedef std::vector Simplex_iterator_list; + typedef std::map Cofaces_map; + + // 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 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 of Cf in the map and: + // * if the list contains only Cf, clear the list (we don't remove the + // list since it was create troubles with the iterators) and add f2 + // 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 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 + { + 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); + } + } + + // Collapse the lower dimension simplices + if (k > 1) + collapse(max_simplex_dim - 1); + } + + void display_stats() const + { + std::cerr << "==========================================================\n"; + std::cerr << "Complex stats:\n"; + + if (m_complex.empty()) + { + std::cerr << "No simplices.\n"; + } + else + { + // Number of simplex for each dimension + std::map simplex_stats; + + typedef std::set Simplex; + typedef std::set Complex; + + 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(it_simplex->size()) - 1]; + } + + for (std::map::const_iterator it_map = simplex_stats.begin() ; + it_map != simplex_stats.end() ; ++it_map) + { + std::cerr << " * " << it_map->first << "-simplices: " + << it_map->second << std::endl; + } + } + + std::cerr << "==========================================================\n"; + } + +private: + typedef Simplex_range Complex; + + Complex m_complex; + +}; // /class Simplicial_complex + +} // end namespace CGAL + +#endif // SIMPLICIAL_COMPLEX_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index bf3e70cb7c1..639ce0a8f0d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -24,6 +24,7 @@ #include #include +#include #include #include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) @@ -151,6 +152,29 @@ namespace Tangential_complex_ { return output_basis; } + + // Compute all the k-combinations of elements + // Output_iterator::value_type must be std::set > + template + void combinations(const Elements_container elements, int k, + Output_iterator combinations) + { + std::size_t n = elements.size(); + std::vector booleans(n, false); + std::fill(booleans.begin() + n - k, booleans.end(), true); + do + { + std::set combination; + 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 From 1e11e67859109d695995028a0d195ee9f2b24586 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 Feb 2015 13:49:46 +0100 Subject: [PATCH 142/269] Moved code around + updated check_if_all_simplices_are_in_the_ambient_delaunay --- .../Tangential_complex/benchmark_tc.cpp | 12 +- .../include/CGAL/Tangential_complex.h | 218 ++++++++++-------- .../Tangential_complex/Simplicial_complex.h | 56 ++++- .../CGAL/Tangential_complex/utilities.h | 1 + 4 files changed, 188 insertions(+), 99 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ed55aa637db..46e4264356b 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -205,14 +205,24 @@ void make_tc(std::vector &points, int intrinsic_dim, best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, time_limit_for_fix); double fix_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_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + TC::Simplicial_complex complex; + int max_dim = tc.export_TC(complex); + tc.check_if_all_simplices_are_in_the_ambient_delaunay(&complex); + complex.collapse(max_dim); + complex.display_stats(); + std::ofstream off_stream("output/test.off"); // CJTODO TEMP TEST + tc.export_to_off(complex, off_stream); + double export_after_time = -1.; if (intrinsic_dim <= 3) { diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 82006ec1156..2f3ac0fb9ec 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -203,6 +203,8 @@ class Tangential_complex public: + typedef Tangential_complex_::Simplicial_complex Simplicial_complex; + /// Constructor for a range of points template Tangential_complex(InputIterator first, InputIterator last, @@ -526,15 +528,6 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Time limit reached." << std::endl; #endif - check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); // CJTODO: make it optional? - Simplicial_complex complex; // CJTODO: don't do it here - int max_dim = export_TC(complex); - complex.collapse(max_dim); - complex.display_stats(); - - std::ofstream off_stream("output/test.off"); // CJTODO TEMP TEST - export_to_off(complex, off_stream); - return TIME_LIMIT_REACHED; } } @@ -628,7 +621,43 @@ public: } return max_dim; } - + + void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() + { + for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) + { + bool inconsistencies_found; + do + { + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + inconsistencies_found = + check_and_solve_inconsistencies_by_adding_higher_dim_simplices( + idx, *it_inc_simplex); + + // m_stars[idx] has been modified, let's start again + // CJTODO: optimize? + if (inconsistencies_found) + break; + } + } while (inconsistencies_found); + } + + // CJTODO TEMP + std::pair stats_after = + number_of_inconsistent_simplices(false); + std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_after.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_after.first << "%" + << std::endl; + } + std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os) { @@ -693,8 +722,13 @@ public: } bool check_if_all_simplices_are_in_the_ambient_delaunay( + const Simplicial_complex *p_complex = NULL, + bool check_for_any_dimension_simplices = true, std::set > * incorrect_simplices = NULL) { + typedef Simplicial_complex::Simplex Simplex; + typedef Simplicial_complex::Simplex_range Simplex_range; + if (m_points.empty()) return true; @@ -706,7 +740,6 @@ public: > > DT; typedef typename DT::Vertex_handle DT_VH; typedef typename DT::Finite_full_cell_const_iterator FFC_it; - typedef std::set Indexed_simplex; //------------------------------------------------------------------------- // Build the ambient Delaunay triangulation @@ -721,69 +754,89 @@ public: vh->data() = i; } - std::set amb_dt_simplices; + std::set amb_dt_simplices; for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; cit != ambient_dt.finite_full_cells_end() ; ++cit ) { - CGAL::Combination_enumerator combi( - m_intrinsic_dimension + 1, 0, ambient_dim + 1); + int lowest_dim = + (check_for_any_dimension_simplices ? 1 : m_intrinsic_dimension); + int highest_dim = + (check_for_any_dimension_simplices ? ambient_dim : m_intrinsic_dimension); - for ( ; !combi.finished() ; ++combi) + for (int dim = lowest_dim ; dim <= highest_dim ; ++dim) { - Indexed_simplex simplex; - for (int i = 0 ; i < m_intrinsic_dimension + 1 ; ++i) - simplex.insert(cit.base()->vertex(combi[i])->data()); + CGAL::Combination_enumerator combi( + dim + 1, 0, ambient_dim + 1); - amb_dt_simplices.insert(simplex); - } - } - - //------------------------------------------------------------------------- - // Parse the TC and save its simplices into "stars_simplices" - //------------------------------------------------------------------------- - - std::set stars_simplices; - - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); - // For each triangulation - for ( ; it_tr != it_tr_end ; ++it_tr) - { - Triangulation const& tr = it_tr->tr(); - Tr_vertex_handle center_vh = it_tr->center_vertex(); - - std::vector incident_cells; - tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); - - typename std::vector::const_iterator it_c = - incident_cells.begin(); - typename std::vector::const_iterator it_c_end = - incident_cells.end(); - // For each cell - for ( ; it_c != it_c_end ; ++it_c) - { - if (tr.is_infinite(*it_c)) + for ( ; !combi.finished() ; ++combi) { - std::cerr << "Warning: infinite cell in star" << std::endl; - continue; - } - Indexed_simplex simplex; - for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) - simplex.insert((*it_c)->vertex(i)->data()); + Simplex simplex; + for (int i = 0 ; i < dim + 1 ; ++i) + simplex.insert(cit.base()->vertex(combi[i])->data()); - stars_simplices.insert(simplex); + amb_dt_simplices.insert(simplex); + } } } //------------------------------------------------------------------------- - // Check if simplices of "stars_simplices" are all in "amb_dt_simplices" + // If p_complex is NULL, parse the TC and + // save its simplices into "stars_simplices" //------------------------------------------------------------------------- - std::set diff; + Simplex_range const *p_simplices; + + if (!p_complex) + { + Simplex_range stars_simplices; + + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for ( ; it_tr != it_tr_end ; ++it_tr) + { + Triangulation const& tr = it_tr->tr(); + Tr_vertex_handle center_vh = it_tr->center_vertex(); + + std::vector incident_cells; + tr.incident_full_cells(center_vh, std::back_inserter(incident_cells)); + + typename std::vector::const_iterator it_c = + incident_cells.begin(); + typename std::vector::const_iterator it_c_end = + incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + if (tr.is_infinite(*it_c)) + { + std::cerr << "Warning: infinite cell in star" << std::endl; + continue; + } + Simplex simplex; + for (int i = 0 ; i < tr.current_dimension() + 1 ; ++i) + simplex.insert((*it_c)->vertex(i)->data()); + + stars_simplices.insert(simplex); + } + } + + p_simplices = &stars_simplices; + } + else + { + p_simplices = &p_complex->simplex_range(); + } + + //------------------------------------------------------------------------- + // Check if simplices of "*p_complex" are all in "amb_dt_simplices" + //------------------------------------------------------------------------- + + std::set diff; if (!incorrect_simplices) incorrect_simplices = &diff; - set_difference(stars_simplices.begin(), stars_simplices.end(), + set_difference(p_simplices->begin(), p_simplices->end(), amb_dt_simplices.begin(), amb_dt_simplices.end(), std::inserter(*incorrect_simplices, incorrect_simplices->begin()) ); @@ -795,14 +848,27 @@ public: << std::endl << " Number of simplices in ambient DT: " << amb_dt_simplices.size() << std::endl - << " Number of unique simplices in TC stars: " << stars_simplices.size() + << " Number of unique simplices in TC stars: " << p_simplices->size() << std::endl << " Number of wrong simplices: " << incorrect_simplices->size() << std::endl; return false; } else + { +#ifdef CGAL_TC_VERBOSE + std::cerr + << "SUCCESS check_if_all_simplices_are_in_the_ambient_delaunay:" + << std::endl + << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << std::endl + << " Number of unique simplices in TC stars: " << p_simplices->size() + << std::endl + << " Number of wrong simplices: " << incorrect_simplices->size() + << std::endl; +#endif return true; + } } private: @@ -1933,42 +1999,6 @@ private: return inconsistencies_found; } - void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() - { - for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) - { - bool inconsistencies_found; - do - { - Star::const_iterator it_inc_simplex = m_stars[idx].begin(); - Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); - for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) - { - inconsistencies_found = - check_and_solve_inconsistencies_by_adding_higher_dim_simplices( - idx, *it_inc_simplex); - - // m_stars[idx] has been modified, let's start again - // CJTODO: optimize? - if (inconsistencies_found) - break; - } - } while (inconsistencies_found); - } - - // CJTODO TEMP - std::pair stats_after = - number_of_inconsistent_simplices(false); - std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%" - << std::endl; - } - std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_simplices, bool color_inconsistencies = false) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 1fbda4dd9a5..445864ceb67 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -28,8 +28,7 @@ #include namespace CGAL { - -using namespace Tangential_complex_; +namespace Tangential_complex_ { class Simplicial_complex { @@ -123,7 +122,7 @@ public: if (k > 1) collapse(max_simplex_dim - 1); } - + void display_stats() const { std::cerr << "==========================================================\n"; @@ -160,6 +159,54 @@ public: std::cerr << "==========================================================\n"; } + // CJTODO: this is only based on the fact that each edge should have two + // cofaces + bool is_manifold(bool exit_at_the_first_problem = true) + { + typedef std::set Edge; + typedef std::map Cofaces_map; + + // Counts the number of cofaces of each edge + + // 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() > 2) + { + std::vector edges; + // Get the k-faces composing the simplex + combinations(*it_simplex, 2, std::back_inserter(edges)); + for (const auto &edge : edges) // CJTODO C++1 + { + ++cofaces_map[edge]; + } + } + } + + bool manifold = true; + 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) + { + std::cerr << "Found an edge with " << it_map_elt->second << " cofaces\n"; + if (exit_at_the_first_problem) + return false; + else + manifold = false; + } + } + + return manifold; + } + private: typedef Simplex_range Complex; @@ -167,6 +214,7 @@ private: }; // /class Simplicial_complex -} // end namespace CGAL +} // namespace Tangential_complex_ +} //namespace CGAL #endif // SIMPLICIAL_COMPLEX_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 639ce0a8f0d..a15c38f13f8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -153,6 +153,7 @@ namespace Tangential_complex_ { return output_basis; } + // CJTODO: use CGAL::Combination_enumerator (cf. Tangential_complex.h) // Compute all the k-combinations of elements // Output_iterator::value_type must be std::set > template From 9dbdaf42c440ef88e75667170ebc40a50813343f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 Feb 2015 22:56:37 +0100 Subject: [PATCH 143/269] Better export + debug code --- .../include/CGAL/Tangential_complex.h | 130 ++++++++++++++---- 1 file changed, 102 insertions(+), 28 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2f3ac0fb9ec..b499f8b1160 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -220,7 +220,8 @@ public: m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), m_ambiant_dim(k.point_dimension_d_object()(*first)), m_points(first, last) -# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ + && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) # endif , m_points_ds(m_points) @@ -233,7 +234,8 @@ public: /// Destructor ~Tangential_complex() { -#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ + && defined(CGAL_TC_GLOBAL_REFRESH) delete [] m_p_perturb_mutexes; #endif } @@ -595,7 +597,8 @@ public: } // Return the max dimension of the simplices - int export_TC(Simplicial_complex &complex) + int export_TC(Simplicial_complex &complex, + bool export_infinite_simplices = false) { int max_dim = -1; @@ -611,6 +614,11 @@ public: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { + // Don't export infinite cells + if (!export_infinite_simplices && *it_inc_simplex->rbegin() + == std::numeric_limits::max()) + continue; + std::set c = *it_inc_simplex; if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); @@ -657,15 +665,17 @@ public: << 100. * stats_after.second / stats_after.first << "%" << std::endl; } - + std::ostream &export_to_off( - const Simplicial_complex &complex, std::ostream & os) + const Simplicial_complex &complex, std::ostream & os, + std::set > const *p_additional_simpl_to_color = NULL) { - return export_to_off(os, false, &complex); + return export_to_off(os, false, p_additional_simpl_to_color, &complex); } - + std::ostream &export_to_off( - std::ostream & os, bool color_inconsistencies = false, + std::ostream & os, bool color_inconsistencies = false, + std::set > const *p_additional_simpl_to_color = NULL, const Simplicial_complex *p_complex = NULL) { if (m_points.empty()) @@ -702,11 +712,16 @@ public: std::size_t num_simplices, num_vertices; export_vertices_to_off(output, num_vertices); if (p_complex) + { export_simplices_to_off( - *p_complex, output, num_simplices, color_inconsistencies); + *p_complex, output, num_simplices, p_additional_simpl_to_color); + } else + { export_simplices_to_off( - output, num_simplices, color_inconsistencies); + output, num_simplices, color_inconsistencies, + p_additional_simpl_to_color); + } #ifdef CGAL_TC_EXPORT_NORMALS os << "N"; @@ -1892,6 +1907,8 @@ private: Tr_point Cq = tr_power_center( simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); + //std::cerr << "Cq weight: " << tr_point_weight(Cq) << std::endl; // CJTODO TEMP + //------------------------------------------------------------------------- //3. Find points t1, t2... (in ambient space) which are inside S //------------------------------------------------------------------------- @@ -1911,6 +1928,36 @@ private: inconsistent_simplex.end()) { inside_point_idx = neighbor_point_idx; + + { // CJTODO TEMP DEBUG + ++nn_it; + int count_insiders = 1; + for (int count = 0 ; count < inconsistent_simplex.size() ; ++count, ++nn_it) + { + std::size_t neighbor_point_idx = nn_it->first; + if (inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) + { + //std::cerr << "insider dist: " << nn_it->second << std::endl; // CJTODO TEMP + ++count_insiders; + } + else + { + //std::cerr << "Simplex point dist: " << nn_it->second << std::endl; // CJTODO TEMP + ++count; + } + } + + if (count_insiders > 1) + { + std::cerr << "Warning: " << count_insiders << " insiders in " + << inconsistent_simplex.size() - 1 << " simplex\n"; + } + //else + // std::cerr << "Ok: only one vertex inside the sphere\n"; + + } // END CJTODO + break; } } @@ -1954,6 +2001,11 @@ private: { bool inconsistencies_found = false; + // Don't check infinite simplices + if (*incident_simplex.rbegin() + == std::numeric_limits::max()) + return false; + std::set simplex = incident_simplex; simplex.insert(tr_index); @@ -1964,9 +2016,6 @@ private: for ( ; it_point_idx != simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; - // Don't check infinite simplices - if (point_idx == std::numeric_limits::max()) - continue; Star const& star = m_stars[point_idx]; @@ -2001,7 +2050,8 @@ private: std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_simplices, - bool color_inconsistencies = false) + bool color_inconsistencies = false, + std::set > const *p_additional_simpl_to_color = NULL) { // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) @@ -2040,14 +2090,22 @@ private: c.insert(idx); std::size_t num_vertices = c.size(); - bool is_simpl_consistent = true; + bool color_simplex = false; if (color_inconsistencies) { - is_simpl_consistent = is_simplex_consistent(c); - if (!is_simpl_consistent) + color_simplex = !is_simplex_consistent(c); + if (color_simplex) is_star_inconsistent = true; } + if (p_additional_simpl_to_color && !color_simplex) + { + color_simplex = (std::find( + p_additional_simpl_to_color->begin(), + p_additional_simpl_to_color->end(), + c) != p_additional_simpl_to_color->end()); + } + // If only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) if (num_vertices == 2) @@ -2062,7 +2120,7 @@ private: if (num_vertices <= 3) { - star_using_triangles.push_back(std::make_pair(c, is_simpl_consistent)); + star_using_triangles.push_back(std::make_pair(c, color_simplex)); } else { @@ -2079,7 +2137,7 @@ private: triangle.insert(*it); } star_using_triangles.push_back( - std::make_pair(triangle, is_simpl_consistent)); + std::make_pair(triangle, color_simplex)); } while (std::next_permutation(booleans.begin(), booleans.end())); } } @@ -2097,7 +2155,7 @@ private: continue; const std::set &c = it_simplex->first; - bool is_simpl_consistent = it_simplex->second; + bool color_simplex = it_simplex->second; std::stringstream sstr_c; @@ -2109,19 +2167,19 @@ private: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != idx && is_simpl_consistent) + if (*c.begin() != idx && !color_simplex) continue; os << 3 << " " << sstr_c.str(); - if (color_inconsistencies) + if (color_inconsistencies || p_additional_simpl_to_color) { - if (is_simpl_consistent) - os << " " << color.str(); - else + if (color_simplex) { os << " 255 0 0"; ++num_inconsistent_simplices; } + else + os << " " << color.str(); } ++num_simplices; os << std::endl; @@ -2154,11 +2212,10 @@ private: return os; } - std::ostream &export_simplices_to_off( const Simplicial_complex &complex, std::ostream & os, std::size_t &num_simplices, - bool color_inconsistencies = false) + std::set > const *p_additional_simpl_to_color = NULL) { typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; @@ -2175,7 +2232,16 @@ private: { Simplex c = *it_s; - // Gather the triangles here, with a bool saying if it's consistent + bool color_simplex = false; + if (p_additional_simpl_to_color) + { + color_simplex = (std::find( + p_additional_simpl_to_color->begin(), + p_additional_simpl_to_color->end(), + c) != p_additional_simpl_to_color->end()); + } + + // Gather the triangles here typedef std::vector Triangles; Triangles triangles; @@ -2235,6 +2301,14 @@ private: os << *it_point_idx << " "; } + if (p_additional_simpl_to_color) + { + if (color_simplex) + os << " 255 0 0"; + else + os << " 128 128 128"; + } + ++num_simplices; os << std::endl; } From 70c4d330c5cd07acd1ecbb3df2fc1d19e75bbfbf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 Feb 2015 22:57:27 +0100 Subject: [PATCH 144/269] More exports in the benchmark --- .../Tangential_complex/benchmark_tc.cpp | 61 ++++++++++++++----- .../include/CGAL/Tangential_complex/config.h | 4 +- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 46e4264356b..b8f795ceea5 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -213,17 +213,7 @@ void make_tc(std::vector &points, int intrinsic_dim, CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", final_num_inconsistent_local_tr); - tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); - TC::Simplicial_complex complex; - int max_dim = tc.export_TC(complex); - tc.check_if_all_simplices_are_in_the_ambient_delaunay(&complex); - complex.collapse(max_dim); - complex.display_stats(); - - std::ofstream off_stream("output/test.off"); // CJTODO TEMP TEST - tc.export_to_off(complex, off_stream); - - double export_after_time = -1.; + double export_after_fix_time = -1.; if (intrinsic_dim <= 3) { t.reset(); @@ -232,10 +222,48 @@ void make_tc(std::vector &points, int intrinsic_dim, << "_in_R" << ambient_dim << "_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(); + export_after_fix_time = t.elapsed(); t.reset(); } - /*else - tc.number_of_inconsistent_simplices();*/ + + // Try to solve the remaining inconstencies + tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + TC::Simplicial_complex complex; + int max_dim = tc.export_TC(complex, false); + std::set > not_delaunay_simplices; + if (ambient_dim <= 4) + { + tc.check_if_all_simplices_are_in_the_ambient_delaunay( + &complex, true, ¬_delaunay_simplices); + } + + double export_after_fix2_time = -1.; + if (intrinsic_dim <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim + << "_in_R" << ambient_dim << "_AFTER_FIX2.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(complex, off_stream, ¬_delaunay_simplices); + export_after_fix2_time = t.elapsed(); t.reset(); + } + + // Collapse + complex.collapse(max_dim); + + double export_after_collapse_time = -1.; + if (intrinsic_dim <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim + << "_in_R" << ambient_dim << "_AFTER_COLLAPSE.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(complex, off_stream); + export_after_collapse_time = t.elapsed(); t.reset(); + } + + complex.display_stats(); std::cerr << std::endl << "================================================" << std::endl @@ -249,7 +277,10 @@ void make_tc(std::vector &points, int intrinsic_dim, << " * 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 + << " * Export to OFF (after fix): " << export_after_fix_time << std::endl + << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl + << " * Export to OFF (after collapse): " + << export_after_collapse_time << std::endl << "================================================" << std::endl << std::endl; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index f9339340dbe..47bf0147c91 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -58,10 +58,10 @@ // 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 # define CGAL_TC_PERTURB_POSITION_TANGENTIAL // default //# define CGAL_TC_PERTURB_POSITION_GLOBAL -//#define CGAL_TC_PERTURB_WEIGHT +#define CGAL_TC_PERTURB_WEIGHT //#define CGAL_TC_PERTURB_TANGENT_SPACE //========================= Parameters ======================================== From bdf8a6286b47e5866c5c0ee60ee4cf13c112b44d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 23 Feb 2015 17:43:30 +0100 Subject: [PATCH 145/269] Add TODOs and temporary comments --- Tangential_complex/include/CGAL/Tangential_complex.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b499f8b1160..59ea4b8baed 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -632,6 +632,7 @@ public: void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() { + // CJTODO: parallel_for for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) { bool inconsistencies_found; @@ -1915,6 +1916,10 @@ private: // CJTODO: on prend le point le plus proche pour l'instant, mais il // faudra changer ça (cf 4 5 6, ci dessous) + // Et aussi, il faudra utiliser Power_distance dans le cas oů on perturbe + // avec des poids (on est dans l'espace ambiant, donc ce sont les seuls + // poids possibles). Il faut aussi ajouter une marge lors de la recherche + // ANN puis restester la distance avec le vrai point perturbée. Point global_Cq = unproject_point(Cq, center_pt, m_tangent_spaces[q_idx], q_tr_traits); std::size_t inside_point_idx; From f4de16d0932a9ace0297e6433a1343528cc8dac6 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 24 Feb 2015 14:00:28 +0100 Subject: [PATCH 146/269] Link Power_center_d. --- NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h | 2 ++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index cd8269f07da..52114ff6442 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -66,6 +66,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Point_dimension_d; typedef typename Get_functor::type Side_of_oriented_sphere_d; typedef typename Get_functor::type Power_test_d; + typedef typename Get_functor::type Power_center_d; typedef typename Get_functor::type Contained_in_affine_hull_d; typedef typename Get_functor::type Construct_flat_orientation_d; typedef typename Get_functor::type In_flat_orientation_d; @@ -175,6 +176,7 @@ template 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_test_d power_test_d_object()const{ return Power_test_d(*this); } + Power_center_d power_center_d_object()const{ return Power_center_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); } diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 96ca0b4c39e..99c369a5f55 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -123,7 +123,7 @@ void test2(){ typedef typename K1::Difference_of_vectors_d DV; typedef typename K1::Difference_of_points_d DP; typedef typename K1::Translated_point_d TP; - typedef typename CGAL::Get_functor::type PC; + typedef typename K1::Power_center_d PC; typedef typename CGAL::Get_functor::type PoD; typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; @@ -187,7 +187,7 @@ void test2(){ DV dv Kinit(difference_of_vectors_d_object); DP dp Kinit(difference_of_points_d_object); TP tp Kinit(translated_point_d_object); - PC pc (k); + 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); From ed6ac903843d7732e43caae7d026726de0a57b3a Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 24 Feb 2015 17:32:47 +0100 Subject: [PATCH 147/269] Link Power_distance_d. --- NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h | 2 ++ NewKernel_d/test/NewKernel_d/Epick_d.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index 52114ff6442..4652e2dc17b 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -67,6 +67,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Side_of_oriented_sphere_d; typedef typename Get_functor::type Power_test_d; typedef typename Get_functor::type Power_center_d; + typedef typename Get_functor::type Power_distance_d; typedef typename Get_functor::type Contained_in_affine_hull_d; typedef typename Get_functor::type Construct_flat_orientation_d; typedef typename Get_functor::type In_flat_orientation_d; @@ -177,6 +178,7 @@ template struct Kernel_d_interface : public Base_ { Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } Power_test_d power_test_d_object()const{ return Power_test_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); } diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 99c369a5f55..1b9dbcd45e8 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -124,7 +124,7 @@ void test2(){ typedef typename K1::Difference_of_points_d DP; typedef typename K1::Translated_point_d TP; typedef typename K1::Power_center_d PC; - typedef typename CGAL::Get_functor::type PoD; + 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; @@ -191,7 +191,7 @@ void test2(){ 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 (k); + PoD pod Kinit(power_distance_d_object); CGAL_USE(bc); CGAL_USE(pol); From a08463fd4d79049b00f1852d32f240d5e4d6014c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 14:32:19 +0100 Subject: [PATCH 148/269] check_if_all_simplices_are_in_the_ambient_delaunay takes weights into account --- .../include/CGAL/Tangential_complex.h | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 59ea4b8baed..ecece6b9921 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -749,24 +749,26 @@ public: return true; const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); - typedef Delaunay_triangulation - > > DT; - typedef typename DT::Vertex_handle DT_VH; - typedef typename DT::Finite_full_cell_const_iterator FFC_it; + typedef Regular_triangulation_euclidean_traits RT_Traits; + typedef Regular_triangulation< + RT_Traits, + Triangulation_data_structure< + typename RT_Traits::Dimension, + Triangulation_vertex + > > RT; + typedef typename RT::Vertex_handle RT_VH; + typedef typename RT::Finite_full_cell_const_iterator FFC_it; //------------------------------------------------------------------------- // Build the ambient Delaunay triangulation // Then save its simplices into "amb_dt_simplices" //------------------------------------------------------------------------- - DT ambient_dt(ambient_dim); + RT ambient_dt(ambient_dim); for (std::size_t i=0; idata() = i; } @@ -862,7 +864,7 @@ public: std::cerr << "ERROR check_if_all_simplices_are_in_the_ambient_delaunay:" << std::endl - << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << " Number of simplices in ambient RT: " << amb_dt_simplices.size() << std::endl << " Number of unique simplices in TC stars: " << p_simplices->size() << std::endl @@ -876,7 +878,7 @@ public: std::cerr << "SUCCESS check_if_all_simplices_are_in_the_ambient_delaunay:" << std::endl - << " Number of simplices in ambient DT: " << amb_dt_simplices.size() + << " Number of simplices in ambient RT: " << amb_dt_simplices.size() << std::endl << " Number of unique simplices in TC stars: " << p_simplices->size() << std::endl From 907483a0d09f2e50bea19108345e6b79278340e4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 14:35:14 +0100 Subject: [PATCH 149/269] Remove unused classes --- .../include/CGAL/Tangential_complex.h | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ecece6b9921..2071a278936 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -909,42 +909,6 @@ private: Kernel const& m_k; }; - struct Tr_vertex_to_global_point - { - typedef Tr_vertex_handle argument_type; - typedef Point result_type; - - Tr_vertex_to_global_point(Points const& points) - : m_points(points) {} - - result_type operator()(argument_type const& vh) const - { - return m_points[vh->data()]; - } - - private: - Points const& m_points; - }; - - struct Tr_vertex_to_bare_point - { - typedef Tr_vertex_handle argument_type; - typedef Tr_bare_point result_type; - - Tr_vertex_to_bare_point(Tr_traits const& traits) - : m_traits(traits) {} - - result_type operator()(argument_type const& vh) const - { - typename Tr_traits::Point_drop_weight_d pdw = - m_traits.point_drop_weight_d_object(); - return pdw(vh->point()); - } - - private: - Tr_traits const& m_traits; - }; - #ifdef CGAL_LINKED_WITH_TBB // Functor for compute_tangential_complex function class Compute_tangent_triangulation From 91a52fe65badb1a6a925dfb2dfbe743d4a212a52 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 16:02:15 +0100 Subject: [PATCH 150/269] Improve solve_inconsistency_by_adding_higher_dimensional_simplices Now, it handles the case where more than one vertices are in the Tq-centered sphere. Also, fixes a bug with the star-sphere radius. --- .../include/CGAL/Tangential_complex.h | 493 ++++++++++++------ 1 file changed, 328 insertions(+), 165 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2071a278936..53d557d4d73 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -112,6 +112,7 @@ class Tangential_complex { typedef typename Kernel::FT FT; typedef typename Kernel::Point_d Point; + typedef typename Kernel::Weighted_point_d Weighted_point; typedef typename Kernel::Vector_d Vector; typedef Tr Triangulation; @@ -386,14 +387,17 @@ public: #endif } - // time_limit in seconds + // time_limit in seconds: 0 = no fix to do, < 0 = no time limit Fix_inconsistencies_status fix_inconsistencies( unsigned int &num_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, - double time_limit = 0.) + double time_limit = -1.) { + if (time_limit == 0.) + return TIME_LIMIT_REACHED; + Wall_clock_timer t; typename Kernel::Point_drop_weight_d drop_w = @@ -525,7 +529,7 @@ public: ++num_steps; done = (num_inconsistent_local_tr == 0); - if (!done && time_limit != 0 && t.elapsed() > time_limit) + if (!done && time_limit > 0. && t.elapsed() > time_limit) { #ifdef CGAL_TC_VERBOSE std::cerr << "Time limit reached." << std::endl; @@ -944,8 +948,11 @@ private: #endif // CGAL_LINKED_WITH_TBB void compute_tangent_triangulation( - std::size_t i, bool tangent_spaces_are_already_computed = false) + std::size_t i, bool tangent_spaces_are_already_computed = false, + bool verbose = false) { + if (verbose) + std::cerr << "** Computing tangent tri #" << i << " **" << std::endl; //std::cerr << "***********************************************" << std::endl; Triangulation &local_tr = m_triangulations[i].construct_triangulation(m_intrinsic_dimension); @@ -953,31 +960,19 @@ private: Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects - typename Kernel::Difference_of_points_d k_diff_pts = - m_k.difference_of_points_d_object(); typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); - typename Kernel::Translated_point_d k_transl = - m_k.translated_point_d_object(); // Triangulation's traits functor & objects - typename Tr_traits::Squared_distance_d sqdist = - local_tr_traits.squared_distance_d_object(); typename Tr_traits::Point_weight_d point_weight = local_tr_traits.point_weight_d_object(); - typename Tr_traits::Point_drop_weight_d drop_w = - local_tr_traits.point_drop_weight_d_object(); /*typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object();*/ // CJTODO typename Get_functor::type power_center(local_tr_traits); -#ifdef CGAL_TC_PERTURB_POSITION // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions - const Point center_pt = k_transl(m_points[i], m_translations[i]); -#else - const Point ¢er_pt = m_points[i]; -#endif + const Point center_pt = compute_perturbed_point(i); // Estimate the tangent space if (!tangent_spaces_are_already_computed) @@ -1016,6 +1011,8 @@ private: ); center_vertex = local_tr.insert(wp); center_vertex->data() = i; + if (verbose) + std::cerr << "* Inserted point #" << i << std::endl; //const int NUM_NEIGHBORS = 150; //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); @@ -1025,7 +1022,7 @@ private: // of the sphere "star sphere" centered at "center_vertex" // and which contains all the // circumspheres of the star of "center_vertex" - boost::optional star_sphere_squared_radius; + boost::optional squared_star_sphere_radius_plus_margin; // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; @@ -1037,24 +1034,17 @@ private: // ith point = p, which is already inserted if (neighbor_point_idx != i) { -#ifdef CGAL_TC_PERTURB_POSITION - // No need to lock the mutex here since this will not be called while - // other threads are perturbing the positions - const Point neighbor_pt = k_transl( - m_points[neighbor_point_idx], m_translations[neighbor_point_idx]); -#else - const Point &neighbor_pt = m_points[neighbor_point_idx]; -#endif -#ifdef CGAL_TC_PERTURB_WEIGHT - FT neighbor_weight = m_weights[neighbor_point_idx]; -#else - FT neighbor_weight = 0; -#endif + // No need to lock the Mutex_for_perturb here since this will not be + // called while other threads are perturbing the positions + Point neighbor_pt; + FT neighbor_weight; + compute_perturbed_weighted_point( + neighbor_point_idx, neighbor_pt, neighbor_weight); // "4*m_sq_half_sparsity" because both points can be perturbed - if (star_sphere_squared_radius + if (squared_star_sphere_radius_plus_margin && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*m_sq_half_sparsity) + > *squared_star_sphere_radius_plus_margin) break; Tr_point proj_pt = project_point_and_compute_weight( @@ -1065,18 +1055,15 @@ private: //Tr_vertex_handle vh = local_tr.insert(proj_pt); if (vh != Tr_vertex_handle()) { - // CJTODO TEMP TEST - /*if (star_sphere_squared_radius - && k_sqdist(center_pt, neighbor_pt) - > *star_sphere_squared_radius + 4*m_sq_half_sparsity) - std::cout << "ARGGGGGGGH" << std::endl;*/ + if (verbose) + std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; vh->data() = neighbor_point_idx; - // Let's recompute star_sphere_squared_radius + // Let's recompute squared_star_sphere_radius_plus_margin if (local_tr.current_dimension() >= m_intrinsic_dimension) { - star_sphere_squared_radius = 0; + squared_star_sphere_radius_plus_margin = boost::none; // Get the incident cells and look for the biggest circumsphere std::vector incident_cells; local_tr.incident_full_cells( @@ -1088,7 +1075,7 @@ private: Tr_full_cell_handle cell = *cit; if (local_tr.is_infinite(cell)) { - star_sphere_squared_radius = boost::none; + squared_star_sphere_radius_plus_margin = boost::none; break; } else @@ -1101,16 +1088,24 @@ private: FT sq_power_sphere_diam = 4*point_weight(c); - if (!star_sphere_squared_radius - || sq_power_sphere_diam > *star_sphere_squared_radius) + if (!squared_star_sphere_radius_plus_margin + || sq_power_sphere_diam > + *squared_star_sphere_radius_plus_margin) { - star_sphere_squared_radius = sq_power_sphere_diam; + squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; } } } + + // Let's add the margin, now + if (squared_star_sphere_radius_plus_margin) + { + squared_star_sphere_radius_plus_margin = CGAL::square( + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + + 2*m_half_sparsity); + } } } - //std::cerr << star_sphere_squared_radius << std::endl; } } @@ -1118,8 +1113,8 @@ private: // Update the associated star (in m_stars) //*************************************************** Star &star = m_stars[i]; - int cur_dim_plus_1 = local_tr.current_dimension() + 1; star.clear(); + int cur_dim_plus_1 = local_tr.current_dimension() + 1; std::vector incident_cells; local_tr.incident_full_cells( @@ -1270,6 +1265,51 @@ private: */ } + Point compute_perturbed_point(std::size_t pt_idx) + { +#ifdef CGAL_TC_PERTURB_POSITION + return m_k.translated_point_d_object()( + m_points[pt_idx], m_translations[pt_idx]); +#else + return m_points[pt_idx]; +#endif + } + + void compute_perturbed_weighted_point(std::size_t pt_idx, Point &p, FT &w) + { +#ifdef CGAL_TC_PERTURB_POSITION + p = m_k.translated_point_d_object()( + m_points[pt_idx], m_translations[pt_idx]); +#else + p = m_points[pt_idx]; +#endif +#ifdef CGAL_TC_PERTURB_WEIGHT + w = m_weights[pt_idx]; +#else + w = 0; +#endif + } + + Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) + { + typename Kernel::Construct_weighted_point_d k_constr_wp = + m_k.construct_weighted_point_d_object(); + + Weighted_point wp = k_constr_wp( +#ifdef CGAL_TC_PERTURB_POSITION + m_k.translated_point_d_object()(m_points[pt_idx], m_translations[pt_idx]), +#else + m_points[pt_idx], +#endif +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[pt_idx]); +#else + 0); +#endif + + return wp; + } + Point unproject_point(const Tr_point &p, const Point &origin, const Tangent_space_basis &tsb, const Tr_traits &tr_traits) @@ -1318,6 +1358,18 @@ private: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p + Tr_point project_point_and_compute_weight( + const Weighted_point &wp, const Point &origin, const Tangent_space_basis &ts, + const Tr_traits &tr_traits) const + { + typename Kernel::Point_drop_weight_d k_drop_w = + m_k.point_drop_weight_d_object(); + typename Kernel::Point_weight_d k_point_weight = + m_k.point_weight_d_object(); + return project_point_and_compute_weight( + k_drop_w(wp), k_point_weight(wp), origin, ts, tr_traits); + } + Tr_point project_point_and_compute_weight( const Point &p, FT w, const Point &origin, const Tangent_space_basis &ts, const Tr_traits &tr_traits) const @@ -1392,19 +1444,7 @@ private: ic_to_find.erase(point_idx); // For each cell - bool found = false; - Star::const_iterator it_inc_simplex = star.begin(); - Star::const_iterator it_inc_simplex_end = star.end(); - for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) - { - if (*it_inc_simplex == ic_to_find) - { - found = true; - break; - } - } - - if (!found) + if (std::find(star.begin(), star.end(), ic_to_find) == star.end()) return false; } @@ -1730,7 +1770,8 @@ private: } std::ostream &export_vertices_to_off( - std::ostream & os, std::size_t &num_vertices) + std::ostream & os, std::size_t &num_vertices, + bool use_perturbed_points = false) { if (m_points.empty()) { @@ -1755,13 +1796,14 @@ private: typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); // For each point p - for ( ; it_p != it_p_end ; ++it_p) + for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) { + Point p = (use_perturbed_points ? compute_perturbed_point(i) : *it_p); for (int ii = 0 ; ii < N ; ++ii) { int i = 0; for ( ; i < num_coords ; ++i) - os << CGAL::to_double(coord(*it_p, i)) << " "; + os << CGAL::to_double(coord(p, i)) << " "; if (i == 2) os << "0"; @@ -1810,12 +1852,37 @@ private: // Solves one inconsistency // "inconsistent_simplex" must contain p_idx and q_idx + // "inconsistent_simplex" must be in star(p) but not in star(q) void solve_inconsistency_by_adding_higher_dimensional_simplices( std::size_t p_idx, std::size_t q_idx, const std::set &inconsistent_simplex) { + CGAL_assertion_code( + std::set inc_s_minus_p = inconsistent_simplex; + inc_s_minus_p.erase(p_idx); + std::set inc_s_minus_q = inconsistent_simplex; + inc_s_minus_q.erase(q_idx); + ); + CGAL_assertion(std::find(m_stars[p_idx].begin(), m_stars[p_idx].end(), + inc_s_minus_p) != m_stars[p_idx].end()); + CGAL_assertion(std::find(m_stars[q_idx].begin(), m_stars[q_idx].end(), + inc_s_minus_q) == m_stars[q_idx].end()); + + typename Kernel::Point_drop_weight_d k_drop_w = + m_k.point_drop_weight_d_object(); typename Kernel::Translated_point_d k_transl = m_k.translated_point_d_object(); + typename Kernel::Squared_distance_d k_sqdist = + m_k.squared_distance_d_object(); + typename Kernel::Difference_of_points_d k_diff_pts = + m_k.difference_of_points_d_object(); + typename Kernel::Scalar_product_d k_inner_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Construct_weighted_point_d k_constr_wp = + m_k.construct_weighted_point_d_object(); + //typename Kernel::Power_distance_d k_power_dist = + // m_k.power_distance_d_object(); // CJTODO + typename Get_functor::type k_power_dist(m_k); const Tr_traits &q_tr_traits = m_triangulations[q_idx].tr().geom_traits(); /*typename Tr_traits::Power_center_d power_center = @@ -1825,130 +1892,238 @@ private: q_tr_traits.point_weight_d_object(); //------------------------------------------------------------------------- - //1. Compute power_center(p'q'r') in Tp => cp - //------------------------------------------------------------------------- - // CJTODO - - //------------------------------------------------------------------------- + //1. Compute power_center(p'q'r1'r2'..ri') in Tp => Cp //2. Compute power_center(inconsistent_simplex projected in Tq) // => gives Cq and radius Rq // Rq is also the radius of the ambient sphere S whose center is Cq and // which goes through all the ambient points of "inconsistent_simplex" - //------------------------------------------------------------------------- - std::vector simplex_pts_in_Tq; + //------------------------------------------------------------------------ + std::vector simplex_pts_in_Tp, simplex_pts_in_Tq; + simplex_pts_in_Tp.reserve(inconsistent_simplex.size()); simplex_pts_in_Tq.reserve(inconsistent_simplex.size()); - -#ifdef CGAL_TC_PERTURB_POSITION + // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions - const Point center_pt = k_transl(m_points[q_idx], m_translations[q_idx]); -#else - const Point ¢er_pt = m_points[q_idx]; -#endif + const Point pt_p = compute_perturbed_point(p_idx); + const Point pt_q = compute_perturbed_point(q_idx); std::set::const_iterator it_point_idx = inconsistent_simplex.begin(); std::set::const_iterator it_point_idx_end = inconsistent_simplex.end(); - // For each point p of the simplex, we reproject it onto the tangent + // For each point of the simplex, we reproject it onto the tangent // space. Could be optimized since it's already been computed before. for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { -#ifdef CGAL_TC_PERTURB_POSITION - // No need to lock the mutex here since this will not be called while - // other threads are perturbing the positions - const Point p = k_transl( - m_points[*it_point_idx], m_translations[*it_point_idx]); -#else - const Point &p = m_points[*it_point_idx]; -#endif -#ifdef CGAL_TC_PERTURB_WEIGHT - FT w = m_weights[*it_point_idx]; -#else - FT w = 0; -#endif + const Weighted_point wp = compute_perturbed_weighted_point(*it_point_idx); + // No need to lock the Mutex_for_perturb here since this will not be + // called while other threads are perturbing the positions + simplex_pts_in_Tp.push_back(project_point_and_compute_weight( + wp, pt_p, m_tangent_spaces[p_idx], q_tr_traits)); simplex_pts_in_Tq.push_back(project_point_and_compute_weight( - p, w, center_pt, m_tangent_spaces[q_idx], q_tr_traits)); + wp, pt_q, m_tangent_spaces[q_idx], q_tr_traits)); } + Tr_point Cp = tr_power_center( + simplex_pts_in_Tp.begin(), simplex_pts_in_Tp.end()); Tr_point Cq = tr_power_center( simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); - //std::cerr << "Cq weight: " << tr_point_weight(Cq) << std::endl; // CJTODO TEMP + FT circumsphere_sqradius_p = tr_point_weight(Cp); + FT circumsphere_sqradius_q = tr_point_weight(Cq); + FT squared_circumsphere_radius_q_plus_margin = CGAL::square( + CGAL::sqrt(circumsphere_sqradius_q) + 2*m_half_sparsity); - //------------------------------------------------------------------------- - //3. Find points t1, t2... (in ambient space) which are inside S - //------------------------------------------------------------------------- - - // CJTODO: on prend le point le plus proche pour l'instant, mais il - // faudra changer ça (cf 4 5 6, ci dessous) - // Et aussi, il faudra utiliser Power_distance dans le cas oů on perturbe - // avec des poids (on est dans l'espace ambiant, donc ce sont les seuls - // poids possibles). Il faut aussi ajouter une marge lors de la recherche - // ANN puis restester la distance avec le vrai point perturbée. - Point global_Cq = unproject_point(Cq, center_pt, - m_tangent_spaces[q_idx], q_tr_traits); - std::size_t inside_point_idx; - INS_range ins_range = m_points_ds.query_incremental_ANN(global_Cq); + Weighted_point global_Cp = k_constr_wp( + unproject_point(Cp, pt_p, m_tangent_spaces[p_idx], q_tr_traits), + circumsphere_sqradius_p); + + Weighted_point global_Cq = k_constr_wp( + unproject_point(Cq, pt_q, m_tangent_spaces[q_idx], q_tr_traits), + circumsphere_sqradius_q); + + + // CJTODO TEMP ==================== + /*{ + INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(global_Cp)); for (INS_iterator nn_it = ins_range.begin() ; nn_it != ins_range.end() ; ++nn_it) { + FT neighbor_sqdist = nn_it->second; + + //std::cerr << nn_it->first << " : " << neighbor_sqdist << " / "; // CJTODO TEMP + + // When we're sure we got all the potential points, break + //if (neighbor_sqdist > circumsphere_sqradius_p + m_sq_half_sparsity) + // break; + std::size_t neighbor_point_idx = nn_it->first; - if (inconsistent_simplex.find(neighbor_point_idx) == - inconsistent_simplex.end()) + FT point_to_Cp_power_sqdist = k_power_dist( + global_Cp, compute_perturbed_weighted_point(neighbor_point_idx)); + //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP + // If the point is ACTUALLY "inside" S + if (point_to_Cp_power_sqdist <= FT(0) + && inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) { - inside_point_idx = neighbor_point_idx; - - { // CJTODO TEMP DEBUG - ++nn_it; - int count_insiders = 1; - for (int count = 0 ; count < inconsistent_simplex.size() ; ++count, ++nn_it) - { - std::size_t neighbor_point_idx = nn_it->first; - if (inconsistent_simplex.find(neighbor_point_idx) == - inconsistent_simplex.end()) - { - //std::cerr << "insider dist: " << nn_it->second << std::endl; // CJTODO TEMP - ++count_insiders; - } - else - { - //std::cerr << "Simplex point dist: " << nn_it->second << std::endl; // CJTODO TEMP - ++count; - } - } - - if (count_insiders > 1) - { - std::cerr << "Warning: " << count_insiders << " insiders in " - << inconsistent_simplex.size() - 1 << " simplex\n"; - } - //else - // std::cerr << "Ok: only one vertex inside the sphere\n"; - - } // END CJTODO - - break; + std::cerr << "Warning: " << neighbor_point_idx << " is inside Cp with power dist " << point_to_Cp_power_sqdist << "\n"; } } + }*/ + // /CJTODO ==================== - //std::size_t inside_point_idx = kns_range.begin()->first; - //------------------------------------------------------------------------- - //4. S'il n'y a qu'un seul points ti, passer ŕ la derničre étape + //3. Find points t1, t2... (in ambient space) which are inside S //------------------------------------------------------------------------- + std::vector inside_pt_indices; + INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(global_Cq)); + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) + { + FT neighbor_sqdist = nn_it->second; + + // When we're sure we got all the potential points, break + if (neighbor_sqdist > squared_circumsphere_radius_q_plus_margin) + break; + + std::size_t neighbor_point_idx = nn_it->first; + FT point_to_Cq_power_sqdist = k_power_dist( + global_Cq, compute_perturbed_weighted_point(neighbor_point_idx)); + // If the point is ACTUALLY "inside" S + if (point_to_Cq_power_sqdist <= FT(0) + && inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) + { + inside_pt_indices.push_back(neighbor_point_idx); + } + // CJTODO TEMP: + /*{ + typename Tr_traits::Power_test_d side = q_tr_traits.power_test_d_object(); + typename Tr_traits::Orientation_d orient = q_tr_traits.orientation_d_object(); + Orientation o = orient(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); + auto p = project_point_and_compute_weight( + compute_perturbed_weighted_point(neighbor_point_idx), + pt_q, m_tangent_spaces[q_idx], q_tr_traits); + auto sid = (o == NEGATIVE ? + side(simplex_pts_in_Tq.rbegin(), simplex_pts_in_Tq.rend(), p) + : side(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end(), p)); + switch(sid) + { + case ON_NEGATIVE_SIDE: + std::cerr << "ON_NEGATIVE_SIDE" << std::endl; // CJTODO TEMP + break; + case ON_POSITIVE_SIDE: + std::cerr << "ON_POSITIVE_SIDE" << std::endl; // CJTODO TEMP + break; + case ON_ORIENTED_BOUNDARY: + std::cerr << "ON_ORIENTED_BOUNDARY" << std::endl; // CJTODO TEMP + break; + } + }*/ + } + CGAL_assertion_msg(!inside_pt_indices.empty(), + "There should be at least one vertex inside the sphere"); + // CJTODO TEMP DEBUG + /*if (inside_pt_indices.empty()) + { + //compute_tangent_triangulation(q_idx, true, true); + std::cerr << "Error: inside_pt_indices.empty()\n"; + std::cerr << "Stars:\n"; + for (auto s : m_stars[q_idx]) + { + std::cerr << q_idx << " "; + std::copy(s.begin(), s.end(), + std::ostream_iterator(std::cerr, " ")); + std::cerr << std::endl; + } + std::cerr << std::endl; + }*/ + // CJTODO TEMP DEBUG + if (inside_pt_indices.size() > 1) + { + std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " + << inconsistent_simplex.size() - 1 << " simplex\n"; + } + //------------------------------------------------------------------------- - //5. Pour chaque ti, calculer la sphčre qui passe par p, q, r, ti dont le centre est sur la droite (cq, cq) + //4. If there's more than one ti... or not //------------------------------------------------------------------------- - + // CJTODO: take weights into account + std::size_t inside_point_idx; + if (inside_pt_indices.size() > 1) + { + //----------------------------------------------------------------------- + //5. For each ti, compute the sphere that goes through + // p, q, r1, r2..., ri and ti whose center is on (cp, cq) + // We're looking for a point on (Cp, Cq) at equal distance from p and + // ti. + // The center of the sphere is then: Cp + a(Cq - Cp) + // where a = (sqdist(Cp,ti) - sqdist(Cp,p)) / (2*(Cq-Cp).(ti-p)) + //6. Keep point ti such as dist(cp, ci) is the smallest + //----------------------------------------------------------------------- + + FT min_a = std::numeric_limits::max(); + for (auto idx : inside_pt_indices) // CJTODO: C++11 + { + const Point ti = compute_perturbed_point(idx); + const Point &cp = k_drop_w(global_Cp); + const Point &cq = k_drop_w(global_Cq); + FT a = + (k_sqdist(cp, ti) - k_sqdist(cp, pt_p)) / + (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); + + if (a < min_a) + { + min_a = a; + inside_point_idx = idx; + } + } + + // CJTODO TEMP ==================== + /*{ + typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + typename Kernel::Point_weight_d k_weight = m_k.point_weight_d_object(); + Weighted_point C = k_constr_wp( + k_transl(k_drop_w(global_Cp), scaled_vec(k_diff_pts(k_drop_w(global_Cq), k_drop_w(global_Cp)), min_a)), + k_sqdist(k_transl(k_drop_w(global_Cp), scaled_vec(k_diff_pts(k_drop_w(global_Cq), k_drop_w(global_Cp)), min_a)), pt_p)); + INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(C)); + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) + { + FT neighbor_sqdist = nn_it->second; + + //std::cerr << nn_it->first << " : " << neighbor_sqdist << " / "; // CJTODO TEMP + + // When we're sure we got all the potential points, break + if (neighbor_sqdist > k_weight(C) + m_sq_half_sparsity) + break; + + std::size_t neighbor_point_idx = nn_it->first; + FT point_to_C_power_sqdist = + k_power_dist(C, compute_perturbed_weighted_point(neighbor_point_idx)); + //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP + // If the point is ACTUALLY "inside" S + if (point_to_C_power_sqdist <= FT(-0.000001) + && inconsistent_simplex.find(neighbor_point_idx) == + inconsistent_simplex.end()) + { + std::cerr << "Warning: " << neighbor_point_idx << " is inside C with power dist " << point_to_C_power_sqdist << "\n"; + } + } + }*/ + // /CJTODO ==================== + } + else + { + inside_point_idx = *inside_pt_indices.begin(); + } + //------------------------------------------------------------------------- - //6. Conserver le point ti tel que dist(cp, ci) soit la plus petite - //------------------------------------------------------------------------- - - //------------------------------------------------------------------------- - //7. Créer un k+1-simplex (inconsistent_simplex, ti) + //7. Create a k+1-simplex (inconsistent_simplex, ti) //------------------------------------------------------------------------- std::set new_simplex = inconsistent_simplex; new_simplex.insert(inside_point_idx); @@ -1967,6 +2142,7 @@ private: // Test and solve inconsistencies of a simplex. // Returns true if some inconsistencies were found. + // Precondition: incident_simplex is in the star of m_points[tr_index] bool check_and_solve_inconsistencies_by_adding_higher_dim_simplices( std::size_t tr_index, const std::set &incident_simplex) { @@ -1981,10 +2157,10 @@ private: simplex.insert(tr_index); // Check if the simplex is in the stars of all its vertices - std::set::const_iterator it_point_idx = simplex.begin(); + std::set::const_iterator it_point_idx = incident_simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p // and we check if "simplex" is among them - for ( ; it_point_idx != simplex.end() ; ++it_point_idx) + for ( ; it_point_idx != incident_simplex.end() ; ++it_point_idx) { std::size_t point_idx = *it_point_idx; @@ -1994,20 +2170,7 @@ private: Incident_simplex ic_to_find = simplex; ic_to_find.erase(point_idx); - // For each cell - bool found = false; - Star::const_iterator it_inc_simplex = star.begin(); - Star::const_iterator it_inc_simplex_end = star.end(); - for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) - { - if (*it_inc_simplex == ic_to_find) - { - found = true; - break; - } - } - - if (!found) + if (std::find(star.begin(), star.end(), ic_to_find) == star.end()) { solve_inconsistency_by_adding_higher_dimensional_simplices( tr_index, *it_point_idx, simplex); From cd4d1a3fa80fec425158285aff8cd5ea86f71c58 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 16:02:46 +0100 Subject: [PATCH 151/269] Added timers --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index b8f795ceea5..a82f0cb1caf 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -225,16 +225,18 @@ void make_tc(std::vector &points, int intrinsic_dim, export_after_fix_time = t.elapsed(); t.reset(); } + t.reset(); // Try to solve the remaining inconstencies tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + double fix2_time = t.elapsed(); t.reset(); TC::Simplicial_complex complex; int max_dim = tc.export_TC(complex, false); std::set > not_delaunay_simplices; - if (ambient_dim <= 4) + /*if (ambient_dim <= 4) { tc.check_if_all_simplices_are_in_the_ambient_delaunay( &complex, true, ¬_delaunay_simplices); - } + }*/ double export_after_fix2_time = -1.; if (intrinsic_dim <= 3) @@ -277,6 +279,7 @@ void make_tc(std::vector &points, int intrinsic_dim, << " * Fix inconsistencies: " << fix_time << " (" << num_fix_steps << " steps) ==> " << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl + << " * Fix 2: " << fix2_time << std::endl << " * Export to OFF (after fix): " << export_after_fix_time << std::endl << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl << " * Export to OFF (after collapse): " From c3a7c297629c94bd7be6046ac1378b3d9df1073c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 16:17:38 +0100 Subject: [PATCH 152/269] Updated script + config file --- .../Tangential_complex/benchmark_script.txt | 28 ++++++++++++------- .../include/CGAL/Tangential_complex/config.h | 4 +-- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index ffcaec285e8..17d30966cbe 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -3,21 +3,29 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- #---------------------------------------------------------- Very small cases for Debug mode ------------------------------------------------------------- -#generate_sphere_d 3 - - 20 3 2 0.05 3000 1 -#generate_klein_bottle_4D 4 3 - 20 4 2 1.5 3000 1 +#generate_sphere_d 3 - - 20 3 2 0.05 1 1 +#generate_klein_bottle_4D 4 3 - 70 4 2 1.5 1 1 #------------------------------------------------------------------ From files --------------------------------------------------------------------------- #data/SO3_50000.txt - - - 0 9 3 0.2 3000 1 -data/SO3_10000.txt - - - 0 9 3 0.05 3000 1 +#data/SO3_10000.txt - - - 0 9 3 0.05 10 1 #data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 3000 1 #data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 3000 1 #data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 3000 1 -#data/Cy8.txt - - - 0 24 2 0.1 3000 1 +#data/Cy8.txt - - - 0 24 2 0.1 2 1 #data/Kl.txt - - - 0 5 2 0.05 3000 1 #data/S3.txt - - - 0 4 3 0.05 3000 1 -#data/buddha_100kv.txt - - - 0 3 2 0.005 3000 1 -#data/fandisk.txt - - - 0 3 2 0.01 3000 1 -#data/fertility.txt - - - 0 3 2 0.1 600 1 + +#---------------------------------------------------------------------- 3D meshes ------------------------------------------------------------------------ +#data/buddha_100kv.txt - - - 0 3 2 0.005 10 1 +data/fandisk.txt - - - 0 3 2 0.01 100 1 +#data/fertility.txt - - - 0 3 2 0.4 120 1 +#data/bunny.txt - - - 0 3 2 0.5 5 1 +#data/blob.txt - - - 0 3 2 0.01 10 1 +#data/3holes.txt - - - 0 3 2 0.01 10 1 +#data/785_hand_2500v.txt - - - 0 3 2 0.01 10 1 +#data/785_hand_50kv.txt - - - 0 3 2 0.01 10 1 +#data/bumpy_sphere.txt - - - 0 3 2 0.01 10 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ #generate_sphere_d 3 - - 4 3 2 0.05 3000 1 @@ -26,9 +34,9 @@ data/SO3_10000.txt - - - 0 9 3 0.05 3000 1 #generate_sphere_d 3 - - 30000 4 3 0.05 3000 1 #generate_plane - - - 30000 3 2 0.005 3000 1 #generate_moment_curve 0 1 - 30000 6 1 0.005 3000 1 -#generate_klein_bottle_4D 4 3 - 10000 4 2 1.5 3000 1 +#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 10 1 #generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 3000 1 #----------------------------------------------------------- Performance testing ------------------------------------------------------------------------- -# TC: 5.55 / 1st fix step : 2.7 -data/fertility.txt - - - 0 3 2 0.1 600 1 \ No newline at end of file +# TC: 5.55 / 1st fix step : 0.2 +#data/fertility.txt - - - 0 3 2 0.1 10 1 \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 47bf0147c91..f9339340dbe 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -58,10 +58,10 @@ // 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 # define CGAL_TC_PERTURB_POSITION_TANGENTIAL // default //# define CGAL_TC_PERTURB_POSITION_GLOBAL -#define CGAL_TC_PERTURB_WEIGHT +//#define CGAL_TC_PERTURB_WEIGHT //#define CGAL_TC_PERTURB_TANGENT_SPACE //========================= Parameters ======================================== From 7357337195097f820f64505e8c8fad827ee9b79b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 3 Mar 2015 16:41:46 +0100 Subject: [PATCH 153/269] Added a TODO --- Tangential_complex/include/CGAL/Tangential_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 53d557d4d73..bff9c3e3b06 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1998,7 +1998,7 @@ private: { inside_pt_indices.push_back(neighbor_point_idx); } - // CJTODO TEMP: + // CJTODO: use this instead of point_to_Cq_power_sqdist? /*{ typename Tr_traits::Power_test_d side = q_tr_traits.power_test_d_object(); typename Tr_traits::Orientation_d orient = q_tr_traits.orientation_d_object(); From 16279ad6312a4bec51f554a880f2fa5a7cae5f33 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Mar 2015 15:43:22 +0100 Subject: [PATCH 154/269] Refined margin computation + Use Power_center_d and Power_distance_d --- .../include/CGAL/Tangential_complex.h | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index bff9c3e3b06..e307fa4c72b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -636,7 +636,7 @@ public: void check_and_solve_inconsistencies_by_adding_higher_dim_simplices() { - // CJTODO: parallel_for + // CJTODO: parallel_for??? for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) { bool inconsistencies_found; @@ -966,9 +966,8 @@ private: // Triangulation's traits functor & objects typename Tr_traits::Point_weight_d point_weight = local_tr_traits.point_weight_d_object(); - /*typename Tr_traits::Power_center_d power_center = - local_tr_traits.power_center_d_object();*/ // CJTODO - typename Get_functor::type power_center(local_tr_traits); + typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object(); // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions @@ -1098,11 +1097,17 @@ private: } // Let's add the margin, now + // The value depends on whether we perturb weight or position if (squared_star_sphere_radius_plus_margin) { +#ifdef CGAL_TC_PERTURB_WEIGHT + squared_star_sphere_radius_plus_margin = + *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; +#else squared_star_sphere_radius_plus_margin = CGAL::square( CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2*m_half_sparsity); +#endif } } } @@ -1700,9 +1705,8 @@ private: local_tr_traits)); } - //typename Tr_traits::Power_center_d power_center = - // local_tr_traits.power_center_d_object(); // CJTODO - typename Get_functor::type power_center(local_tr_traits); + typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object(); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); @@ -1880,14 +1884,12 @@ private: m_k.scalar_product_d_object(); typename Kernel::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); - //typename Kernel::Power_distance_d k_power_dist = - // m_k.power_distance_d_object(); // CJTODO - typename Get_functor::type k_power_dist(m_k); + typename Kernel::Power_distance_d k_power_dist = + m_k.power_distance_d_object(); const Tr_traits &q_tr_traits = m_triangulations[q_idx].tr().geom_traits(); - /*typename Tr_traits::Power_center_d power_center = - local_tr_traits.power_center_d_object();*/ // CJTODO - typename Get_functor::type tr_power_center(q_tr_traits); + typename Tr_traits::Power_center_d tr_power_center = + q_tr_traits.power_center_d_object(); typename Tr_traits::Point_weight_d tr_point_weight = q_tr_traits.point_weight_d_object(); From 8ad1b81323ceeadb0c3eab7804cb3b0e1e452b87 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 4 Mar 2015 16:54:23 +0100 Subject: [PATCH 155/269] Now taking weights into account for the computation of "min_a" --- .../include/CGAL/Tangential_complex.h | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index e307fa4c72b..d1f83fcb601 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1933,8 +1933,13 @@ private: FT circumsphere_sqradius_p = tr_point_weight(Cp); FT circumsphere_sqradius_q = tr_point_weight(Cq); +#ifdef CGAL_TC_PERTURB_WEIGHT + FT squared_circumsphere_radius_q_plus_margin = + circumsphere_sqradius_q + 4*m_sq_half_sparsity; +#else FT squared_circumsphere_radius_q_plus_margin = CGAL::square( CGAL::sqrt(circumsphere_sqradius_q) + 2*m_half_sparsity); +#endif Weighted_point global_Cp = k_constr_wp( unproject_point(Cp, pt_p, m_tangent_spaces[p_idx], q_tr_traits), @@ -2053,7 +2058,6 @@ private: //------------------------------------------------------------------------- //4. If there's more than one ti... or not //------------------------------------------------------------------------- - // CJTODO: take weights into account std::size_t inside_point_idx; if (inside_pt_indices.size() > 1) { @@ -2073,9 +2077,20 @@ private: const Point ti = compute_perturbed_point(idx); const Point &cp = k_drop_w(global_Cp); const Point &cq = k_drop_w(global_Cq); + +#ifdef CGAL_TC_PERTURB_WEIGHT + const Weighted_point ti_w = compute_perturbed_weighted_point(idx); + const Weighted_point p_w = compute_perturbed_weighted_point(p_idx); + const Weighted_point cp_w0 = k_constr_wp(k_drop_w(global_Cp), FT(0)); + const Weighted_point wp_w0 = k_constr_wp(k_drop_w(global_Cq), FT(0)); + FT a = + (k_power_dist(cp_w0, ti_w) - k_power_dist(cp_w0, p_w)) / + (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); +#else FT a = (k_sqdist(cp, ti) - k_sqdist(cp, pt_p)) / (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); +#endif if (a < min_a) { From 20f871174017420d530ec38a984292cbbb97ebc7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 9 Mar 2015 14:49:12 +0100 Subject: [PATCH 156/269] Remove useless function call --- Tangential_complex/include/CGAL/Tangential_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d1f83fcb601..42e1ea34b27 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -795,7 +795,7 @@ public: { Simplex simplex; for (int i = 0 ; i < dim + 1 ; ++i) - simplex.insert(cit.base()->vertex(combi[i])->data()); + simplex.insert(cit->vertex(combi[i])->data()); amb_dt_simplices.insert(simplex); } From 742b9d45e2bf43ef6ca2df80be91732d45bafa4f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 13 Mar 2015 11:07:26 +0100 Subject: [PATCH 157/269] Clarify comment --- .../include/CGAL/Tangential_complex/Simplicial_complex.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 445864ceb67..3e304742f64 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -74,10 +74,10 @@ public: } // For each non-maximal k-face F, if F has only one maximal coface Cf: - // - Look for the other k-faces F2 of Cf in the map and: + // - 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 was create troubles with the iterators) and add f2 - // to the complex + // 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(), From 672f3ac0c1f907a853f65b4dc591fd52013c061f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 13 Mar 2015 17:09:46 +0100 Subject: [PATCH 158/269] Bug fix: go one step further in the recursive call --- .../include/CGAL/Tangential_complex/Simplicial_complex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 3e304742f64..3ef449dfa9c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -95,6 +95,7 @@ public: 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); @@ -119,7 +120,7 @@ public: } // Collapse the lower dimension simplices - if (k > 1) + if (k > 0) collapse(max_simplex_dim - 1); } From d23a39c740fa3defed525eb4f142916b367f7419 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Mar 2015 18:04:50 +0100 Subject: [PATCH 159/269] Added SC::is_pure_manifold --- .../Tangential_complex/benchmark_tc.cpp | 32 ++++++--- .../Tangential_complex/Simplicial_complex.h | 66 ++++++++++++++----- 2 files changed, 72 insertions(+), 26 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index a82f0cb1caf..308d3e950ad 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -91,9 +91,12 @@ protected: subelements.push_back("Final_num_inconsistent_local_tr"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); - subelements.push_back("Fix_successful"); - subelements.push_back("Fix_time"); - subelements.push_back("Fix_steps"); + subelements.push_back("Fix1_successful"); + subelements.push_back("Fix1_time"); + subelements.push_back("Fix1_steps"); + subelements.push_back("Fix2_pure_manifold"); + subelements.push_back("Fix2_num_wrong_number_of_cofaces"); + subelements.push_back("Fix2_time"); subelements.push_back("Info"); return subelements; @@ -264,22 +267,26 @@ void make_tc(std::vector &points, int intrinsic_dim, tc.export_to_off(complex, off_stream); export_after_collapse_time = t.elapsed(); t.reset(); } - + std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces; + bool pure_manifold = complex.is_pure_manifold( + intrinsic_dim, false, 0, + &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); complex.display_stats(); std::cerr << std::endl << "================================================" << std::endl << "Number of vertices: " << tc.number_of_vertices() << std::endl + << "Pure manifold: " << (pure_manifold ? "YES" : "NO") << 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 + << " * Fix inconsistencies 1: " << fix_time << " (" << num_fix_steps << " steps) ==> " << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl - << " * Fix 2: " << fix2_time << std::endl + << " * Fix inconsistencies 2: " << fix2_time << std::endl << " * Export to OFF (after fix): " << export_after_fix_time << std::endl << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl << " * Export to OFF (after collapse): " @@ -289,10 +296,15 @@ void make_tc(std::vector &points, int intrinsic_dim, CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); - CGAL_TC_SET_PERFORMANCE_DATA("Fix_successful", - (fix_ret == CGAL::TC_FIXED ? "Y" : "N")); - CGAL_TC_SET_PERFORMANCE_DATA("Fix_time", fix_time); - CGAL_TC_SET_PERFORMANCE_DATA("Fix_steps", num_fix_steps); + CGAL_TC_SET_PERFORMANCE_DATA("Fix1_successful", + (fix_ret == CGAL::TC_FIXED ? "Y" : "N")); + CGAL_TC_SET_PERFORMANCE_DATA("Fix1_time", fix_time); + CGAL_TC_SET_PERFORMANCE_DATA("Fix1_steps", num_fix_steps); + CGAL_TC_SET_PERFORMANCE_DATA("Fix2_pure_manifold", + (pure_manifold ? "Y" : "N")); + CGAL_TC_SET_PERFORMANCE_DATA("Fix2_num_wrong_number_of_cofaces", + num_wrong_number_of_cofaces); + CGAL_TC_SET_PERFORMANCE_DATA("Fix2_time", fix2_time); CGAL_TC_SET_PERFORMANCE_DATA("Info", ""); } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 3ef449dfa9c..e386739020f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -160,14 +160,19 @@ public: std::cerr << "==========================================================\n"; } - // CJTODO: this is only based on the fact that each edge should have two - // cofaces - bool is_manifold(bool exit_at_the_first_problem = true) + // verbose_level = 0, 1 or 2 + bool is_pure_manifold(int simplex_dim, + 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) { - typedef std::set Edge; - typedef std::map Cofaces_map; + typedef std::set K_1_face; + typedef std::map Cofaces_map; - // Counts the number of cofaces of each edge + std::size_t num_wrong_dim_simplices = 0, 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 @@ -177,19 +182,26 @@ public: it_simplex != it_simplex_end ; ++it_simplex) { - if (it_simplex->size() > 2) + if (it_simplex->size() != simplex_dim + 1) { - std::vector edges; - // Get the k-faces composing the simplex - combinations(*it_simplex, 2, std::back_inserter(edges)); - for (const auto &edge : edges) // CJTODO C++1 + if (verbose_level >= 2) + std::cerr << "Found a simplex with dim = " + << it_simplex->size() - 1 << std::endl; + ++num_wrong_dim_simplices; + } + else + { + std::vector 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[edge]; + ++cofaces_map[k_1_face]; } } } - bool manifold = true; for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(), it_map_end = cofaces_map.end() ; it_map_elt != it_map_end ; @@ -197,15 +209,37 @@ public: { if (it_map_elt->second != 2) { - std::cerr << "Found an edge with " << it_map_elt->second << " cofaces\n"; + 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 - manifold = false; + ++num_wrong_number_of_cofaces; } } - return manifold; + bool ret = num_wrong_dim_simplices == 0 && num_wrong_number_of_cofaces == 0; + + if (verbose_level >= 1) + { + std::cerr << "is_pure_manifold: " << (ret ? "YES" : "NO") << std::endl; + if (!ret) + { + std::cerr << " * Number of wrong dimension simplices: " + << num_wrong_dim_simplices << std::endl + << " * Number of wrong number of cofaces: " + << num_wrong_number_of_cofaces << std::endl; + } + } + + 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; } private: From cbc108171b7224576e56dfa93b661b3af20f9ed9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Mar 2015 18:05:10 +0100 Subject: [PATCH 160/269] Updated script and config --- .../Tangential_complex/benchmark_script.txt | 40 +++++++++---------- .../include/CGAL/Tangential_complex/config.h | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 17d30966cbe..0aa065fd7a8 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -3,29 +3,29 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- #---------------------------------------------------------- Very small cases for Debug mode ------------------------------------------------------------- -#generate_sphere_d 3 - - 20 3 2 0.05 1 1 -#generate_klein_bottle_4D 4 3 - 70 4 2 1.5 1 1 +#generate_sphere_d 3 - - 20 3 2 0.05 60 1 +#generate_klein_bottle_4D 4 3 - 70 4 2 1.5 60 1 #------------------------------------------------------------------ From files --------------------------------------------------------------------------- -#data/SO3_50000.txt - - - 0 9 3 0.2 3000 1 -#data/SO3_10000.txt - - - 0 9 3 0.05 10 1 +data/SO3_50000.txt - - - 0 9 3 0.2 60 1 +data/SO3_10000.txt - - - 0 9 3 0.05 60 1 #data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 3000 1 #data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 3000 1 #data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 3000 1 -#data/Cy8.txt - - - 0 24 2 0.1 2 1 -#data/Kl.txt - - - 0 5 2 0.05 3000 1 -#data/S3.txt - - - 0 4 3 0.05 3000 1 +data/Cy8.txt - - - 0 24 2 0.1 60 1 +data/Kl.txt - - - 0 5 2 0.05 60 1 +data/S3.txt - - - 0 4 3 0.05 60 1 #---------------------------------------------------------------------- 3D meshes ------------------------------------------------------------------------ -#data/buddha_100kv.txt - - - 0 3 2 0.005 10 1 -data/fandisk.txt - - - 0 3 2 0.01 100 1 -#data/fertility.txt - - - 0 3 2 0.4 120 1 -#data/bunny.txt - - - 0 3 2 0.5 5 1 -#data/blob.txt - - - 0 3 2 0.01 10 1 -#data/3holes.txt - - - 0 3 2 0.01 10 1 -#data/785_hand_2500v.txt - - - 0 3 2 0.01 10 1 -#data/785_hand_50kv.txt - - - 0 3 2 0.01 10 1 -#data/bumpy_sphere.txt - - - 0 3 2 0.01 10 1 +data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 +data/fandisk.txt - - - 0 3 2 0.01 60 1 +data/fertility.txt - - - 0 3 2 0.4 60 1 +data/bunny.txt - - - 0 3 2 0.5 60 1 +data/blob.txt - - - 0 3 2 0.01 60 1 +data/3holes.txt - - - 0 3 2 0.01 60 1 +data/785_hand_2500v.txt - - - 0 3 2 0.01 60 1 +data/785_hand_50kv.txt - - - 0 3 2 0.01 60 1 +data/bumpy_sphere.txt - - - 0 3 2 0.01 60 1 #----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ #generate_sphere_d 3 - - 4 3 2 0.05 3000 1 @@ -33,10 +33,10 @@ data/fandisk.txt - - - 0 3 2 0.01 100 1 #generate_sphere_d 3 - - 30000 3 2 0.005 3000 1 #generate_sphere_d 3 - - 30000 4 3 0.05 3000 1 #generate_plane - - - 30000 3 2 0.005 3000 1 -#generate_moment_curve 0 1 - 30000 6 1 0.005 3000 1 -#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 10 1 -#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 3000 1 +generate_moment_curve 0 1 - 30000 6 1 0.005 60 1 +generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 60 1 +generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 #----------------------------------------------------------- Performance testing ------------------------------------------------------------------------- # TC: 5.55 / 1st fix step : 0.2 -#data/fertility.txt - - - 0 3 2 0.1 10 1 \ No newline at end of file +#data/fertility.txt - - - 0 3 2 0.1 100 1 \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index f9339340dbe..1ba33d4eead 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -41,7 +41,7 @@ //#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 k + 1 + CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS closest points +#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 From a9c14b20091f504618e08db06959b287ed25f45f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 13 Apr 2015 16:42:23 +0200 Subject: [PATCH 161/269] Added normalize_vector --- .../CGAL/Tangential_complex/utilities.h | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index a15c38f13f8..64e8c4ddfc2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -113,22 +113,33 @@ namespace Tangential_complex_ { } };*/ + + + template + std::vector + normalize_vector( + std::vector &v, + K const& k) + { + v = k.scaled_vector_d_object()( + v, FT(1)/CGAL::sqrt(k.squared_length_d_object()(v))); + } template std::vector compute_gram_schmidt_basis( std::vector const& input_basis, - K const& kernel) + K const& k) { typedef typename K::FT FT; typedef typename K::Vector_d Vector; typedef std::vector Basis; // Kernel functors - typename K::Squared_length_d sqlen = kernel.squared_length_d_object(); - typename K::Scaled_vector_d scaled_vec = kernel.scaled_vector_d_object(); - typename K::Scalar_product_d inner_pdct = kernel.scalar_product_d_object(); - typename K::Difference_of_vectors_d diff_vec = kernel.difference_of_vectors_d_object(); + typename K::Squared_length_d sqlen = k.squared_length_d_object(); + typename K::Scaled_vector_d scaled_vec = k.scaled_vector_d_object(); + typename K::Scalar_product_d inner_pdct = k.scalar_product_d_object(); + typename K::Difference_of_vectors_d diff_vec = k.difference_of_vectors_d_object(); Basis output_basis; @@ -146,8 +157,7 @@ namespace Tangential_complex_ { u = diff_vec(u, u_proj); } - output_basis.push_back( - scaled_vec(u, FT(1)/CGAL::sqrt(sqlen(u)))); + output_basis.push_back(normalize_vector(u, k)); } return output_basis; From d1a1ec164de7d7ecbfe4ac41673a59bbd2ea87ef Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 13 Apr 2015 16:45:46 +0200 Subject: [PATCH 162/269] Added the ability to compute the orthogonal space basis --- .../include/CGAL/Tangential_complex.h | 113 +++++++++++------- 1 file changed, 73 insertions(+), 40 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 42e1ea34b27..ce7b916a950 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -68,6 +68,7 @@ //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) + namespace CGAL { using namespace Tangential_complex_; @@ -124,6 +125,7 @@ class Tangential_complex typedef typename Tr_traits::Vector_d Tr_vector; typedef std::vector Tangent_space_basis; + typedef std::vector Orthogonal_space_basis; typedef std::vector Points; typedef std::vector Weights; @@ -180,20 +182,21 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; - typedef typename std::vector TS_container; - typedef typename std::vector Tr_container; - typedef typename std::vector Vectors; + typedef typename std::vector TS_container; + typedef typename std::vector OS_container; + typedef typename std::vector Tr_container; + typedef typename std::vector Vectors; // An Incident_simplex is the list of the verter indices // except the center vertex - typedef std::set Incident_simplex; - typedef std::vector Star; - typedef std::vector Stars_container; + typedef std::set Incident_simplex; + typedef std::vector Star; + typedef std::vector Stars_container; #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - //typedef tbb::queuing_mutex Tr_mutex; + //typedef tbb::queuing_mutex Tr_mutex; #endif // For transform_iterator @@ -261,6 +264,9 @@ public: //m_tr_mutexes.resize(m_points.size()); #endif m_tangent_spaces.resize(m_points.size()); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_orth_spaces.resize(m_points.size()); +#endif #ifdef CGAL_TC_PERTURB_WEIGHT m_weights.resize(m_points.size(), FT(0)); #endif @@ -275,10 +281,6 @@ public: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE m_perturb_tangent_space.resize(m_points.size(), false); #endif -#ifdef CGAL_TC_EXPORT_NORMALS - m_normals.resize(m_points.size(), - m_k.construct_vector_d_object()(m_ambiant_dim)); -#endif #ifdef CGAL_LINKED_WITH_TBB // Parallel @@ -976,8 +978,9 @@ private: // Estimate the tangent space if (!tangent_spaces_are_already_computed) { -#ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i]); #else m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif @@ -985,10 +988,11 @@ private: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { -#ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt,&m_normals[i],true); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt, true); + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); #endif m_perturb_tangent_space[i] = false; } @@ -1151,14 +1155,14 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } - Tangent_space_basis compute_tangent_space(const Point &p -#ifdef CGAL_TC_EXPORT_NORMALS - , Vector *p_normal -#endif + Tangent_space_basis compute_tangent_space( + const Point &p + , bool normalize_basis = true + , Orthogonal_space_basis *p_orth_space_basis = NULL #ifdef CGAL_TC_PERTURB_TANGENT_SPACE - , bool perturb = false + , bool perturb = false #endif - ) const + ) const { //******************************* PCA ************************************* @@ -1216,17 +1220,44 @@ private: i >= m_ambiant_dim - m_intrinsic_dimension ; --i) { - ts.push_back(constr_vec( - m_ambiant_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim)); + if (normalize_basis) + { + ts.push_back(normalize_vector(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim))); + } + else + { + ts.push_back(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim)); + } + } + + if (p_orth_space_basis) + { + for (int i = m_ambiant_dim - m_intrinsic_dimension - 1 ; + i >= 0 ; + --i) + { + if (normalize_basis) + { + p_orth_space_basis->push_back(normalize_vector(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim))); + } + else + { + p_orth_space_basis->push_back(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim)); + } + } } -#ifdef CGAL_TC_EXPORT_NORMALS - *p_normal = constr_vec( - m_ambiant_dim, - eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data(), - eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data() + m_ambiant_dim); -#endif //************************************************************************* @@ -1234,7 +1265,9 @@ private: //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; - return compute_gram_schmidt_basis(ts, m_k); + // CJTODO: les vecteurs sont déjŕ orthogonaux, a priori ! A VERIFIER au cas oů + //return compute_gram_schmidt_basis(ts, m_k); + return ts; // CJTODO: this is only for a sphere in R^3 @@ -1795,7 +1828,7 @@ private: int num_coords = min(ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS - Vectors::const_iterator it_n = m_normals.begin(); + OS_container::const_iterator it_os = m_orth_spaces.begin(); #endif typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -1813,12 +1846,12 @@ private: #ifdef CGAL_TC_EXPORT_NORMALS for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double(coord(*it_n, i)); + os << " " << CGAL::to_double(coord(*it_os->begin(), i)); #endif os << std::endl; } #ifdef CGAL_TC_EXPORT_NORMALS - ++it_n; + ++it_os; #endif } @@ -2219,7 +2252,7 @@ private: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - if (tr.current_dimension() < m_intrinsic_dimension) + if (&tr == NULL || tr.current_dimension() < m_intrinsic_dimension) continue; // Color for this star @@ -2502,15 +2535,15 @@ private: Points_ds m_points_ds; TS_container m_tangent_spaces; +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + OS_container m_orth_spaces; +#endif Tr_container m_triangulations; // Contains the triangulations // and their center vertex Stars_container m_stars; #ifdef CGAL_LINKED_WITH_TBB //std::vector m_tr_mutexes; #endif -#ifdef CGAL_TC_EXPORT_NORMALS - Vectors m_normals; -#endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM Points m_points_for_tse; From d40325bae4910607a2374c92c6a1b1cbea824188 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 13 Apr 2015 16:45:46 +0200 Subject: [PATCH 163/269] Added the ability to compute the orthogonal space basis --- .../include/CGAL/Tangential_complex.h | 119 ++++++++++++------ .../CGAL/Tangential_complex/utilities.h | 8 +- 2 files changed, 83 insertions(+), 44 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 42e1ea34b27..8d63b68f583 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -124,6 +124,7 @@ class Tangential_complex typedef typename Tr_traits::Vector_d Tr_vector; typedef std::vector Tangent_space_basis; + typedef std::vector Orthogonal_space_basis; typedef std::vector Points; typedef std::vector Weights; @@ -180,20 +181,21 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; - typedef typename std::vector TS_container; - typedef typename std::vector Tr_container; - typedef typename std::vector Vectors; + typedef typename std::vector TS_container; + typedef typename std::vector OS_container; + typedef typename std::vector Tr_container; + typedef typename std::vector Vectors; // An Incident_simplex is the list of the verter indices // except the center vertex - typedef std::set Incident_simplex; - typedef std::vector Star; - typedef std::vector Stars_container; + typedef std::set Incident_simplex; + typedef std::vector Star; + typedef std::vector Stars_container; #ifdef CGAL_LINKED_WITH_TBB // CJTODO: test other mutexes // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - //typedef tbb::queuing_mutex Tr_mutex; + //typedef tbb::queuing_mutex Tr_mutex; #endif // For transform_iterator @@ -201,6 +203,11 @@ class Tangential_complex { return vh->point(); } + template + static const P &vertex_handle_to_point(VH vh) + { + return vh->point(); + } public: @@ -261,6 +268,9 @@ public: //m_tr_mutexes.resize(m_points.size()); #endif m_tangent_spaces.resize(m_points.size()); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_orth_spaces.resize(m_points.size()); +#endif #ifdef CGAL_TC_PERTURB_WEIGHT m_weights.resize(m_points.size(), FT(0)); #endif @@ -275,10 +285,6 @@ public: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE m_perturb_tangent_space.resize(m_points.size(), false); #endif -#ifdef CGAL_TC_EXPORT_NORMALS - m_normals.resize(m_points.size(), - m_k.construct_vector_d_object()(m_ambiant_dim)); -#endif #ifdef CGAL_LINKED_WITH_TBB // Parallel @@ -976,8 +982,9 @@ private: // Estimate the tangent space if (!tangent_spaces_are_already_computed) { -#ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt, &m_normals[i]); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i]); #else m_tangent_spaces[i] = compute_tangent_space(center_pt); #endif @@ -985,10 +992,11 @@ private: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { -#ifdef CGAL_TC_EXPORT_NORMALS - m_tangent_spaces[i] = compute_tangent_space(center_pt,&m_normals[i],true); +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt, true); + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); #endif m_perturb_tangent_space[i] = false; } @@ -1151,14 +1159,14 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } - Tangent_space_basis compute_tangent_space(const Point &p -#ifdef CGAL_TC_EXPORT_NORMALS - , Vector *p_normal -#endif + Tangent_space_basis compute_tangent_space( + const Point &p + , bool normalize_basis = true + , Orthogonal_space_basis *p_orth_space_basis = NULL #ifdef CGAL_TC_PERTURB_TANGENT_SPACE - , bool perturb = false + , bool perturb = false #endif - ) const + ) const { //******************************* PCA ************************************* @@ -1216,17 +1224,48 @@ private: i >= m_ambiant_dim - m_intrinsic_dimension ; --i) { - ts.push_back(constr_vec( - m_ambiant_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim)); + if (normalize_basis) + { + ts.push_back(normalize_vector( + constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim), + m_k)); + } + else + { + ts.push_back(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim)); + } + } + + if (p_orth_space_basis) + { + for (int i = m_ambiant_dim - m_intrinsic_dimension - 1 ; + i >= 0 ; + --i) + { + if (normalize_basis) + { + p_orth_space_basis->push_back(normalize_vector( + constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim), + m_k)); + } + else + { + p_orth_space_basis->push_back(constr_vec( + m_ambiant_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambiant_dim)); + } + } } -#ifdef CGAL_TC_EXPORT_NORMALS - *p_normal = constr_vec( - m_ambiant_dim, - eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data(), - eig.eigenvectors().col(m_ambiant_dim - m_intrinsic_dimension - 1).data() + m_ambiant_dim); -#endif //************************************************************************* @@ -1234,7 +1273,7 @@ private: //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; - return compute_gram_schmidt_basis(ts, m_k); + return ts; // CJTODO: this is only for a sphere in R^3 @@ -1795,7 +1834,7 @@ private: int num_coords = min(ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS - Vectors::const_iterator it_n = m_normals.begin(); + OS_container::const_iterator it_os = m_orth_spaces.begin(); #endif typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -1813,12 +1852,12 @@ private: #ifdef CGAL_TC_EXPORT_NORMALS for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double(coord(*it_n, i)); + os << " " << CGAL::to_double(coord(*it_os->begin(), i)); #endif os << std::endl; } #ifdef CGAL_TC_EXPORT_NORMALS - ++it_n; + ++it_os; #endif } @@ -2219,7 +2258,7 @@ private: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - if (tr.current_dimension() < m_intrinsic_dimension) + if (&tr == NULL || tr.current_dimension() < m_intrinsic_dimension) continue; // Color for this star @@ -2502,15 +2541,15 @@ private: Points_ds m_points_ds; TS_container m_tangent_spaces; +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + OS_container m_orth_spaces; +#endif Tr_container m_triangulations; // Contains the triangulations // and their center vertex Stars_container m_stars; #ifdef CGAL_LINKED_WITH_TBB //std::vector m_tr_mutexes; #endif -#ifdef CGAL_TC_EXPORT_NORMALS - Vectors m_normals; -#endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM Points m_points_for_tse; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 64e8c4ddfc2..33fcad37772 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -113,16 +113,16 @@ namespace Tangential_complex_ { } };*/ - - + // Modifies v in-place template - std::vector + typename K::Vector_d & normalize_vector( - std::vector &v, + typename K::Vector_d &v, K const& k) { v = k.scaled_vector_d_object()( v, FT(1)/CGAL::sqrt(k.squared_length_d_object()(v))); + return v; } template From 2fb396cadd292aabb38cc4910f2effff4b405e9d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Apr 2015 20:10:27 +0200 Subject: [PATCH 164/269] Function does_voronoi_face_and_alpha_tangent_subspace_intersect --- .../CGAL/Tangential_complex/utilities.h | 153 +++++++++++++++++- 1 file changed, 152 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 33fcad37772..ab8048adcb4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -23,12 +23,30 @@ #include #include +#include +#include +#include + +#include +#include #include #include #include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) +// choose exact integral type for QP solver +#ifdef CGAL_USE_GMP +# include + typedef CGAL::Gmpzf ET; +#else +# include + typedef CGAL::MP_Float ET; +#endif +//#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 + + + namespace CGAL { namespace Tangential_complex_ { @@ -168,7 +186,7 @@ namespace Tangential_complex_ { // Output_iterator::value_type must be std::set > template void combinations(const Elements_container elements, int k, - Output_iterator combinations) + Output_iterator combinations) { std::size_t n = elements.size(); std::vector booleans(n, false); @@ -187,6 +205,139 @@ namespace Tangential_complex_ { } while (std::next_permutation(booleans.begin(), booleans.end())); } + // P: dual face in Delaunay triangulation (p0, p1,… pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_alpha_tangent_subspace_intersect( + Point const& center_pt, + Point_range const& P, + Point_range const& Q, + Vector_range const& orthogonal_subspace_basis, + typename K::FT alpha, + K const& k) + { + // Notations: + // Fv: Voronoi k-face + // Fd: dual, (D-k)-face of Delaunay (p0, p1,… pn) + + typedef typename K::FT FT; + typedef typename K::Point_d Point; + typedef typename K::Vector_d Vector; + + typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); + typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); + + const int ambient_dim = k.point_dimension_d_object()(center_pt); + + std::size_t card_P = P.size(); + std::size_t card_Q = Q.size(); + std::size_t card_OSB = orthogonal_subspace_basis.size(); + std::size_t num_couples_among_P = card_P*(card_P-1)/2; + std::size_t num_equations = + 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; + + // Linear solver + typedef CGAL::Quadratic_program Linear_program; + typedef CGAL::Quadratic_program_solution LP_solution; + + Linear_program lp(CGAL::SMALLER, false); + int current_row = 0; + + //=========== First set of equations =========== + // For point pi in P + // 2(p0 - pi).x = p0˛ - pi˛ + Point const& p0 = center_pt; + FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); + for (Point_range::const_iterator it_p = P.begin(), it_p_end = P.end() ; + it_p != it_p_end ; ++it_p) + { + Point const& pi = *it_p; + + for (int k = 0 ; k < ambient_dim ; ++k) + lp.set_a(k, current_row, 2*(p0[k] - pi[k])); + + lp.set_b(current_row, + p0_dot_p0 - scalar_pdct(pt_to_vec(pi), pt_to_vec(pi))); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + // CJTODO: this code might be useful for Option 1 + /*CGAL::Combination_enumerator pi_pj(2, 0, static_cast(card_P)); + for ( ; !pi_pj.finished() ; ++pi_pj) + { + Point const& pi = P[pi_pj[0]]; + Point const& pj = P[pi_pj[1]]; + + for (int k = 0 ; k < ambient_dim ; ++k) + { + FT a = 2*(pi[k] + pj[k]); + lp.set_a(k, current_row , -a); + lp.set_a(k, current_row + 1, a); + } + + FT b = scalar_pdct(pi, pi) - scalar_pdct(pj, pj); + lp.set_b(current_row , -b); + lp.set_b(current_row + 1, b); + + current_row += 2; + }*/ + + //=========== Second set of equations =========== + // For each point qi in Q + // 2(qi - p0).x <= qi˛ - p0˛ + for (Point_range::const_iterator it_q = Q.begin(), it_q_end = Q.end() ; + it_q != it_q_end ; ++it_q) + { + Point const& qi = *it_q; + + for (int k = 0 ; k < ambient_dim ; ++k) + lp.set_a(k, current_row, 2*(qi[k] - p0[k])); + + lp.set_b(current_row, + scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)) - p0_dot_p0); + + ++current_row; + } + + //=========== Third set of equations =========== + // For each vector of OSB + // bi.x <= bi.p + alpha + // -bi.x <= -bi.p + alpha + for (Vector_range::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; + it_osb != it_osb_end ; ++it_osb) + { + Vector const& bi = *it_osb; + + for (int k = 0 ; k < ambient_dim ; ++k) + { + lp.set_a(k, current_row , bi[k]); + lp.set_a(k, current_row + 1, -bi[k]); + } + + FT bi_dot_p = scalar_pdct(bi, pt_to_vec(center_pt)); + lp.set_b(current_row , bi_dot_p + alpha); + lp.set_b(current_row + 1, -bi_dot_p + alpha); + + current_row += 2; + } + + //=========== Other LP parameters =========== + lp.set_c(0, 1); // Minimize x[0] + + //=========== Solve ========================= + LP_solution solution = CGAL::solve_linear_program(lp, ET()); + if (solution.solves_linear_program(lp)) + std::cout << solution; + else + std::cout << "ERROR\n"; + + return solution.solves_linear_program(lp); + } + } // namespace Tangential_complex_ } //namespace CGAL From bddbd463f0cea91c432328bff92214934e3f9305 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Apr 2015 15:59:55 +0200 Subject: [PATCH 165/269] Use indexed point ranges in does_blabla_intersect --- .../CGAL/Tangential_complex/utilities.h | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index ab8048adcb4..173b161d5b0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -36,13 +36,9 @@ // or tbb::atomic (works for doubles, but not officially) // choose exact integral type for QP solver -#ifdef CGAL_USE_GMP -# include - typedef CGAL::Gmpzf ET; -#else -# include - typedef CGAL::MP_Float ET; -#endif +// (Gmpzf is not thread-safe) +#include +typedef CGAL::MP_Float ET; //#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 @@ -207,11 +203,13 @@ namespace Tangential_complex_ { // P: dual face in Delaunay triangulation (p0, p1,… pn) // Q: vertices which are common neighbors of all vertices of P - template + template bool does_voronoi_face_and_alpha_tangent_subspace_intersect( - Point const& center_pt, - Point_range const& P, - Point_range const& Q, + Point_range const& all_points, + std::size_t center_pt_index, + Indexed_point_range const& P, + Indexed_point_range_2 const& Q, Vector_range const& orthogonal_subspace_basis, typename K::FT alpha, K const& k) @@ -227,6 +225,7 @@ namespace Tangential_complex_ { typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); + Point const& center_pt = all_points[center_pt_index]; const int ambient_dim = k.point_dimension_d_object()(center_pt); std::size_t card_P = P.size(); @@ -248,10 +247,11 @@ namespace Tangential_complex_ { // 2(p0 - pi).x = p0˛ - pi˛ Point const& p0 = center_pt; FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); - for (Point_range::const_iterator it_p = P.begin(), it_p_end = P.end() ; + for (Indexed_point_range::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { - Point const& pi = *it_p; + Point const& pi = all_points[*it_p]; for (int k = 0 ; k < ambient_dim ; ++k) lp.set_a(k, current_row, 2*(p0[k] - pi[k])); @@ -287,10 +287,11 @@ namespace Tangential_complex_ { //=========== Second set of equations =========== // For each point qi in Q // 2(qi - p0).x <= qi˛ - p0˛ - for (Point_range::const_iterator it_q = Q.begin(), it_q_end = Q.end() ; + for (Indexed_point_range_2::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; it_q != it_q_end ; ++it_q) { - Point const& qi = *it_q; + Point const& qi = all_points[*it_q]; for (int k = 0 ; k < ambient_dim ; ++k) lp.set_a(k, current_row, 2*(qi[k] - p0[k])); @@ -330,12 +331,9 @@ namespace Tangential_complex_ { //=========== Solve ========================= LP_solution solution = CGAL::solve_linear_program(lp, ET()); - if (solution.solves_linear_program(lp)) - std::cout << solution; - else - std::cout << "ERROR\n"; + bool ret = (solution.status() == CGAL::QP_OPTIMAL); - return solution.solves_linear_program(lp); + return ret; } } // namespace Tangential_complex_ From 609d71ac232b29cd9405f37b7f723473469af2a9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Apr 2015 16:01:50 +0200 Subject: [PATCH 166/269] Added a test file for utilities.h --- .../test/Tangential_complex/CMakeLists.txt | 2 + .../Tangential_complex/test_utilities.cpp | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 Tangential_complex/test/Tangential_complex/test_utilities.cpp diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt index c1b10d3b85c..230af037117 100644 --- a/Tangential_complex/test/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -67,6 +67,8 @@ if ( CGAL_FOUND ) ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES) create_single_source_cgal_program( ${SOURCE_FILES} ) + 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() diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.cpp b/Tangential_complex/test/Tangential_complex/test_utilities.cpp new file mode 100644 index 00000000000..f902cca8f08 --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/test_utilities.cpp @@ -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 +#include + +#include + +using namespace CGAL::Tangential_complex_; + +void test_does_voronoi_face_and_alpha_tangent_subspace_intersect() +{ + typedef CGAL::Epick_d > K; + typedef K::Point_d Pt; + typedef K::Vector_d Vec; + std::vector P; + std::vector Q; + std::vector osb; + + K k; + + std::vector 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_alpha_tangent_subspace_intersect( + points, 0, P, Q, osb, 0.0, k) == false); + + assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + points, 0, P, Q, osb, 0.5, k) == false); + + assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + points, 0, P, Q, osb, 1.0, k) == false); + + assert(does_voronoi_face_and_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; +} From 1dff5b1d819656033181310bc397b5592b3d484e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Apr 2015 16:03:44 +0200 Subject: [PATCH 167/269] First implementation of alpha-TC + typos + bug fix in export_to_off --- .../include/CGAL/Tangential_complex.h | 453 ++++++++++++++++-- 1 file changed, 408 insertions(+), 45 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8d63b68f583..6e3d099bf67 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -67,6 +67,10 @@ #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) +#define CGAL_ALPHA_TC +const double ALPHA = 0.3; +tbb::atomic ttt_star; // CJTODO TEMP +tbb::atomic ttt_intersect; namespace CGAL { @@ -186,18 +190,12 @@ class Tangential_complex typedef typename std::vector Tr_container; typedef typename std::vector Vectors; - // An Incident_simplex is the list of the verter indices + // An Incident_simplex is the list of the vertex indices // except the center vertex typedef std::set Incident_simplex; typedef std::vector Star; typedef std::vector Stars_container; -#ifdef CGAL_LINKED_WITH_TBB - // CJTODO: test other mutexes - // http://www.threadingbuildingblocks.org/docs/help/reference/synchronization/mutexes/mutex_concept.htm - //typedef tbb::queuing_mutex Tr_mutex; -#endif - // For transform_iterator static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) { @@ -226,7 +224,7 @@ public: m_intrinsic_dimension(intrinsic_dimension), m_half_sparsity(0.5*sparsity), m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), - m_ambiant_dim(k.point_dimension_d_object()(*first)), + m_ambient_dim(k.point_dimension_d_object()(*first)), m_points(first, last) # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) @@ -257,6 +255,8 @@ public: { #ifdef CGAL_TC_PROFILING Wall_clock_timer t; + ttt_intersect = 0; + ttt_star = 0; #endif // We need to do that because we don't want the container to copy the @@ -276,7 +276,7 @@ public: #endif #ifdef CGAL_TC_PERTURB_POSITION m_translations.resize(m_points.size(), - m_k.construct_vector_d_object()(m_ambiant_dim)); + m_k.construct_vector_d_object()(m_ambient_dim)); # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) delete [] m_p_perturb_mutexes; m_p_perturb_mutexes = new Mutex_for_perturb[m_points.size()]; @@ -299,12 +299,18 @@ public: #endif // CGAL_LINKED_WITH_TBB { for (std::size_t i = 0 ; i < m_points.size() ; ++i) +#ifdef CGAL_ALPHA_TC + compute_alpha_tangent_triangulation(i, ALPHA); +#else compute_tangent_triangulation(i); +#endif } #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex computed in " << t.elapsed() << " seconds." << std::endl; + std::cerr << "Intersect: " << ((double)ttt_intersect)/1000000 << " s\n" + << "Star: " << ((double)ttt_star)/1000000 << " s\n"; #endif } @@ -314,7 +320,7 @@ public: typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - std::vector sum_eigen_values(m_ambiant_dim, FT(0)); + std::vector sum_eigen_values(m_ambient_dim, FT(0)); Points::const_iterator it_p = m_points.begin(); Points::const_iterator it_p_end = m_points.end(); @@ -329,13 +335,13 @@ public: //******************************* PCA ************************************* // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambient_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { - for (int i = 0 ; i < m_ambiant_dim ; ++i) + for (int i = 0 ; i < m_ambient_dim ; ++i) mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); } Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); @@ -345,7 +351,7 @@ public: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = 0 ; i < m_ambiant_dim ; ++i) + for (int i = 0 ; i < m_ambient_dim ; ++i) sum_eigen_values[i] += eig.eigenvalues()[i]; //************************************************************************* @@ -381,8 +387,13 @@ public: { for (std::size_t i = 0 ; i < m_points.size() ; ++i) { +#ifdef CGAL_ALPHA_TC + compute_alpha_tangent_triangulation(i, ALPHA, + true); // tangent_spaces_are_already_computed +#else compute_tangent_triangulation(i, true); // tangent_spaces_are_already_computed +#endif } } @@ -692,8 +703,7 @@ public: if (m_points.empty()) return os; - const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); - if (ambient_dim < 2) + if (m_ambient_dim < 2) { std::cerr << "Error: export_to_off => ambient dimension should be >= 2." << std::endl; @@ -701,7 +711,7 @@ public: << std::endl; return os; } - if (ambient_dim > 3) + if (m_ambient_dim > 3) { std::cerr << "Warning: export_to_off => ambient dimension should be " "<= 3. Only the first 3 coordinates will be exported." @@ -758,7 +768,6 @@ public: if (m_points.empty()) return true; - const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); typedef Regular_triangulation_euclidean_traits RT_Traits; typedef Regular_triangulation< RT_Traits, @@ -774,7 +783,7 @@ public: // Then save its simplices into "amb_dt_simplices" //------------------------------------------------------------------------- - RT ambient_dt(ambient_dim); + RT ambient_dt(m_ambient_dim); for (std::size_t i=0; i combi( - dim + 1, 0, ambient_dim + 1); + dim + 1, 0, m_ambient_dim + 1); for ( ; !combi.finished() ; ++combi) { @@ -864,7 +873,7 @@ public: std::set diff; if (!incorrect_simplices) incorrect_simplices = &diff; - set_difference(p_simplices->begin(), p_simplices->end(), + std::set_difference(p_simplices->begin(), p_simplices->end(), amb_dt_simplices.begin(), amb_dt_simplices.end(), std::inserter(*incorrect_simplices, incorrect_simplices->begin()) ); @@ -946,8 +955,13 @@ private: { for( size_t i = r.begin() ; i != r.end() ; ++i) { +#ifdef CGAL_ALPHA_TC + m_tc.compute_alpha_tangent_triangulation( + i, ALPHA, m_tangent_spaces_are_already_computed); +#else m_tc.compute_tangent_triangulation( i, m_tangent_spaces_are_already_computed); +#endif } } }; @@ -1159,6 +1173,347 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } + + void compute_alpha_tangent_triangulation( + std::size_t i, FT alpha, bool tangent_spaces_are_already_computed = false, + bool verbose = false) + { + if (verbose) + std::cerr << "** Computing alpha tangent tri #" + << i << " **" << std::endl; + + typedef Regular_triangulation_euclidean_traits Amb_RT_Traits; + typedef Regular_triangulation< + Amb_RT_Traits, + Triangulation_data_structure< + typename Amb_RT_Traits::Dimension, + Triangulation_vertex + > > Amb_RT; + typedef typename Amb_RT::Vertex_handle Amb_RT_VH; + typedef typename Amb_RT::Full_cell_handle Amb_RT_FCH; + //typedef typename Amb_RT::Finite_full_cell_const_iterator Amb_FFC_it; + + typename Kernel::Point_drop_weight_d k_drop_w = + m_k.point_drop_weight_d_object(); + typename Kernel::Squared_distance_d k_sqdist = + m_k.squared_distance_d_object(); + typename Kernel::Point_weight_d k_point_weight = + m_k.point_weight_d_object(); + typename Kernel::Power_center_d k_power_center = + m_k.power_center_d_object(); + + // No need to lock the mutex here since this will not be called while + // other threads are perturbing the positions + const Point ¢er_pt = m_points[i]; + + // Estimate the tangent space + if (!tangent_spaces_are_already_computed) + { +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i]); +#else + m_tangent_spaces[i] = compute_tangent_space(center_pt); +#endif + } +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + else if (m_perturb_tangent_space[i]) + { +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_tangent_spaces[i] = + compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); +#else + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); +#endif + m_perturb_tangent_space[i] = false; + } +#endif + + //*************************************************** + // Build a minimal triangulation in the tangent space + // (we only need the star of p in the AMBIENT triangulation) + //*************************************************** + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_star; +#endif + + Amb_RT local_amb_tr(m_ambient_dim); + + // Insert p + Weighted_point wp = m_k.construct_weighted_point_d_object()( + center_pt, +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights[i] +#else + 0 +#endif + ); + Amb_RT_VH center_vertex = local_amb_tr.insert(wp); + center_vertex->data() = i; + if (verbose) + std::cerr << "* Inserted point #" << i << std::endl; + + INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); + + // While building the local triangulation, we keep the radius + // of the sphere "star sphere" centered at "center_vertex" + // and which contains all the + // circumspheres of the star of "center_vertex" + boost::optional squared_star_sphere_radius_plus_margin; + + // Insert points until we find a point which is outside "star shere" + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) + { + std::size_t neighbor_point_idx = nn_it->first; + + // ith point = p, which is already inserted + if (neighbor_point_idx != i) + { + // No need to lock the Mutex_for_perturb here since this will not be + // called while other threads are perturbing the positions + Weighted_point neighbor_wp = + compute_perturbed_weighted_point(neighbor_point_idx); + + // "4*m_sq_half_sparsity" because both points can be perturbed + if (squared_star_sphere_radius_plus_margin + && k_sqdist(center_pt, k_drop_w(neighbor_wp)) + > *squared_star_sphere_radius_plus_margin) + break; + + Amb_RT_VH vh = local_amb_tr.insert_if_in_star(neighbor_wp, center_vertex); + //Amb_RT_VH vh = local_amb_tr.insert(neighbor_wp); + if (vh != Amb_RT_VH()) + { + if (verbose) + std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; + + vh->data() = neighbor_point_idx; + + // Let's recompute squared_star_sphere_radius_plus_margin + if (local_amb_tr.current_dimension() == m_ambient_dim) + { + squared_star_sphere_radius_plus_margin = boost::none; + // Get the incident cells and look for the biggest circumsphere + std::vector incident_cells; + local_amb_tr.incident_full_cells( + center_vertex, + std::back_inserter(incident_cells)); + for (typename std::vector::iterator cit = + incident_cells.begin(); cit != incident_cells.end(); ++cit) + { + Amb_RT_FCH cell = *cit; + if (local_amb_tr.is_infinite(cell)) + { + squared_star_sphere_radius_plus_margin = boost::none; + break; + } + else + { + Tr_point c = k_power_center( + boost::make_transform_iterator( + cell->vertices_begin(), + vertex_handle_to_point), + boost::make_transform_iterator( + cell->vertices_end(), + vertex_handle_to_point)); + + FT sq_power_sphere_diam = 4*k_point_weight(c); + + if (!squared_star_sphere_radius_plus_margin + || sq_power_sphere_diam > + *squared_star_sphere_radius_plus_margin) + { + squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; + } + } + } + + // Let's add the margin, now + // The value depends on whether we perturb weight or position + if (squared_star_sphere_radius_plus_margin) + { +#ifdef CGAL_TC_PERTURB_WEIGHT + squared_star_sphere_radius_plus_margin = + *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; +#else + squared_star_sphere_radius_plus_margin = CGAL::square( + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + + 2*m_half_sparsity); +#endif + } + } + } + } + } + +#ifdef CGAL_TC_PROFILING + ttt_star += 1000000*t_star.elapsed(); +#endif + + //*************************************************** + // Parse the faces of the star and add the ones that are in the + // restriction to alpha-Tp + // Update the associated star (in m_stars) + //*************************************************** + Star &star = m_stars[i]; + star.clear(); + int cur_dim_plus_1 = m_ambient_dim + 1; + + std::vector incident_cells; + local_amb_tr.incident_full_cells( + center_vertex, std::back_inserter(incident_cells)); + + typedef std::set DT_face; // DT face without center vertex (i) + typedef std::set Neighbor_vertices; + typedef std::map DT_faces_and_neighbors; + + // Maps that associate a k-face and the list of its neighbor points + // (i.e. there are k+1-cofaces that contain these points) + // N.B.: each k-face contains 'i', so 'i' is not stored in the faces + // faces_and_neighbors[0] => dim 1, faces_and_neighbors[1] => dim 2 + std::vector faces_and_neighbors; + faces_and_neighbors.resize(m_ambient_dim); + + // Fill faces_and_neighbors + // Let's first take care of the D-faces + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end= incident_cells.end(); + // For each cell + for ( ; it_c != it_c_end ; ++it_c) + { + DT_face face; + // CJTODO: use (*it_c)->vertices_begin(), etc. + for (int j = 0 ; j < cur_dim_plus_1 ; ++j) + { + std::size_t index = (*it_c)->vertex(j)->data(); + if (index == std::numeric_limits::max()) + goto next_face; + if (index != i) + face.insert(index); + } + faces_and_neighbors[m_ambient_dim-1][face] = Neighbor_vertices(); +next_face: + ; + } + // Then the D-k-faces... + int current_dim = m_ambient_dim - 1; + while (current_dim > 0) + { + // Let's fill faces_and_neighbors[current_dim-1] + // (stores the current_dim-faces) + DT_faces_and_neighbors& cur_faces_and_nghb = + faces_and_neighbors[current_dim-1]; + + typedef DT_faces_and_neighbors::const_iterator FaN_it; + // Parse k+1-faces + for (FaN_it it_k_p1_face = faces_and_neighbors[current_dim].begin(), + it_k_p1_face_end = faces_and_neighbors[current_dim].end() ; + it_k_p1_face != it_k_p1_face_end ; ++it_k_p1_face) + { + DT_face const& k_p1_face = it_k_p1_face->first; + + // Add each k faces to cur_faces_and_nghb + std::size_t n = current_dim + 1; // Not +2 since 'i' is not stored + std::vector booleans(n, false); + std::fill(booleans.begin() + 1, booleans.end(), true); + do + { + DT_face k_face; + std::size_t remaining_vertex; + DT_face::const_iterator it_v = k_p1_face.begin(); + for (std::size_t i = 0 ; i < n ; ++i, ++it_v) + { + if (booleans[i]) + k_face.insert(*it_v); + else + remaining_vertex = *it_v; + } + + cur_faces_and_nghb[k_face].insert(remaining_vertex); + + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + --current_dim; + } + + // For each face V of Voronoi_cell(P[i]) - dim 0 to dim D-1 + // I.e. For each DT face F of the star - dim D to dim 1 + current_dim = m_ambient_dim; + while (current_dim > 0) + { + // Remember: faces_and_neighbors[current_dim-1] stores + // the current_dim-faces + DT_faces_and_neighbors const& cur_faces_and_nghb = + faces_and_neighbors[current_dim-1]; + + for (DT_faces_and_neighbors::const_iterator + it_f = cur_faces_and_nghb.begin(), + it_f_end = cur_faces_and_nghb.end() ; + it_f != it_f_end ; ++it_f) + { + Neighbor_vertices const& curr_neighbors = it_f->second; + + DT_face const& current_DT_face = it_f->first; + CGAL_assertion(static_cast(current_DT_face.size()) + == current_dim); + + // P: list of current_DT_face points (including 'i') + std::vector P( + current_DT_face.begin(), current_DT_face.end()); + P.push_back(i); + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_inters; +#endif + bool does_intersect = + does_voronoi_face_and_alpha_tangent_subspace_intersect( + m_points, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); +#ifdef CGAL_TC_PROFILING + ttt_intersect += 1000000*t_inters.elapsed(); +#endif + if (does_intersect) + { + star.push_back(current_DT_face); + + // Clear all subfaces of current_DT_face from the maps + for (int dim = current_dim - 1 ; dim > 0 ; --dim) + { + std::size_t n = current_DT_face.size(); + std::vector booleans(n, false); + std::fill(booleans.begin() + n - dim, booleans.end(), true); + do + { + DT_face dim_face; + DT_face::const_iterator it_v = current_DT_face.begin(); + for (std::size_t i = 0 ; i < n ; ++i, ++it_v) + { + if (booleans[i]) + dim_face.insert(*it_v); + } + + faces_and_neighbors[dim-1].erase(dim_face); + + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + } + } + + --current_dim; + } + + // CJTODO DEBUG + //std::cerr << "\nChecking topology and geometry..." + // << (local_amb_tr.is_valid(true) ? "OK.\n" : "Error.\n"); + // DEBUG: output the local mesh into an OFF file + //std::stringstream sstr; + //sstr << "data/local_tri_" << i << ".off"; + //std::ofstream off_stream_tr(sstr.str()); + //CGAL::export_triangulation_to_off(off_stream_tr, local_amb_tr); + } + Tangent_space_basis compute_tangent_space( const Point &p , bool normalize_basis = true @@ -1196,13 +1551,13 @@ private: #endif // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambiant_dim); + Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambient_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; ++j, ++nn_it) { - for (int i = 0 ; i < m_ambiant_dim ; ++i) + for (int i = 0 ; i < m_ambient_dim ; ++i) { //const Point p = transl( // m_points[nn_it->first], m_translations[nn_it->first]); @@ -1220,31 +1575,31 @@ private: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = m_ambiant_dim - 1 ; - i >= m_ambiant_dim - m_intrinsic_dimension ; + for (int i = m_ambient_dim - 1 ; + i >= m_ambient_dim - m_intrinsic_dimension ; --i) { if (normalize_basis) { ts.push_back(normalize_vector( constr_vec( - m_ambiant_dim, + m_ambient_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim), + eig.eigenvectors().col(i).data() + m_ambient_dim), m_k)); } else { ts.push_back(constr_vec( - m_ambiant_dim, + m_ambient_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim)); + eig.eigenvectors().col(i).data() + m_ambient_dim)); } } if (p_orth_space_basis) { - for (int i = m_ambiant_dim - m_intrinsic_dimension - 1 ; + for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; i >= 0 ; --i) { @@ -1252,17 +1607,17 @@ private: { p_orth_space_basis->push_back(normalize_vector( constr_vec( - m_ambiant_dim, + m_ambient_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim), + eig.eigenvectors().col(i).data() + m_ambient_dim), m_k)); } else { p_orth_space_basis->push_back(constr_vec( - m_ambiant_dim, + m_ambient_dim, eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambiant_dim)); + eig.eigenvectors().col(i).data() + m_ambient_dim)); } } } @@ -1544,7 +1899,7 @@ private: typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(m_ambiant_dim, 1); + tr_point_on_sphere_generator(m_ambient_dim, 1); // Parallel # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) Vector transl = k_scaled_vec(k_pt_to_vec( @@ -1576,7 +1931,7 @@ private: Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( *tr_point_on_sphere_generator++, 0); - Translation_for_perturb global_transl = k_constr_vec(m_ambiant_dim); + Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { @@ -1826,13 +2181,12 @@ private: // to be able to export each segment as a flat triangle with 3 different // indices (otherwise, Meshlab detects degenerated simplices) const int N = (m_intrinsic_dimension == 1 ? 2 : 1); - const int ambient_dim = m_k.point_dimension_d_object()(*m_points.begin()); // Kernel functors typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - int num_coords = min(ambient_dim, 3); + int num_coords = min(m_ambient_dim, 3); #ifdef CGAL_TC_EXPORT_NORMALS OS_container::const_iterator it_os = m_orth_spaces.begin(); #endif @@ -2296,15 +2650,20 @@ private: c) != p_additional_simpl_to_color->end()); } - // If only 2 vertices, add a third one (each vertex is duplicated in + + // If m_intrinsic_dimension = 1, each point is output two times, + // so we need to multiply each index by 2 + // And if only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) - if (num_vertices == 2) + if (m_intrinsic_dimension == 1) { std::set tmp_c; std::set::iterator it = c.begin(); for ( ; it != c.end() ; ++it) tmp_c.insert(*it * 2); - tmp_c.insert(*c.rbegin() + 1); + if (num_vertices == 2) + tmp_c.insert(*tmp_c.rbegin() + 1); + c = tmp_c; } @@ -2440,15 +2799,19 @@ private: if (num_vertices < m_intrinsic_dimension + 1) continue; - // If only 2 vertices, add a third one (each vertex is duplicated in + // If m_intrinsic_dimension = 1, each point is output two times, + // so we need to multiply each index by 2 + // And if only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) - if (num_vertices == 2) + if (m_intrinsic_dimension == 1) { std::set tmp_c; std::set::iterator it = c.begin(); for ( ; it != c.end() ; ++it) tmp_c.insert(*it * 2); - tmp_c.insert(*c.rbegin() + 1); + if (num_vertices == 2) + tmp_c.insert(*tmp_c.rbegin() + 1); + c = tmp_c; } @@ -2523,7 +2886,7 @@ private: const int m_intrinsic_dimension; const double m_half_sparsity; const double m_sq_half_sparsity; - const int m_ambiant_dim; + const int m_ambient_dim; Points m_points; #ifdef CGAL_TC_PERTURB_WEIGHT From 26d07750f868277d4df6a2c99456e3adb6dccdba Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 17 Apr 2015 17:10:00 +0200 Subject: [PATCH 168/269] Temporary code to test the alpha-TC --- .../Tangential_complex/benchmark_tc.cpp | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 308d3e950ad..4803abccfae 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -183,6 +183,37 @@ void make_tc(std::vector &points, int intrinsic_dim, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); + // CJTODO TEMP =========================== + { + TC::Simplicial_complex complex; + int max_dim = tc.export_TC(complex, false); + complex.display_stats(); + + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim + << "_in_R" << ambient_dim << "_ALPHA_COMPLEX.off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(complex, off_stream); + + // Collapse + complex.collapse(max_dim); + { + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim + << "_in_R" << ambient_dim << "_AFTER_COLLAPSE.off"; + std::ofstream off_stream(output_filename.str().c_str()); + 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( + intrinsic_dim, false, 1, + &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); + complex.display_stats(); + } + + return; + // CJTODO TEMP =========================== + //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); double export_before_time = -1.; @@ -198,6 +229,7 @@ void make_tc(std::vector &points, int intrinsic_dim, } + t.reset(); unsigned int num_fix_steps; std::size_t initial_num_inconsistent_local_tr; @@ -254,7 +286,7 @@ void make_tc(std::vector &points, int intrinsic_dim, } // Collapse - complex.collapse(max_dim); + //complex.collapse(max_dim); double export_after_collapse_time = -1.; if (intrinsic_dim <= 3) @@ -271,6 +303,7 @@ void make_tc(std::vector &points, int intrinsic_dim, bool pure_manifold = complex.is_pure_manifold( intrinsic_dim, false, 0, &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); + complex.display_stats(); std::cerr << std::endl From 509bff1152858632e10e283825e59a4fd923b93b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 12:54:22 +0200 Subject: [PATCH 169/269] Add is_pure_pseudomanifold__do_not_check_if_stars_are_connected + minor changes --- .../Tangential_complex/Simplicial_complex.h | 235 +++++++++++++++++- 1 file changed, 224 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index e386739020f..dac05d35a89 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -26,6 +26,13 @@ #include #include +#include + +// For is_pure_pseudomanifold +#include +#include +#include +#include namespace CGAL { namespace Tangential_complex_ { @@ -46,8 +53,19 @@ public: return m_complex; } - void collapse(int max_simplex_dim) + void clear() { + m_complex.clear(); + } + + // 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; @@ -121,7 +139,12 @@ public: // Collapse the lower dimension simplices if (k > 0) - collapse(max_simplex_dim - 1); + collapse(max_simplex_dim - 1, true); + +#ifdef CGAL_TC_VERBOSE + if (!quiet) + std::cerr << "done." << std::endl; +#endif } void display_stats() const @@ -137,9 +160,6 @@ public: { // Number of simplex for each dimension std::map simplex_stats; - - typedef std::set Simplex; - typedef std::set Complex; for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; @@ -161,16 +181,18 @@ public: } // verbose_level = 0, 1 or 2 - bool is_pure_manifold(int simplex_dim, - 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) + bool is_pure_pseudomanifold__do_not_check_if_stars_are_connected( + int simplex_dim, + 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) { typedef std::set K_1_face; typedef std::map Cofaces_map; - std::size_t num_wrong_dim_simplices = 0, num_wrong_number_of_cofaces = 0; + 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 @@ -242,8 +264,199 @@ public: return ret; } + // CJTODO: ADD COMMENTS + bool is_pure_pseudomanifold( + int simplex_dim, + std::size_t num_vertices, + 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_range *p_wrong_dim_simplices = NULL, + Simplex_range *p_wrong_number_of_cofaces_simplices = NULL, + Simplex_range *p_unconnected_stars_simplices = NULL) + { + // 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, + 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 > 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 << std::endl; + ++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, with 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 > + 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 dm1_simpl_of_link_vec( + dm1_simpl_of_link.begin(), dm1_simpl_of_link.end()); + + CGAL::Combination_enumerator 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 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::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) + { + ++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 + std::vector components(boost::num_vertices(adj_graph)); + bool 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" << std::endl; + ++num_unconnected_stars; + if (p_unconnected_stars_simplices) + { + for (std::vector::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 << "is_pure_pseudo_manifold: " + << (ret ? "YES" : "NO") << std::endl; + if (!ret) + { + std::cerr << " * Number of wrong dimension simplices: " + << num_wrong_dim_simplices << std::endl + << " * Number of wrong number of cofaces: " + << num_wrong_number_of_cofaces << std::endl + << " * Number of not-connected stars: " + << num_unconnected_stars << std::endl; + } + } + + 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_range Complex; + + // graph is an adjacency list + typedef boost::adjacency_list Adj_graph; + // map that gives to a certain simplex its node in graph and its dimension + typedef boost::graph_traits::vertex_descriptor Graph_vertex; + typedef boost::graph_traits::edge_descriptor Graph_edge; Complex m_complex; From 7fab99906a6f8d36df2b04a1fe3dc7a5b594611b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 12:57:04 +0200 Subject: [PATCH 170/269] Allow several colors in export_to_off + const correctness --- .../include/CGAL/Tangential_complex.h | 166 ++++++++++++------ 1 file changed, 116 insertions(+), 50 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6e3d099bf67..2f88a7b36cc 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -76,7 +76,8 @@ namespace CGAL { using namespace Tangential_complex_; -enum Fix_inconsistencies_status { TC_FIXED = 0, TIME_LIMIT_REACHED }; +enum Fix_inconsistencies_status { + TC_FIXED = 0, TIME_LIMIT_REACHED, FIX_NOT_PERFORMED }; class Vertex_data { @@ -246,6 +247,15 @@ public: #endif } + int intrinsic_dimension() const + { + return m_intrinsic_dimension; + } + int ambient_dimension() const + { + return m_ambient_dim; + } + std::size_t number_of_vertices() { return m_points.size(); @@ -619,7 +629,7 @@ public: // Return the max dimension of the simplices int export_TC(Simplicial_complex &complex, - bool export_infinite_simplices = false) + bool export_infinite_simplices = false) const { int max_dim = -1; @@ -690,15 +700,22 @@ public: std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, - std::set > const *p_additional_simpl_to_color = NULL) + std::set > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL) + const { - return export_to_off(os, false, p_additional_simpl_to_color, &complex); + return export_to_off( + os, false, p_simpl_to_color_in_red, p_simpl_to_color_in_green, + p_simpl_to_color_in_blue, &complex); } std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, - std::set > const *p_additional_simpl_to_color = NULL, - const Simplicial_complex *p_complex = NULL) + std::set > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL, + const Simplicial_complex *p_complex = NULL) const { if (m_points.empty()) return os; @@ -735,13 +752,14 @@ public: if (p_complex) { export_simplices_to_off( - *p_complex, output, num_simplices, p_additional_simpl_to_color); + *p_complex, output, num_simplices, p_simpl_to_color_in_red, + p_simpl_to_color_in_green, p_simpl_to_color_in_blue); } else { export_simplices_to_off( - output, num_simplices, color_inconsistencies, - p_additional_simpl_to_color); + output, num_simplices, color_inconsistencies, p_simpl_to_color_in_red, + p_simpl_to_color_in_green, p_simpl_to_color_in_blue); } #ifdef CGAL_TC_EXPORT_NORMALS @@ -1664,7 +1682,7 @@ next_face: */ } - Point compute_perturbed_point(std::size_t pt_idx) + Point compute_perturbed_point(std::size_t pt_idx) const { #ifdef CGAL_TC_PERTURB_POSITION return m_k.translated_point_d_object()( @@ -1809,7 +1827,7 @@ next_face: } // A simplex here is a local tri's full cell handle - bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) + bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) const { std::set c; for (int i = 0 ; i < cur_dim + 1 ; ++i) @@ -1821,7 +1839,7 @@ next_face: } // A simplex here is a list of point indices - bool is_simplex_consistent(std::set const& simplex) + bool is_simplex_consistent(std::set const& simplex) const { int cur_dim_plus_1 = static_cast(simplex.size()); @@ -2169,7 +2187,7 @@ next_face: std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices, - bool use_perturbed_points = false) + bool use_perturbed_points = false) const { if (m_points.empty()) { @@ -2595,7 +2613,10 @@ next_face: std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_simplices, bool color_inconsistencies = false, - std::set > const *p_additional_simpl_to_color = NULL) + std::set > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL) + const { // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) @@ -2620,8 +2641,8 @@ next_face: //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; color << 128 << " " << 128 << " " << 128; - // Gather the triangles here, with a bool saying if it's consistent - typedef std::vector, bool> > + // Gather the triangles here, with an int telling its color + typedef std::vector, int> > Star_using_triangles; Star_using_triangles star_using_triangles; @@ -2634,22 +2655,40 @@ next_face: c.insert(idx); std::size_t num_vertices = c.size(); - bool color_simplex = false; + int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue if (color_inconsistencies) { - color_simplex = !is_simplex_consistent(c); - if (color_simplex) - is_star_inconsistent = true; + is_star_inconsistent = !is_simplex_consistent(c); + color_simplex = (is_star_inconsistent ? 0 : -1); } - if (p_additional_simpl_to_color && !color_simplex) + if (color_simplex == -1) { - color_simplex = (std::find( - p_additional_simpl_to_color->begin(), - p_additional_simpl_to_color->end(), - c) != p_additional_simpl_to_color->end()); + if (p_simpl_to_color_in_red && + std::find( + p_simpl_to_color_in_red->begin(), + p_simpl_to_color_in_red->end(), + c) != p_simpl_to_color_in_red->end()) + { + color_simplex = 1; + } + else if (p_simpl_to_color_in_green && + std::find( + p_simpl_to_color_in_green->begin(), + p_simpl_to_color_in_green->end(), + c) != p_simpl_to_color_in_green->end()) + { + color_simplex = 2; + } + else if (p_simpl_to_color_in_blue && + std::find( + p_simpl_to_color_in_blue->begin(), + p_simpl_to_color_in_blue->end(), + c) != p_simpl_to_color_in_blue->end()) + { + color_simplex = 3; + } } - // If m_intrinsic_dimension = 1, each point is output two times, // so we need to multiply each index by 2 @@ -2704,7 +2743,7 @@ next_face: continue; const std::set &c = it_simplex->first; - bool color_simplex = it_simplex->second; + int color_simplex = it_simplex->second; std::stringstream sstr_c; @@ -2716,19 +2755,21 @@ next_face: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != idx && !color_simplex) + if (*c.begin() != idx && color_simplex == -1) continue; os << 3 << " " << sstr_c.str(); - if (color_inconsistencies || p_additional_simpl_to_color) + if (color_inconsistencies || p_simpl_to_color_in_red + || p_simpl_to_color_in_green || p_simpl_to_color_in_blue) { - if (color_simplex) + switch (color_simplex) { - os << " 255 0 0"; - ++num_inconsistent_simplices; - } - else - os << " " << color.str(); + case 0: os << " 255 255 0"; ++num_inconsistent_simplices; break; + case 1: os << " 255 0 0"; break; + case 2: os << " 0 255 0"; break; + case 3: os << " 0 0 255"; break; + default: os << " " << color.str(); break; + } } ++num_simplices; os << std::endl; @@ -2764,7 +2805,10 @@ next_face: std::ostream &export_simplices_to_off( const Simplicial_complex &complex, std::ostream & os, std::size_t &num_simplices, - std::set > const *p_additional_simpl_to_color = NULL) + std::set > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL) + const { typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; @@ -2780,15 +2824,32 @@ next_face: for ( ; it_s != it_s_end ; ++it_s) { Simplex c = *it_s; - - bool color_simplex = false; - if (p_additional_simpl_to_color) - { - color_simplex = (std::find( - p_additional_simpl_to_color->begin(), - p_additional_simpl_to_color->end(), - c) != p_additional_simpl_to_color->end()); - } + + int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue + if (p_simpl_to_color_in_red && + std::find( + p_simpl_to_color_in_red->begin(), + p_simpl_to_color_in_red->end(), + c) != p_simpl_to_color_in_red->end()) + { + color_simplex = 1; + } + else if (p_simpl_to_color_in_green && + std::find( + p_simpl_to_color_in_green->begin(), + p_simpl_to_color_in_green->end(), + c) != p_simpl_to_color_in_green->end()) + { + color_simplex = 2; + } + else if (p_simpl_to_color_in_blue && + std::find( + p_simpl_to_color_in_blue->begin(), + p_simpl_to_color_in_blue->end(), + c) != p_simpl_to_color_in_blue->end()) + { + color_simplex = 3; + } // Gather the triangles here typedef std::vector Triangles; @@ -2854,12 +2915,17 @@ next_face: os << *it_point_idx << " "; } - if (p_additional_simpl_to_color) + if (p_simpl_to_color_in_red || p_simpl_to_color_in_green + || p_simpl_to_color_in_blue) { - if (color_simplex) - os << " 255 0 0"; - else - os << " 128 128 128"; + switch (color_simplex) + { + case 0: os << " 255 255 0"; break; + case 1: os << " 255 0 0"; break; + case 2: os << " 0 255 0"; break; + case 3: os << " 0 0 255"; break; + default: os << " 128 128 128"; break; + } } ++num_simplices; From 268cd0994b67a9b73dea065b19f0385fa66c9642 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 12:57:52 +0200 Subject: [PATCH 171/269] Improved benchmark (comments, output...) --- .../Tangential_complex/benchmark_script.txt | 82 ++-- .../Tangential_complex/benchmark_tc.cpp | 379 ++++++++++++------ 2 files changed, 310 insertions(+), 151 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 0aa065fd7a8..a26d5085ada 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -1,42 +1,54 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- -# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY FIX_TIME_LIMIT NUM_ITERATIONS +# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- -#---------------------------------------------------------- Very small cases for Debug mode ------------------------------------------------------------- -#generate_sphere_d 3 - - 20 3 2 0.05 60 1 -#generate_klein_bottle_4D 4 3 - 70 4 2 1.5 60 1 +#---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- +#generate_sphere_d 4 - - 20 3 2 0.05 N N Y 60 1 +#generate_sphere_d 3 - - 70 3 2 0.05 Y Y Y 60 1 +#generate_sphere_d 3 - - 1000 3 2 0.05 Y Y Y 60 1 +#generate_sphere_d 3 - - 70 4 3 0.05 Y Y Y 60 1 +#generate_sphere_d 3 - - 70 5 4 0.05 Y Y Y 60 1 +#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 Y Y Y 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.7 Y Y Y 60 1 +#generate_moment_curve 0 1 - 30 3 1 0.005 Y Y Y 60 1 -#------------------------------------------------------------------ From files --------------------------------------------------------------------------- -data/SO3_50000.txt - - - 0 9 3 0.2 60 1 -data/SO3_10000.txt - - - 0 9 3 0.05 60 1 -#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 3000 1 -#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 3000 1 -#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 3000 1 -data/Cy8.txt - - - 0 24 2 0.1 60 1 -data/Kl.txt - - - 0 5 2 0.05 60 1 -data/S3.txt - - - 0 4 3 0.05 60 1 +#---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ +#generate_sphere_d 0.302 - - 70 2 1 0.005 N N Y 60 1 +#generate_sphere_d 0.5 - - 70 2 1 0.005 N N Y 60 1 +generate_klein_bottle_4D 40 15 - 130 4 2 0.2 N N Y 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 Y Y Y 60 1 #Takes forever -#---------------------------------------------------------------------- 3D meshes ------------------------------------------------------------------------ -data/buddha_100kv.txt - - - 0 3 2 0.005 60 1 -data/fandisk.txt - - - 0 3 2 0.01 60 1 -data/fertility.txt - - - 0 3 2 0.4 60 1 -data/bunny.txt - - - 0 3 2 0.5 60 1 -data/blob.txt - - - 0 3 2 0.01 60 1 -data/3holes.txt - - - 0 3 2 0.01 60 1 -data/785_hand_2500v.txt - - - 0 3 2 0.01 60 1 -data/785_hand_50kv.txt - - - 0 3 2 0.01 60 1 -data/bumpy_sphere.txt - - - 0 3 2 0.01 60 1 +#------------------------------------------------------------------ From files -------------------------------------------------------------------------- +#data/SO3_50000.txt - - - 0 9 3 0.2 Y Y Y 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.05 Y Y Y 60 1 +#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 Y Y Y 3000 1 +#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 Y Y Y 3000 1 +#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 Y Y Y 3000 1 +#data/Cy8.txt - - - 0 24 2 0.1 Y Y Y 60 1 +#data/Kl.txt - - - 0 5 2 0.05 Y Y Y 60 1 +#data/S3.txt - - - 0 4 3 0.05 Y Y Y 60 1 -#----------------------------------------------------------- Generated point sets ------------------------------------------------------------------------ -#generate_sphere_d 3 - - 4 3 2 0.05 3000 1 -#generate_sphere_d 3 - - 30000 2 1 0.005 3000 1 -#generate_sphere_d 3 - - 30000 3 2 0.005 3000 1 -#generate_sphere_d 3 - - 30000 4 3 0.05 3000 1 -#generate_plane - - - 30000 3 2 0.005 3000 1 -generate_moment_curve 0 1 - 30000 6 1 0.005 60 1 -generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 60 1 -generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 60 1 +#---------------------------------------------------------------------- 3D meshes ----------------------------------------------------------------------- +#data/buddha_100kv.txt - - - 0 3 2 0.005 Y Y Y 60 1 +#data/fandisk.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/fertility.txt - - - 0 3 2 0.4 Y Y Y 60 1 +#data/bunny.txt - - - 0 3 2 0.5 Y Y Y 60 1 +#data/blob.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/3holes.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/785_hand_2500v.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/785_hand_50kv.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/bumpy_sphere.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#----------------------------------------------------------- Performance testing ------------------------------------------------------------------------- -# TC: 5.55 / 1st fix step : 0.2 -#data/fertility.txt - - - 0 3 2 0.1 100 1 \ No newline at end of file +#----------------------------------------------------------- Generated point sets ----------------------------------------------------------------------- +#generate_sphere_d 3 - - 4 3 2 0.05 Y Y Y 3000 1 +#generate_sphere_d 3 - - 30000 2 1 0.005 Y Y Y 3000 1 +#generate_sphere_d 3 - - 30000 3 2 0.005 Y Y Y 3000 1 +#generate_sphere_d 3 - - 30000 4 3 0.05 Y Y Y 3000 1 +#generate_plane - - - 30000 3 2 0.005 Y Y Y 3000 1 +#generate_moment_curve 0 1 - 30000 6 1 0.005 Y Y Y 60 1 +#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 Y Y Y 60 1 +#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 Y Y Y 60 1 + +#----------------------------------------------------------- Performance testing ------------------------------------------------------------------------ +# TC: 5.55 / 1st fix step : 0.2 +#data/fertility.txt - - - 0 3 2 0.1 Y Y Y 100 1 \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 4803abccfae..ae2b8310809 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -91,12 +91,14 @@ protected: subelements.push_back("Final_num_inconsistent_local_tr"); subelements.push_back("Init_time"); subelements.push_back("Comput_time"); - subelements.push_back("Fix1_successful"); - subelements.push_back("Fix1_time"); - subelements.push_back("Fix1_steps"); - subelements.push_back("Fix2_pure_manifold"); - subelements.push_back("Fix2_num_wrong_number_of_cofaces"); - subelements.push_back("Fix2_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; @@ -125,13 +127,94 @@ protected: XML_exporter::Element_with_map m_current_element; }; -void make_tc(std::vector &points, int intrinsic_dim, - double sparsity = 0., double time_limit_for_fix = 0., +template +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 > const *p_simpl_to_color_in_red = NULL, + std::set > const *p_simpl_to_color_in_green = NULL, + std::set > const *p_simpl_to_color_in_blue = NULL) +{ + if (tc.intrinsic_dimension() <= 3) + { + std::stringstream output_filename; + output_filename << "output/" << input_name_stripped << "_" + << tc.intrinsic_dimension() << "_in_R" + << tc.ambient_dimension() << suffix << ".off"; + std::ofstream off_stream(output_filename.str().c_str()); + + if (p_complex) + { + 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); + } + 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); +#endif + } + return true; + } + return false; +} + +void make_tc(std::vector &points, + int intrinsic_dim, + double sparsity = 0., + bool perturb = true, + bool add_high_dim_simpl = false, + bool collapse = false, + double time_limit_for_perturb = 0., const char *input_name = "tc") { + // CJTODO TEMP TEST + //TC::Simplicial_complex compl; + //{std::size_t ss[] = {0, 1, 2}; compl.add_simplex(std::set(ss, ss + 3)); } + //{std::size_t ss[] = {0, 2, 3}; compl.add_simplex(std::set(ss, ss + 3)); } + //{std::size_t ss[] = {0, 3, 4}; compl.add_simplex(std::set(ss, ss + 3)); } + //{std::size_t ss[] = {0, 4, 1}; compl.add_simplex(std::set(ss, ss + 3)); } + //{std::size_t ss[] = {0, 5, 6}; compl.add_simplex(std::set(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(ss, ss + 4)); } + //{std::size_t ss[] = {0, 2, 3, 5}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 3, 4, 5}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 4, 1, 5}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 1, 2, 6}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 2, 3, 6}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 3, 4, 6}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 4, 1, 6}; compl.add_simplex(std::set(ss, ss + 4)); } + //{std::size_t ss[] = {0, 4, 7, 8}; compl.add_simplex(std::set(ss, ss + 4)); } + //compl.is_pure_pseudomanifold(3, 9, false, 10); + // /CJTODO TEMP TEST + + //=========================================================================== + // Init + //=========================================================================== Kernel k; 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) @@ -160,6 +243,9 @@ void make_tc(std::vector &points, int intrinsic_dim, std::vector points_not_sparse = points; #endif + //=========================================================================== + // Sparsify point set if requested + //=========================================================================== if (sparsity != 0.) { std::size_t num_points_before = points.size(); @@ -167,10 +253,14 @@ void make_tc(std::vector &points, int intrinsic_dim, std::cerr << "Number of points before/after sparsification: " << num_points_before << " / " << points.size() << std::endl; } - + CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); + //=========================================================================== + // Compute Tangential Complex + //=========================================================================== + #ifdef 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); @@ -183,8 +273,10 @@ void make_tc(std::vector &points, int intrinsic_dim, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - // CJTODO TEMP =========================== - { + //=========================================================================== + // CJTODO TEMP + //=========================================================================== + /*{ TC::Simplicial_complex complex; int max_dim = tc.export_TC(complex, false); complex.display_stats(); @@ -204,141 +296,191 @@ void make_tc(std::vector &points, int intrinsic_dim, std::ofstream off_stream(output_filename.str().c_str()); 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( - intrinsic_dim, false, 1, - &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); + std::size_t num_wrong_dim_simplices, + num_wrong_number_of_cofaces, + num_unconnected_stars; + bool pure_manifold = complex.is_pure_pseudomanifold( + intrinsic_dim, tc.number_of_vertices(), false, 1, + &num_wrong_dim_simplices, &num_wrong_number_of_cofaces, + &num_unconnected_stars); complex.display_stats(); } - - return; + return;*/ // CJTODO TEMP =========================== //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); - double export_before_time = -1.; - if (intrinsic_dim <= 3) - { - t.reset(); - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_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(); - } - - - + //=========================================================================== + // Export to OFF + //=========================================================================== + t.reset(); + double export_before_time = + (export_to_off(tc, input_name_stripped, "_BEFORE_FIX") ? t.elapsed() : -1); 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( - num_fix_steps, initial_num_inconsistent_local_tr, - best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, - time_limit_for_fix); - double fix_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); - double export_after_fix_time = -1.; - if (intrinsic_dim <= 3) + 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::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_AFTER_FIX.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(off_stream, true); - export_after_fix_time = t.elapsed(); 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( + 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); + + //========================================================================= + // Export to OFF + //========================================================================= + t.reset(); + bool exported = export_to_off(tc, input_name_stripped, "_AFTER_FIX", true); + double export_after_perturb_time = (exported ? t.elapsed() : -1); + t.reset(); + } + 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"); } - t.reset(); - // Try to solve the remaining inconstencies - tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); - double fix2_time = t.elapsed(); t.reset(); - TC::Simplicial_complex complex; - int max_dim = tc.export_TC(complex, false); - std::set > not_delaunay_simplices; - /*if (ambient_dim <= 4) - { - tc.check_if_all_simplices_are_in_the_ambient_delaunay( - &complex, true, ¬_delaunay_simplices); - }*/ - + int max_dim = -1; + double fix2_time = -1; double export_after_fix2_time = -1.; - if (intrinsic_dim <= 3) + TC::Simplicial_complex complex; + if (add_high_dim_simpl) { + //========================================================================= + // Try to fix inconsistencies by adding higher-dimension simplices + //========================================================================= t.reset(); - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_AFTER_FIX2.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(complex, off_stream, ¬_delaunay_simplices); - export_after_fix2_time = t.elapsed(); t.reset(); - } - - // Collapse - //complex.collapse(max_dim); + // Try to solve the remaining inconstencies + tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + fix2_time = t.elapsed(); t.reset(); + max_dim = tc.export_TC(complex, false); + /*std::set > not_delaunay_simplices; + if (ambient_dim <= 4) + { + tc.check_if_all_simplices_are_in_the_ambient_delaunay( + &complex, true, ¬_delaunay_simplices); + }*/ - double export_after_collapse_time = -1.; - if (intrinsic_dim <= 3) - { + //========================================================================= + // Export to OFF + //========================================================================= + t.reset(); + bool exported = export_to_off( + tc, input_name_stripped, "_AFTER_FIX2", false, &complex); + double export_after_fix2_time = (exported ? t.elapsed() : -1); t.reset(); - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_AFTER_COLLAPSE.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(complex, off_stream); - export_after_collapse_time = t.elapsed(); t.reset(); } - std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces; - bool pure_manifold = complex.is_pure_manifold( - intrinsic_dim, false, 0, - &num_wrong_dim_simplices, &num_wrong_number_of_cofaces); + else + { + max_dim = tc.export_TC(complex, false); + } complex.display_stats(); + + //=========================================================================== + // Collapse + //=========================================================================== + std::cerr << max_dim << std::endl; + if (collapse) + complex.collapse(max_dim); + + //=========================================================================== + // Is the result a pure pseudomanifold? + //=========================================================================== + std::size_t num_wrong_dim_simplices, + num_wrong_number_of_cofaces, + num_unconnected_stars; + std::set > wrong_dim_simplices; + std::set > wrong_number_of_cofaces_simplices; + std::set > unconnected_stars_simplices; + bool is_pure_pseudomanifold = complex.is_pure_pseudomanifold( + intrinsic_dim, tc.number_of_vertices(), 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 + complex.display_stats(); + + //=========================================================================== + // Export to OFF + //=========================================================================== + 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:" << std::endl + << " * Red: wrong dim simplices" << std::endl + << " * Green: wrong number of cofaces simplices" << std::endl + << " * Blue: not-connected stars" << std::endl; + double export_after_collapse_time = (exported ? t.elapsed() : -1); + t.reset(); + + //=========================================================================== + // Display info + //=========================================================================== std::cerr << std::endl << "================================================" << std::endl << "Number of vertices: " << tc.number_of_vertices() << std::endl - << "Pure manifold: " << (pure_manifold ? "YES" : "NO") << std::endl + << "Pure pseudomanifold: " << (is_pure_pseudomanifold ? "YES" : "NO") << std::endl << "Computation times (seconds): " << std::endl - << " * Tangential complex: " << init_time + computation_time - << 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 1: " << fix_time - << " (" << num_fix_steps << " steps) ==> " - << (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl + << " * Export to OFF (before perturb): " << export_before_time << std::endl + << " * Fix inconsistencies 1: " << perturb_time + << " (" << num_perturb_steps << " steps) ==> " + << (perturb_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl << " * Fix inconsistencies 2: " << fix2_time << std::endl - << " * Export to OFF (after fix): " << export_after_fix_time << std::endl + << " * Export to OFF (after perturb): " << export_after_perturb_time << std::endl << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl << " * Export to OFF (after collapse): " << export_after_collapse_time << std::endl << "================================================" << std::endl << std::endl; - - CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); - CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); - CGAL_TC_SET_PERFORMANCE_DATA("Fix1_successful", - (fix_ret == CGAL::TC_FIXED ? "Y" : "N")); - CGAL_TC_SET_PERFORMANCE_DATA("Fix1_time", fix_time); - CGAL_TC_SET_PERFORMANCE_DATA("Fix1_steps", num_fix_steps); - CGAL_TC_SET_PERFORMANCE_DATA("Fix2_pure_manifold", - (pure_manifold ? "Y" : "N")); - CGAL_TC_SET_PERFORMANCE_DATA("Fix2_num_wrong_number_of_cofaces", - num_wrong_number_of_cofaces); - CGAL_TC_SET_PERFORMANCE_DATA("Fix2_time", fix2_time); - CGAL_TC_SET_PERFORMANCE_DATA("Info", ""); + + //=========================================================================== + // 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() @@ -406,7 +548,8 @@ int main() int ambient_dim; int intrinsic_dim; double sparsity; - double time_limit_for_fix; + char perturb, add_high_dim_simpl, collapse; + double time_limit_for_perturb; int num_iteration; sstr >> input; sstr >> param1; @@ -416,7 +559,10 @@ int main() sstr >> ambient_dim; sstr >> intrinsic_dim; sstr >> sparsity; - sstr >> time_limit_for_fix; + 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) @@ -490,7 +636,8 @@ int main() if (!points.empty()) { make_tc(points, intrinsic_dim, sparsity, - time_limit_for_fix, input.c_str()); + perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', + time_limit_for_perturb, input.c_str()); std::cerr << "TC #" << i++ << " done." << std::endl; std::cerr << std::endl << "---------------------------------" From f5e4f541c6a3edab433a311c4f64d45c51dcbc64 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 16:50:54 +0200 Subject: [PATCH 172/269] Added possibility to add noise in the point on sphere generator --- .../test/Tangential_complex/test_utilities.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 1eb2e3ad57d..14e1617ef4d 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -287,9 +287,12 @@ std::vector generate_points_on_moment_curve( template std::vector generate_points_on_sphere_d( - std::size_t num_points, int dim, double radius) + 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 generator(dim, radius); std::vector points; points.reserve(num_points); @@ -299,6 +302,20 @@ std::vector generate_points_on_sphere_d( 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; From bee9976153ce2b492e9133e2580173cecc0a75d5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 16:51:35 +0200 Subject: [PATCH 173/269] Added get_simplices_matching_test() + added checks in add_simplex --- .../Tangential_complex/Simplicial_complex.h | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index dac05d35a89..efd3e7646a0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -34,6 +34,8 @@ #include #include +#include + namespace CGAL { namespace Tangential_complex_ { @@ -43,8 +45,44 @@ public: typedef std::set Simplex; typedef std::set Simplex_range; - void add_simplex(const std::set &s) + void add_simplex( + const std::set &s, bool perform_checks = true) { + if (perform_checks) + { + unsigned int num_pts = static_cast(s.size()); + std::vector 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; + } + // 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::const_iterator it= to_erase.begin(); + it != to_erase.end() ; ++it) + { + m_complex.erase(*it); + } + } m_complex.insert(s); } @@ -58,6 +96,19 @@ public: m_complex.clear(); } + template + 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) From e6cb33d97e0877017377ef33fbadab46c04d0e6c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 16:52:51 +0200 Subject: [PATCH 174/269] Fixed indentation + typo --- .../include/CGAL/Tangential_complex.h | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2f88a7b36cc..c1509942497 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -2820,36 +2820,36 @@ next_face: complex.simplex_range().begin(); typename Simplex_range::const_iterator it_s_end = complex.simplex_range().end(); - // For each triangulation + // For each simplex for ( ; it_s != it_s_end ; ++it_s) { Simplex c = *it_s; - int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue - if (p_simpl_to_color_in_red && - std::find( - p_simpl_to_color_in_red->begin(), - p_simpl_to_color_in_red->end(), - c) != p_simpl_to_color_in_red->end()) - { - color_simplex = 1; - } - else if (p_simpl_to_color_in_green && - std::find( - p_simpl_to_color_in_green->begin(), - p_simpl_to_color_in_green->end(), - c) != p_simpl_to_color_in_green->end()) - { - color_simplex = 2; - } - else if (p_simpl_to_color_in_blue && - std::find( - p_simpl_to_color_in_blue->begin(), - p_simpl_to_color_in_blue->end(), - c) != p_simpl_to_color_in_blue->end()) - { - color_simplex = 3; - } + int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue + if (p_simpl_to_color_in_red && + std::find( + p_simpl_to_color_in_red->begin(), + p_simpl_to_color_in_red->end(), + c) != p_simpl_to_color_in_red->end()) + { + color_simplex = 1; + } + else if (p_simpl_to_color_in_green && + std::find( + p_simpl_to_color_in_green->begin(), + p_simpl_to_color_in_green->end(), + c) != p_simpl_to_color_in_green->end()) + { + color_simplex = 2; + } + else if (p_simpl_to_color_in_blue && + std::find( + p_simpl_to_color_in_blue->begin(), + p_simpl_to_color_in_blue->end(), + c) != p_simpl_to_color_in_blue->end()) + { + color_simplex = 3; + } // Gather the triangles here typedef std::vector Triangles; From 0eff36145c52d596df747b013d86f5a53afa8bda Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 16:53:27 +0200 Subject: [PATCH 175/269] Added a colored export just before collapse --- .../Tangential_complex/benchmark_tc.cpp | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ae2b8310809..ca1513be303 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -127,6 +127,27 @@ protected: 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::max()) + : m_min_allowed_dim(min_allowed_dim), m_max_allowed_dim(max_allowed_dim) + {} + + template + 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; +}; + template bool export_to_off( TC const& tc, @@ -395,11 +416,19 @@ void make_tc(std::vector &points, } complex.display_stats(); + + // Export to OFF with higher-dim simplices colored + std::set > 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, + &higher_dim_simplices); //=========================================================================== // Collapse //=========================================================================== - std::cerr << max_dim << std::endl; if (collapse) complex.collapse(max_dim); @@ -409,7 +438,7 @@ void make_tc(std::vector &points, std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces, num_unconnected_stars; - std::set > wrong_dim_simplices; + std::set > wrong_dim_simplices; std::set > wrong_number_of_cofaces_simplices; std::set > unconnected_stars_simplices; bool is_pure_pseudomanifold = complex.is_pure_pseudomanifold( @@ -607,7 +636,8 @@ int main() { points = generate_points_on_sphere_d( num_points, ambient_dim, - std::atof(param1.c_str())); + std::atof(param1.c_str()), + std::atof(param2.c_str())); } else if (input == "generate_klein_bottle_3D") { From 8ba0ff256672aeca2bf2af5a98ccabcee505cde8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 17:18:49 +0200 Subject: [PATCH 176/269] Updated script --- .../benchmark/Tangential_complex/benchmark_script.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index a26d5085ada..1b050e0eccf 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -15,7 +15,8 @@ #---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ #generate_sphere_d 0.302 - - 70 2 1 0.005 N N Y 60 1 #generate_sphere_d 0.5 - - 70 2 1 0.005 N N Y 60 1 -generate_klein_bottle_4D 40 15 - 130 4 2 0.2 N N Y 60 1 +generate_sphere_d 3 2 - 100 3 2 0.05 N N Y 60 1 +#generate_klein_bottle_4D 40 15 - 130 4 2 0.2 N N Y 60 1 #generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 Y Y Y 60 1 #Takes forever #------------------------------------------------------------------ From files -------------------------------------------------------------------------- From 5aedcaea15eb0c603ef6c6e42a44c52ce82d3613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 23 Apr 2015 15:36:06 +0200 Subject: [PATCH 177/269] Fix compilation issues (cherry picked from commit b02fdcb35398ba5d87ce7ae0523357e3f5d867a2) --- .../include/CGAL/Tangential_complex.h | 39 +++++++++---------- .../CGAL/Tangential_complex/utilities.h | 31 +++++++-------- .../test/Tangential_complex/test_utilities.h | 1 - 3 files changed, 33 insertions(+), 38 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c1509942497..075dbbde152 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -69,8 +69,10 @@ //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) #define CGAL_ALPHA_TC const double ALPHA = 0.3; +#ifdef CGAL_LINKED_WITH_TBB tbb::atomic ttt_star; // CJTODO TEMP tbb::atomic ttt_intersect; +#endif namespace CGAL { @@ -263,7 +265,7 @@ public: void compute_tangential_complex() { -#ifdef CGAL_TC_PROFILING +#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) Wall_clock_timer t; ttt_intersect = 0; ttt_star = 0; @@ -316,7 +318,7 @@ public: #endif } -#ifdef CGAL_TC_PROFILING +#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) std::cerr << "Tangential complex computed in " << t.elapsed() << " seconds." << std::endl; std::cerr << "Intersect: " << ((double)ttt_intersect)/1000000 << " s\n" @@ -1207,10 +1209,11 @@ private: typename Amb_RT_Traits::Dimension, Triangulation_vertex > > Amb_RT; + typedef typename Amb_RT::Weighted_point Amb_RT_Point; typedef typename Amb_RT::Vertex_handle Amb_RT_VH; typedef typename Amb_RT::Full_cell_handle Amb_RT_FCH; //typedef typename Amb_RT::Finite_full_cell_const_iterator Amb_FFC_it; - + typename Kernel::Point_drop_weight_d k_drop_w = m_k.point_drop_weight_d_object(); typename Kernel::Squared_distance_d k_sqdist = @@ -1330,7 +1333,7 @@ private: } else { - Tr_point c = k_power_center( + Amb_RT_Point c = k_power_center( boost::make_transform_iterator( cell->vertices_begin(), vertex_handle_to_point), @@ -1367,10 +1370,10 @@ private: } } -#ifdef CGAL_TC_PROFILING +#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) ttt_star += 1000000*t_star.elapsed(); #endif - + //*************************************************** // Parse the faces of the star and add the ones that are in the // restriction to alpha-Tp @@ -1488,8 +1491,8 @@ next_face: #endif bool does_intersect = does_voronoi_face_and_alpha_tangent_subspace_intersect( - m_points, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); -#ifdef CGAL_TC_PROFILING + m_points, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); +#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) ttt_intersect += 1000000*t_inters.elapsed(); #endif if (does_intersect) @@ -1599,12 +1602,10 @@ next_face: { if (normalize_basis) { - ts.push_back(normalize_vector( - constr_vec( - m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim), - m_k)); + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambient_dim); + ts.push_back(normalize_vector(v, m_k)); } else { @@ -1623,12 +1624,10 @@ next_face: { if (normalize_basis) { - p_orth_space_basis->push_back(normalize_vector( - constr_vec( - m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim), - m_k)); + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(i).data(), + eig.eigenvectors().col(i).data() + m_ambient_dim); + p_orth_space_basis->push_back(normalize_vector(v, m_k)); } else { diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 173b161d5b0..531f3318c1b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -129,13 +129,11 @@ namespace Tangential_complex_ { // Modifies v in-place template - typename K::Vector_d & - normalize_vector( - typename K::Vector_d &v, - K const& k) + typename K::Vector_d& normalize_vector(typename K::Vector_d& v, + K const& k) { v = k.scaled_vector_d_object()( - v, FT(1)/CGAL::sqrt(k.squared_length_d_object()(v))); + v, typename K::FT(1)/CGAL::sqrt(k.squared_length_d_object()(v))); return v; } @@ -145,7 +143,6 @@ namespace Tangential_complex_ { std::vector const& input_basis, K const& k) { - typedef typename K::FT FT; typedef typename K::Vector_d Vector; typedef std::vector Basis; @@ -201,7 +198,7 @@ namespace Tangential_complex_ { } while (std::next_permutation(booleans.begin(), booleans.end())); } - // P: dual face in Delaunay triangulation (p0, p1,… pn) + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P template @@ -216,7 +213,7 @@ namespace Tangential_complex_ { { // Notations: // Fv: Voronoi k-face - // Fd: dual, (D-k)-face of Delaunay (p0, p1,… pn) + // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) typedef typename K::FT FT; typedef typename K::Point_d Point; @@ -244,11 +241,11 @@ namespace Tangential_complex_ { //=========== First set of equations =========== // For point pi in P - // 2(p0 - pi).x = p0˛ - pi˛ + // 2(p0 - pi).x = p0^2 - pi^2 Point const& p0 = center_pt; FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); - for (Indexed_point_range::const_iterator it_p = P.begin(), - it_p_end = P.end() ; + for (typename Indexed_point_range::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { Point const& pi = all_points[*it_p]; @@ -286,9 +283,9 @@ namespace Tangential_complex_ { //=========== Second set of equations =========== // For each point qi in Q - // 2(qi - p0).x <= qi˛ - p0˛ - for (Indexed_point_range_2::const_iterator it_q = Q.begin(), - it_q_end = Q.end() ; + // 2(qi - p0).x <= qi^2 - p0^2 + for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; it_q != it_q_end ; ++it_q) { Point const& qi = all_points[*it_q]; @@ -306,9 +303,9 @@ namespace Tangential_complex_ { // For each vector of OSB // bi.x <= bi.p + alpha // -bi.x <= -bi.p + alpha - for (Vector_range::const_iterator it_osb = - orthogonal_subspace_basis.begin(), - it_osb_end = orthogonal_subspace_basis.end() ; + for (typename Vector_range::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; it_osb != it_osb_end ; ++it_osb) { Vector const& bi = *it_osb; diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 14e1617ef4d..6b0c8c89b4c 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -135,7 +135,6 @@ sparsify_point_set( const Kernel &k, Point_container const& input_pts, typename Kernel::FT min_squared_dist) { - 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::INS_iterator INS_iterator; From b3bd06aa211d025a8cb90bd7c03994d2fd102424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 23 Apr 2015 15:38:28 +0200 Subject: [PATCH 178/269] Fix trailing whitespace (cherry picked from commit 502ab45855e9d5c42660be842f8e27cbe94bea3e) --- .../include/CGAL/Tangential_complex.h | 232 +++++++++--------- .../CGAL/Tangential_complex/utilities.h | 20 +- .../test/Tangential_complex/test_utilities.h | 16 +- 3 files changed, 134 insertions(+), 134 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 075dbbde152..c7ccdecb53d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -89,7 +89,7 @@ public: {} operator std::size_t() { return m_data; } operator std::size_t() const { return m_data; } - + private: std::size_t m_data; }; @@ -193,7 +193,7 @@ class Tangential_complex typedef typename std::vector Tr_container; typedef typename std::vector Vectors; - // An Incident_simplex is the list of the vertex indices + // An Incident_simplex is the list of the vertex indices // except the center vertex typedef std::set Incident_simplex; typedef std::vector Star; @@ -241,7 +241,7 @@ public: {} /// Destructor - ~Tangential_complex() + ~Tangential_complex() { #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) @@ -325,7 +325,7 @@ public: << "Star: " << ((double)ttt_star)/1000000 << " s\n"; #endif } - + void estimate_intrinsic_dimension() { // Kernel functors @@ -389,8 +389,8 @@ public: if (boost::is_convertible::value) { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), - Compute_tangent_triangulation(*this, - true) //tangent_spaces_are_already_computed + Compute_tangent_triangulation(*this, + true) //tangent_spaces_are_already_computed ); } // Sequential @@ -403,12 +403,12 @@ public: compute_alpha_tangent_triangulation(i, ALPHA, true); // tangent_spaces_are_already_computed #else - compute_tangent_triangulation(i, + compute_tangent_triangulation(i, true); // tangent_spaces_are_already_computed #endif } } - + #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex refreshed in " << t.elapsed() @@ -418,10 +418,10 @@ public: // time_limit in seconds: 0 = no fix to do, < 0 = no time limit Fix_inconsistencies_status fix_inconsistencies( - unsigned int &num_steps, + unsigned int &num_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, + std::size_t &best_num_inconsistent_local_tr, + std::size_t &final_num_inconsistent_local_tr, double time_limit = -1.) { if (time_limit == 0.) @@ -429,7 +429,7 @@ public: Wall_clock_timer t; - typename Kernel::Point_drop_weight_d drop_w = + typename Kernel::Point_drop_weight_d drop_w = m_k.point_drop_weight_d_object(); #ifdef CGAL_TC_VERBOSE @@ -460,7 +460,7 @@ public: while (!done) { std::size_t num_inconsistent_local_tr = 0; - + #ifdef CGAL_TC_PROFILING Wall_clock_timer t_fix_step; #endif @@ -484,7 +484,7 @@ public: { for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) { - num_inconsistent_local_tr += + num_inconsistent_local_tr += (try_to_solve_inconsistencies_in_a_local_triangulation(i) ? 1 : 0); } } @@ -503,7 +503,7 @@ public: number_of_inconsistent_simplices(false); std::cerr << std::endl - << "==========================================================" + << "==========================================================" << std::endl << "Inconsistencies (detailed stats):\n" << " * Number of vertices: " << m_points.size() << std::endl @@ -512,12 +512,12 @@ public: << " - Total number of simplices in stars (incl. duplicates): " << stats_before.first << std::endl << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second + << stats_before.second << " (" << 100. * stats_before.second / stats_before.first << "%)" << std::endl << " * Num inconsistent local triangulations: " - << num_inconsistent_local_tr - << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" + << num_inconsistent_local_tr + << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl << std::endl << " * AFTER fix_inconsistencies:" << std::endl @@ -540,7 +540,7 @@ public: << std::endl << "fix_inconsistencies():\n" << " * " << m_points.size() << " vertices" << std::endl - << " * " << num_inconsistent_local_tr + << " * " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << " inconsistent triangulations encountered" << std::endl << "==========================================================" @@ -598,7 +598,7 @@ public: // Don't export infinite cells if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; - + std::set c = *it_inc_simplex; c.insert(idx); // Add the missing index @@ -675,7 +675,7 @@ public: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - inconsistencies_found = + inconsistencies_found = check_and_solve_inconsistencies_by_adding_higher_dim_simplices( idx, *it_inc_simplex); @@ -683,10 +683,10 @@ public: // CJTODO: optimize? if (inconsistencies_found) break; - } + } } while (inconsistencies_found); } - + // CJTODO TEMP std::pair stats_after = number_of_inconsistent_simplices(false); @@ -699,7 +699,7 @@ public: << 100. * stats_after.second / stats_after.first << "%" << std::endl; } - + std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, std::set > const *p_simpl_to_color_in_red = NULL, @@ -711,7 +711,7 @@ public: os, false, p_simpl_to_color_in_red, p_simpl_to_color_in_green, p_simpl_to_color_in_blue, &complex); } - + std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, std::set > const *p_simpl_to_color_in_red = NULL, @@ -816,9 +816,9 @@ public: for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; cit != ambient_dt.finite_full_cells_end() ; ++cit ) { - int lowest_dim = + int lowest_dim = (check_for_any_dimension_simplices ? 1 : m_intrinsic_dimension); - int highest_dim = + int highest_dim = (check_for_any_dimension_simplices ? m_ambient_dim : m_intrinsic_dimension); for (int dim = lowest_dim ; dim <= highest_dim ; ++dim) @@ -838,7 +838,7 @@ public: } //------------------------------------------------------------------------- - // If p_complex is NULL, parse the TC and + // If p_complex is NULL, parse the TC and // save its simplices into "stars_simplices" //------------------------------------------------------------------------- @@ -1012,12 +1012,12 @@ private: // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions const Point center_pt = compute_perturbed_point(i); - + // Estimate the tangent space if (!tangent_spaces_are_already_computed) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, &m_orth_spaces[i]); #else m_tangent_spaces[i] = compute_tangent_space(center_pt); @@ -1027,7 +1027,7 @@ private: else if (m_perturb_tangent_space[i]) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); #else m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); @@ -1075,7 +1075,7 @@ private: // ith point = p, which is already inserted if (neighbor_point_idx != i) { - // No need to lock the Mutex_for_perturb here since this will not be + // No need to lock the Mutex_for_perturb here since this will not be // called while other threads are perturbing the positions Point neighbor_pt; FT neighbor_weight; @@ -1089,7 +1089,7 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, neighbor_weight, center_pt, m_tangent_spaces[i], + neighbor_pt, neighbor_weight, center_pt, m_tangent_spaces[i], local_tr_traits); Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); @@ -1130,7 +1130,7 @@ private: FT sq_power_sphere_diam = 4*point_weight(c); if (!squared_star_sphere_radius_plus_margin - || sq_power_sphere_diam > + || sq_power_sphere_diam > *squared_star_sphere_radius_plus_margin) { squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; @@ -1147,7 +1147,7 @@ private: *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; #else squared_star_sphere_radius_plus_margin = CGAL::square( - CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2*m_half_sparsity); #endif } @@ -1162,7 +1162,7 @@ private: Star &star = m_stars[i]; star.clear(); int cur_dim_plus_1 = local_tr.current_dimension() + 1; - + std::vector incident_cells; local_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); @@ -1199,7 +1199,7 @@ private: bool verbose = false) { if (verbose) - std::cerr << "** Computing alpha tangent tri #" + std::cerr << "** Computing alpha tangent tri #" << i << " **" << std::endl; typedef Regular_triangulation_euclidean_traits Amb_RT_Traits; @@ -1222,7 +1222,7 @@ private: m_k.point_weight_d_object(); typename Kernel::Power_center_d k_power_center = m_k.power_center_d_object(); - + // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions const Point ¢er_pt = m_points[i]; @@ -1231,7 +1231,7 @@ private: if (!tangent_spaces_are_already_computed) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, &m_orth_spaces[i]); #else m_tangent_spaces[i] = compute_tangent_space(center_pt); @@ -1241,7 +1241,7 @@ private: else if (m_perturb_tangent_space[i]) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = + m_tangent_spaces[i] = compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); #else m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); @@ -1254,13 +1254,13 @@ private: // Build a minimal triangulation in the tangent space // (we only need the star of p in the AMBIENT triangulation) //*************************************************** - + #ifdef CGAL_TC_PROFILING Wall_clock_timer t_star; #endif Amb_RT local_amb_tr(m_ambient_dim); - + // Insert p Weighted_point wp = m_k.construct_weighted_point_d_object()( center_pt, @@ -1293,7 +1293,7 @@ private: // ith point = p, which is already inserted if (neighbor_point_idx != i) { - // No need to lock the Mutex_for_perturb here since this will not be + // No need to lock the Mutex_for_perturb here since this will not be // called while other threads are perturbing the positions Weighted_point neighbor_wp = compute_perturbed_weighted_point(neighbor_point_idx); @@ -1344,7 +1344,7 @@ private: FT sq_power_sphere_diam = 4*k_point_weight(c); if (!squared_star_sphere_radius_plus_margin - || sq_power_sphere_diam > + || sq_power_sphere_diam > *squared_star_sphere_radius_plus_margin) { squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; @@ -1361,7 +1361,7 @@ private: *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; #else squared_star_sphere_radius_plus_margin = CGAL::square( - CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2*m_half_sparsity); #endif } @@ -1382,7 +1382,7 @@ private: Star &star = m_stars[i]; star.clear(); int cur_dim_plus_1 = m_ambient_dim + 1; - + std::vector incident_cells; local_amb_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); @@ -1423,7 +1423,7 @@ next_face: int current_dim = m_ambient_dim - 1; while (current_dim > 0) { - // Let's fill faces_and_neighbors[current_dim-1] + // Let's fill faces_and_neighbors[current_dim-1] // (stores the current_dim-faces) DT_faces_and_neighbors& cur_faces_and_nghb = faces_and_neighbors[current_dim-1]; @@ -1435,7 +1435,7 @@ next_face: it_k_p1_face != it_k_p1_face_end ; ++it_k_p1_face) { DT_face const& k_p1_face = it_k_p1_face->first; - + // Add each k faces to cur_faces_and_nghb std::size_t n = current_dim + 1; // Not +2 since 'i' is not stored std::vector booleans(n, false); @@ -1465,7 +1465,7 @@ next_face: current_dim = m_ambient_dim; while (current_dim > 0) { - // Remember: faces_and_neighbors[current_dim-1] stores + // Remember: faces_and_neighbors[current_dim-1] stores // the current_dim-faces DT_faces_and_neighbors const& cur_faces_and_nghb = faces_and_neighbors[current_dim-1]; @@ -1478,7 +1478,7 @@ next_face: Neighbor_vertices const& curr_neighbors = it_f->second; DT_face const& current_DT_face = it_f->first; - CGAL_assertion(static_cast(current_DT_face.size()) + CGAL_assertion(static_cast(current_DT_face.size()) == current_dim); // P: list of current_DT_face points (including 'i') @@ -1498,7 +1498,7 @@ next_face: if (does_intersect) { star.push_back(current_DT_face); - + // Clear all subfaces of current_DT_face from the maps for (int dim = current_dim - 1 ; dim > 0 ; --dim) { @@ -1561,7 +1561,7 @@ next_face: m_k.difference_of_vectors_d_object(); //typename Kernel::Translated_point_d transl = // m_k.translated_point_d_object(); - + #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM KNS_range kns_range = m_points_ds_for_tse.query_ANN( p, NUM_POINTS_FOR_PCA, false); @@ -1596,8 +1596,8 @@ next_face: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues Tangent_space_basis ts; - for (int i = m_ambient_dim - 1 ; - i >= m_ambient_dim - m_intrinsic_dimension ; + for (int i = m_ambient_dim - 1 ; + i >= m_ambient_dim - m_intrinsic_dimension ; --i) { if (normalize_basis) @@ -1618,8 +1618,8 @@ next_face: if (p_orth_space_basis) { - for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; - i >= 0 ; + for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; + i >= 0 ; --i) { if (normalize_basis) @@ -1647,7 +1647,7 @@ next_face: return ts; - + // CJTODO: this is only for a sphere in R^3 /*double tt1[3] = {-p[1] - p[2], p[0], p[0]}; double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], @@ -1710,7 +1710,7 @@ next_face: { typename Kernel::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); - + Weighted_point wp = k_constr_wp( #ifdef CGAL_TC_PERTURB_POSITION m_k.translated_point_d_object()(m_points[pt_idx], m_translations[pt_idx]), @@ -1741,7 +1741,7 @@ next_face: for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_point = k_transl( - global_point, + global_point, k_scaled_vec(tsb[i], coord(p, i))); } @@ -1905,7 +1905,7 @@ next_face: #ifdef CGAL_TC_PERTURB_WEIGHT m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); #endif - + #ifdef CGAL_TC_PERTURB_TANGENT_SPACE m_perturb_tangent_space[point_idx] = true; #endif @@ -1915,7 +1915,7 @@ next_face: # ifdef CGAL_TC_PERTURB_POSITION_GLOBAL typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); - CGAL::Random_points_on_sphere_d + CGAL::Random_points_on_sphere_d tr_point_on_sphere_generator(m_ambient_dim, 1); // Parallel # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) @@ -1931,7 +1931,7 @@ next_face: # endif # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL - const Tr_traits &local_tr_traits = + const Tr_traits &local_tr_traits = m_triangulations[point_idx].tr().geom_traits(); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); @@ -1941,8 +1941,8 @@ next_face: m_k.construct_vector_d_object(); typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - - CGAL::Random_points_on_sphere_d + + CGAL::Random_points_on_sphere_d tr_point_on_sphere_generator(m_intrinsic_dimension, 1); Tr_point local_random_transl = @@ -1953,7 +1953,7 @@ next_face: for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_transl = k_transl( - global_transl, + global_transl, k_scaled_vec(tsb[i], m_half_sparsity*coord(local_random_transl, i)) ); } @@ -1979,7 +1979,7 @@ next_face: #ifdef CGAL_LINKED_WITH_TBB //Tr_mutex::scoped_lock lock(m_tr_mutexes[tr_index]); #endif - + Star const& star = m_stars[tr_index]; Triangulation const& tr = m_triangulations[tr_index].tr(); Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); @@ -2009,12 +2009,12 @@ next_face: { is_inconsistent = true; - for (std::set::const_iterator it = c.begin(); + for (std::set::const_iterator it = c.begin(); it != c.end() ; ++it) { perturb(*it); } - + # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif @@ -2030,7 +2030,7 @@ next_face: if (!is_simplex_consistent(c)) { is_inconsistent = true; - + std::size_t idx = tr_index; /*int k; do @@ -2048,7 +2048,7 @@ next_face: // We will try the other cells next time break; } - + //***************************************************************************** // STRATEGY 3: perturb all the points of the 1-star //***************************************************************************** @@ -2058,22 +2058,22 @@ next_face: if (!is_simplex_consistent(c)) { is_inconsistent = true; - + std::set the_1_star; - + Star::const_iterator it_inc_simplex = star.begin(); Star::const_iterator it_inc_simplex_end = star.end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { the_1_star.insert(it_inc_simplex->begin(), it_inc_simplex ->end()); } - - for (std::set::iterator it = the_1_star.begin() ; + + for (std::set::iterator it = the_1_star.begin() ; it != the_1_star.end() ; ++it) { perturb(*it); } - + # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); # endif @@ -2087,7 +2087,7 @@ next_face: // closest points (to the power center of first the inconsistent cell) //***************************************************************************** #elif defined(CGAL_TC_PERTURB_N_CLOSEST_POINTS) - + // Inconsistent? if (!is_simplex_consistent(c)) { @@ -2098,7 +2098,7 @@ next_face: std::vector simplex_pts; simplex_pts.reserve(c.size()); - + Incident_simplex::const_iterator it_point_idx = c.begin(); Incident_simplex::const_iterator it_point_idx_end = c.end(); // For each point p of the simplex, we reproject it onto the tangent @@ -2126,9 +2126,9 @@ next_face: m_points[tr_index], m_tangent_spaces[tr_index], local_tr_traits); - + KNS_range kns_range = m_points_ds.query_ANN( - global_center, + global_center, CGAL_TC_NUMBER_OF_PERTURBED_POINTS(m_intrinsic_dimension)); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; @@ -2138,8 +2138,8 @@ next_face: neighbors.push_back(nn_it->first); } - for (std::vector::iterator it = neighbors.begin(); - it != neighbors.end() ; + for (std::vector::iterator it = neighbors.begin(); + it != neighbors.end() ; ++it) { perturb(*it); @@ -2244,7 +2244,7 @@ next_face: incident_simplex.erase(index); // Remove the center index Star &star = m_stars[index]; - + std::set::const_iterator it_point_idx = simplex.begin(); std::set::const_iterator it_point_idx_end = simplex.end(); for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) @@ -2256,14 +2256,14 @@ next_face: // Temporarily remove this index incident_simplex.erase(*it_point_idx); // Erase incident_simplex from star - star.erase(std::remove(star.begin(), star.end(), incident_simplex), + star.erase(std::remove(star.begin(), star.end(), incident_simplex), star.end()); incident_simplex.insert(*it_point_idx); } star.push_back(incident_simplex); } - + // Solves one inconsistency // "inconsistent_simplex" must contain p_idx and q_idx // "inconsistent_simplex" must be in star(p) but not in star(q) @@ -2319,16 +2319,16 @@ next_face: const Point pt_p = compute_perturbed_point(p_idx); const Point pt_q = compute_perturbed_point(q_idx); - std::set::const_iterator it_point_idx = + std::set::const_iterator it_point_idx = inconsistent_simplex.begin(); - std::set::const_iterator it_point_idx_end = + std::set::const_iterator it_point_idx_end = inconsistent_simplex.end(); // For each point of the simplex, we reproject it onto the tangent // space. Could be optimized since it's already been computed before. for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { const Weighted_point wp = compute_perturbed_weighted_point(*it_point_idx); - // No need to lock the Mutex_for_perturb here since this will not be + // No need to lock the Mutex_for_perturb here since this will not be // called while other threads are perturbing the positions simplex_pts_in_Tp.push_back(project_point_and_compute_weight( wp, pt_p, m_tangent_spaces[p_idx], q_tr_traits)); @@ -2344,7 +2344,7 @@ next_face: FT circumsphere_sqradius_p = tr_point_weight(Cp); FT circumsphere_sqradius_q = tr_point_weight(Cq); #ifdef CGAL_TC_PERTURB_WEIGHT - FT squared_circumsphere_radius_q_plus_margin = + FT squared_circumsphere_radius_q_plus_margin = circumsphere_sqradius_q + 4*m_sq_half_sparsity; #else FT squared_circumsphere_radius_q_plus_margin = CGAL::square( @@ -2381,7 +2381,7 @@ next_face: //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_Cp_power_sqdist <= FT(0) - && inconsistent_simplex.find(neighbor_point_idx) == + && inconsistent_simplex.find(neighbor_point_idx) == inconsistent_simplex.end()) { std::cerr << "Warning: " << neighbor_point_idx << " is inside Cp with power dist " << point_to_Cp_power_sqdist << "\n"; @@ -2410,7 +2410,7 @@ next_face: global_Cq, compute_perturbed_weighted_point(neighbor_point_idx)); // If the point is ACTUALLY "inside" S if (point_to_Cq_power_sqdist <= FT(0) - && inconsistent_simplex.find(neighbor_point_idx) == + && inconsistent_simplex.find(neighbor_point_idx) == inconsistent_simplex.end()) { inside_pt_indices.push_back(neighbor_point_idx); @@ -2421,7 +2421,7 @@ next_face: typename Tr_traits::Orientation_d orient = q_tr_traits.orientation_d_object(); Orientation o = orient(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); auto p = project_point_and_compute_weight( - compute_perturbed_weighted_point(neighbor_point_idx), + compute_perturbed_weighted_point(neighbor_point_idx), pt_q, m_tangent_spaces[q_idx], q_tr_traits); auto sid = (o == NEGATIVE ? side(simplex_pts_in_Tq.rbegin(), simplex_pts_in_Tq.rend(), p) @@ -2440,9 +2440,9 @@ next_face: } }*/ } - CGAL_assertion_msg(!inside_pt_indices.empty(), + CGAL_assertion_msg(!inside_pt_indices.empty(), "There should be at least one vertex inside the sphere"); - + // CJTODO TEMP DEBUG /*if (inside_pt_indices.empty()) { @@ -2461,7 +2461,7 @@ next_face: // CJTODO TEMP DEBUG if (inside_pt_indices.size() > 1) { - std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " + std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " << inconsistent_simplex.size() - 1 << " simplex\n"; } @@ -2474,13 +2474,13 @@ next_face: //----------------------------------------------------------------------- //5. For each ti, compute the sphere that goes through // p, q, r1, r2..., ri and ti whose center is on (cp, cq) - // We're looking for a point on (Cp, Cq) at equal distance from p and + // We're looking for a point on (Cp, Cq) at equal distance from p and // ti. // The center of the sphere is then: Cp + a(Cq - Cp) // where a = (sqdist(Cp,ti) - sqdist(Cp,p)) / (2*(Cq-Cp).(ti-p)) //6. Keep point ti such as dist(cp, ci) is the smallest //----------------------------------------------------------------------- - + FT min_a = std::numeric_limits::max(); for (auto idx : inside_pt_indices) // CJTODO: C++11 { @@ -2493,11 +2493,11 @@ next_face: const Weighted_point p_w = compute_perturbed_weighted_point(p_idx); const Weighted_point cp_w0 = k_constr_wp(k_drop_w(global_Cp), FT(0)); const Weighted_point wp_w0 = k_constr_wp(k_drop_w(global_Cq), FT(0)); - FT a = + FT a = (k_power_dist(cp_w0, ti_w) - k_power_dist(cp_w0, p_w)) / (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); #else - FT a = + FT a = (k_sqdist(cp, ti) - k_sqdist(cp, pt_p)) / (FT(2)*k_inner_pdct(k_diff_pts(cq, cp), k_diff_pts(ti, pt_p))); #endif @@ -2508,7 +2508,7 @@ next_face: inside_point_idx = idx; } } - + // CJTODO TEMP ==================== /*{ typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); @@ -2535,7 +2535,7 @@ next_face: //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_C_power_sqdist <= FT(-0.000001) - && inconsistent_simplex.find(neighbor_point_idx) == + && inconsistent_simplex.find(neighbor_point_idx) == inconsistent_simplex.end()) { std::cerr << "Warning: " << neighbor_point_idx << " is inside C with power dist " << point_to_C_power_sqdist << "\n"; @@ -2554,14 +2554,14 @@ next_face: //------------------------------------------------------------------------- std::set new_simplex = inconsistent_simplex; new_simplex.insert(inside_point_idx); - + it_point_idx = new_simplex.begin(); it_point_idx_end = new_simplex.end(); for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { insert_higher_dim_simplex_into_star(*it_point_idx, new_simplex); } - // CJTODO: call + // CJTODO: call // check_and_solve_inconsistencies_by_adding_higher_dim_simplices // recursively? Not sure, since the star will be parsed again from // the beginning @@ -2576,7 +2576,7 @@ next_face: bool inconsistencies_found = false; // Don't check infinite simplices - if (*incident_simplex.rbegin() + if (*incident_simplex.rbegin() == std::numeric_limits::max()) return false; @@ -2639,9 +2639,9 @@ next_face: std::stringstream color; //color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156; color << 128 << " " << 128 << " " << 128; - + // Gather the triangles here, with an int telling its color - typedef std::vector, int> > + typedef std::vector, int> > Star_using_triangles; Star_using_triangles star_using_triangles; @@ -2688,7 +2688,7 @@ next_face: color_simplex = 3; } } - + // If m_intrinsic_dimension = 1, each point is output two times, // so we need to multiply each index by 2 // And if only 2 vertices, add a third one (each vertex is duplicated in @@ -2718,7 +2718,7 @@ next_face: { std::set triangle; std::set::iterator it = c.begin(); - for (int i = 0; it != c.end() ; ++i, ++it) + for (int i = 0; it != c.end() ; ++i, ++it) { if (booleans[i]) triangle.insert(*it); @@ -2730,17 +2730,17 @@ next_face: } // For each cell - Star_using_triangles::const_iterator it_simplex = + Star_using_triangles::const_iterator it_simplex = star_using_triangles.begin(); - Star_using_triangles::const_iterator it_simplex_end = + Star_using_triangles::const_iterator it_simplex_end = star_using_triangles.end(); for ( ; it_simplex != it_simplex_end ; ++it_simplex) { // Don't export infinite cells - if (*it_simplex->first.rbegin() + if (*it_simplex->first.rbegin() == std::numeric_limits::max()) continue; - + const std::set &c = it_simplex->first; int color_simplex = it_simplex->second; @@ -2858,7 +2858,7 @@ next_face: // Do not export smaller dimension simplices if (num_vertices < m_intrinsic_dimension + 1) continue; - + // If m_intrinsic_dimension = 1, each point is output two times, // so we need to multiply each index by 2 // And if only 2 vertices, add a third one (each vertex is duplicated in @@ -2888,13 +2888,13 @@ next_face: { std::set triangle; std::set::iterator it = c.begin(); - for (int i = 0; it != c.end() ; ++i, ++it) + for (int i = 0; it != c.end() ; ++i, ++it) { if (booleans[i]) triangle.insert(*it); } triangles.push_back(triangle); - } + } while (std::next_permutation(booleans.begin(), booleans.end())); } @@ -2906,7 +2906,7 @@ next_face: // Don't export infinite cells if (*it_tri->rbegin() == std::numeric_limits::max()) continue; - + os << 3 << " "; std::set::const_iterator it_point_idx = it_tri->begin(); for ( ; it_point_idx != it_tri->end() ; ++it_point_idx) @@ -2952,7 +2952,7 @@ private: const double m_half_sparsity; const double m_sq_half_sparsity; const int m_ambient_dim; - + Points m_points; #ifdef CGAL_TC_PERTURB_WEIGHT Weights_for_perturb m_weights; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 531f3318c1b..fa95f035a41 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -32,7 +32,7 @@ #include #include -#include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) +#include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) // choose exact integral type for QP solver @@ -49,7 +49,7 @@ namespace Tangential_complex_ { // Provides copy constructors to std::atomic so that // it can be used in a vector template - struct Atomic_wrapper + struct Atomic_wrapper : public std::atomic { typedef std::atomic Base; @@ -59,7 +59,7 @@ namespace Tangential_complex_ { Atomic_wrapper(const std::atomic &a) : Base(a.load()) {} Atomic_wrapper(const Atomic_wrapper &other) : Base(other.load()) {} - + Atomic_wrapper &operator=(const T &other) { Base::store(other); @@ -173,7 +173,7 @@ namespace Tangential_complex_ { return output_basis; } - + // CJTODO: use CGAL::Combination_enumerator (cf. Tangential_complex.h) // Compute all the k-combinations of elements // Output_iterator::value_type must be std::set > @@ -200,7 +200,7 @@ namespace Tangential_complex_ { // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template bool does_voronoi_face_and_alpha_tangent_subspace_intersect( Point_range const& all_points, @@ -218,7 +218,7 @@ namespace Tangential_complex_ { typedef typename K::FT FT; typedef typename K::Point_d Point; typedef typename K::Vector_d Vector; - + typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); @@ -229,9 +229,9 @@ namespace Tangential_complex_ { std::size_t card_Q = Q.size(); std::size_t card_OSB = orthogonal_subspace_basis.size(); std::size_t num_couples_among_P = card_P*(card_P-1)/2; - std::size_t num_equations = + std::size_t num_equations = 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; - + // Linear solver typedef CGAL::Quadratic_program Linear_program; typedef CGAL::Quadratic_program_solution LP_solution; @@ -266,7 +266,7 @@ namespace Tangential_complex_ { { Point const& pi = P[pi_pj[0]]; Point const& pj = P[pi_pj[1]]; - + for (int k = 0 ; k < ambient_dim ; ++k) { FT a = 2*(pi[k] + pj[k]); @@ -293,7 +293,7 @@ namespace Tangential_complex_ { for (int k = 0 ; k < ambient_dim ; ++k) lp.set_a(k, current_row, 2*(qi[k] - p0[k])); - lp.set_b(current_row, + lp.set_b(current_row, scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)) - p0_dot_p0); ++current_row; diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 6b0c8c89b4c..695d7a93e86 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -48,7 +48,7 @@ public: // 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, + Point_sparsifier(Point_container &points, FT sparsity = FT(0.05*0.05)) : m_points(points), m_sparsity(sparsity), m_points_ds(NULL) {} @@ -72,7 +72,7 @@ public: return true; } } - + return false; } @@ -141,14 +141,14 @@ sparsify_point_set( 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 output; - + Points_ds points_ds(input_pts); std::vector dropped_points(input_pts.size(), false); @@ -162,7 +162,7 @@ sparsify_point_set( { if (dropped_points[pt_idx]) continue; - + output.push_back(*it_pt); INS_range ins_range = points_ds.query_incremental_ANN(*it_pt); @@ -183,7 +183,7 @@ sparsify_point_set( break; } } - + #ifdef CGAL_TC_PROFILING std::cerr << "Point set sparsified in " << t.elapsed() << " seconds." << std::endl; @@ -277,7 +277,7 @@ std::vector generate_points_on_moment_curve( if (sparsifier.try_to_insert_point(p)) ++i; #else - points.push_back(p); + points.push_back(p); ++i; #endif } @@ -467,7 +467,7 @@ generate_points_on_klein_bottle_variant_5D( 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)) From 213cd0071ae47a7930c1f08f6eb2d5ebacdba959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:20:46 +0200 Subject: [PATCH 179/269] Additional compilation fixes (cherry picked from commit 207f119ab0dcd35a203b4da2d66508ccad927d0c) --- .../include/CGAL/Tangential_complex.h | 15 ++++++++------- .../include/CGAL/Tangential_complex/utilities.h | 5 ++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c7ccdecb53d..7a8d4a20b72 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -38,9 +38,7 @@ #include #include -#ifdef CGAL_TC_PROFILING # include -#endif #include // CJTODO TEMP @@ -258,7 +256,7 @@ public: return m_ambient_dim; } - std::size_t number_of_vertices() + std::size_t number_of_vertices() const { return m_points.size(); } @@ -668,7 +666,7 @@ public: // CJTODO: parallel_for??? for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) { - bool inconsistencies_found; + bool inconsistencies_found = false; do { Star::const_iterator it_inc_simplex = m_stars[idx].begin(); @@ -1123,9 +1121,11 @@ private: { Tr_point c = power_center( boost::make_transform_iterator( - cell->vertices_begin(), vertex_handle_to_point), + cell->vertices_begin(), + vertex_handle_to_point), boost::make_transform_iterator( - cell->vertices_end(), vertex_handle_to_point)); + cell->vertices_end(), + vertex_handle_to_point)); FT sq_power_sphere_diam = 4*point_weight(c); @@ -2482,8 +2482,9 @@ next_face: //----------------------------------------------------------------------- FT min_a = std::numeric_limits::max(); - for (auto idx : inside_pt_indices) // CJTODO: C++11 + for (std::size_t i = 0 ; i < inside_pt_indices.size() ; ++i) { + std::size_t idx = inside_pt_indices[i]; const Point ti = compute_perturbed_point(idx); const Point &cp = k_drop_w(global_Cp); const Point &cq = k_drop_w(global_Cq); diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index fa95f035a41..b575f7ff6f1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -160,11 +160,10 @@ namespace Tangential_complex_ { { Vector u = *inb_it; - typename Basis::iterator outb_it = output_basis.begin(); for (int j = 0 ; j < i ; ++j) { - Vector const& ej = *outb_it; - Vector u_proj = scaled_vec(ej, inner_pdct(u, ej)); + Vector const& ej = input_basis[j]; + Vector u_proj = scaled_vec(ej, inner_pdct(u, ej) / inner_pdct(ej, ej)); u = diff_vec(u, u_proj); } From 2997d7464b72f8501f3b4682c244a14f35142f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:32:12 +0200 Subject: [PATCH 180/269] Adapt TC code to be compatible with the anisotropic mesh algorithms The main changes are : -Points always have a weight (defaulted to 0), but we keep using Points and Weights vectors rather than Weighted_points to ease the interface with ANN queries. -Tangent spaces know a point through which they go to allow them to not necessarily go through their corresponding m_points. -Tangent spaces and weights can be set externally (cherry picked from commit ce8c08a03263e9769c76851a9fc5f63f40f9ac97) --- .../include/CGAL/Tangential_complex.h | 264 +++++++++--------- .../CGAL/Tangential_complex/utilities.h | 99 ++++--- 2 files changed, 192 insertions(+), 171 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7a8d4a20b72..077de236f6e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -128,19 +128,17 @@ class Tangential_complex typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename Tr_traits::Vector_d Tr_vector; - typedef std::vector Tangent_space_basis; - typedef std::vector Orthogonal_space_basis; + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; typedef std::vector Points; - typedef std::vector Weights; - #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) typedef tbb::mutex Mutex_for_perturb; typedef Vector Translation_for_perturb; - typedef std::vector > Weights_for_perturb; + typedef std::vector > Weights; #else typedef Vector Translation_for_perturb; - typedef std::vector Weights_for_perturb; + typedef std::vector Weights; #endif typedef std::vector Translations_for_perturb; @@ -186,8 +184,10 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; +public: typedef typename std::vector TS_container; typedef typename std::vector OS_container; +private: typedef typename std::vector Tr_container; typedef typename std::vector Vectors; @@ -226,17 +226,23 @@ public: m_half_sparsity(0.5*sparsity), m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), m_ambient_dim(k.point_dimension_d_object()(*first)), - m_points(first, last) + m_points(first, last), + m_weights(m_points.size(), FT(0)) # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) # endif , m_points_ds(m_points) + , m_are_tangent_spaces_computed(m_points.size(), false) + , m_tangent_spaces(m_points.size(), Tangent_space_basis()) +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) +#endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) #endif - {} + { } /// Destructor ~Tangential_complex() @@ -261,6 +267,35 @@ public: return m_points.size(); } + void set_weights(std::vector const& weights) + { + m_weights = weights; + } + + void set_tangent_planes(const TS_container& tangent_spaces +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + , const OS_container& orthogonal_spaces +#endif + ) + { +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + std::cerr << "Cannot use CGAL_TC_PERTURB_TANGENT_SPACE and set " + << " tangent spaces manually at the same time" << std::endl; + std::exit(EXIT_FAILURE); +#endif + CGAL_assertion(m_points.size() == tangent_spaces.size() +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + && m_points.size() == orthogonal_spaces.size() +#endif + ); + m_tangent_spaces = tangent_spaces; +#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) + m_orth_spaces = orthogonal_spaces; +#endif + for(std::size_t i=0; i::value) { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), - Compute_tangent_triangulation(*this, - true) //tangent_spaces_are_already_computed + Compute_tangent_triangulation(*this) ); } // Sequential @@ -398,16 +423,13 @@ public: for (std::size_t i = 0 ; i < m_points.size() ; ++i) { #ifdef CGAL_ALPHA_TC - compute_alpha_tangent_triangulation(i, ALPHA, - true); // tangent_spaces_are_already_computed + compute_alpha_tangent_triangulation(i, ALPHA); #else - compute_tangent_triangulation(i, - true); // tangent_spaces_are_already_computed + compute_tangent_triangulation(i); #endif } } - #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex refreshed in " << t.elapsed() << " seconds." << std::endl; @@ -951,22 +973,18 @@ private: class Compute_tangent_triangulation { Tangential_complex & m_tc; - bool m_tangent_spaces_are_already_computed; public: // Constructor Compute_tangent_triangulation( - Tangential_complex &tc, bool tangent_spaces_are_already_computed = false) - : m_tc(tc), - m_tangent_spaces_are_already_computed(tangent_spaces_are_already_computed) - {} + Tangential_complex &tc) + : m_tc(tc) + { } // Constructor Compute_tangent_triangulation(const Compute_tangent_triangulation &ctt) - : m_tc(ctt.m_tc), - m_tangent_spaces_are_already_computed( - ctt.m_tangent_spaces_are_already_computed) - {} + : m_tc(ctt.m_tc) + { } // operator() void operator()( const tbb::blocked_range& r ) const @@ -974,20 +992,16 @@ private: for( size_t i = r.begin() ; i != r.end() ; ++i) { #ifdef CGAL_ALPHA_TC - m_tc.compute_alpha_tangent_triangulation( - i, ALPHA, m_tangent_spaces_are_already_computed); + m_tc.compute_alpha_tangent_triangulation(i, ALPHA); #else - m_tc.compute_tangent_triangulation( - i, m_tangent_spaces_are_already_computed); + m_tc.compute_tangent_triangulation(i); #endif } } }; #endif // CGAL_LINKED_WITH_TBB - void compute_tangent_triangulation( - std::size_t i, bool tangent_spaces_are_already_computed = false, - bool verbose = false) + void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) std::cerr << "** Computing tangent tri #" << i << " **" << std::endl; @@ -1012,23 +1026,28 @@ private: const Point center_pt = compute_perturbed_point(i); // Estimate the tangent space - if (!tangent_spaces_are_already_computed) + if (!m_are_tangent_spaces_computed[i]) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_tangent_spaces[i] = - compute_tangent_space(center_pt, true, &m_orth_spaces[i]); + compute_tangent_space(center_pt, i, true/*normalize*/, &m_orth_spaces[i]); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt); + m_tangent_spaces[i] = compute_tangent_space(center_pt, i); #endif } #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = - compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); + m_tangent_spaces[i] = compute_tangent_space(center_pt, i, + true /*normalize_basis*/, + &m_orth_spaces[i], + true /*perturb*/); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); + m_tangent_spaces[i] = compute_tangent_space(center_pt, i, + true /*normalize_basis*/, + NULL /*ortho basis*/, + true /*perturb*/); #endif m_perturb_tangent_space[i] = false; } @@ -1040,15 +1059,11 @@ private: //*************************************************** // Insert p - Tr_point wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(m_intrinsic_dimension, ORIGIN), -#ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[i] -#else - 0 -#endif - ); - center_vertex = local_tr.insert(wp); + const Weighted_point wp = compute_perturbed_weighted_point(i); + Tr_point proj_wp = project_point_and_compute_weight(wp, m_tangent_spaces[i], + local_tr_traits); + + center_vertex = local_tr.insert(proj_wp); center_vertex->data() = i; if (verbose) std::cerr << "* Inserted point #" << i << std::endl; @@ -1087,7 +1102,7 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, neighbor_weight, center_pt, m_tangent_spaces[i], + neighbor_pt, neighbor_weight, m_tangent_spaces[i], local_tr_traits); Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); @@ -1193,10 +1208,9 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } - - void compute_alpha_tangent_triangulation( - std::size_t i, FT alpha, bool tangent_spaces_are_already_computed = false, - bool verbose = false) +#ifdef CGAL_ALPHA_TC + void compute_alpha_tangent_triangulation(std::size_t i, FT alpha, + bool verbose = false) { if (verbose) std::cerr << "** Computing alpha tangent tri #" @@ -1228,24 +1242,16 @@ private: const Point ¢er_pt = m_points[i]; // Estimate the tangent space - if (!tangent_spaces_are_already_computed) + if (!m_are_tangent_spaces_computed[i]) { -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_tangent_spaces[i] = - compute_tangent_space(center_pt, true, &m_orth_spaces[i]); -#else - m_tangent_spaces[i] = compute_tangent_space(center_pt); -#endif + compute_tangent_space(center_pt, i, true /*normalize*/, &m_orth_spaces[i]); } #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_tangent_spaces[i] = - compute_tangent_space(center_pt, true, &m_orth_spaces[i], true); -#else - m_tangent_spaces[i] = compute_tangent_space(center_pt, true, NULL, true); -#endif + compute_tangent_space(center_pt, i, true, &m_orth_spaces[i], true); m_perturb_tangent_space[i] = false; } #endif @@ -1262,14 +1268,8 @@ private: Amb_RT local_amb_tr(m_ambient_dim); // Insert p - Weighted_point wp = m_k.construct_weighted_point_d_object()( - center_pt, -#ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[i] -#else - 0 -#endif - ); + Weighted_point wp = m_k.construct_weighted_point_d_object()(center_pt, + m_weights[i]); Amb_RT_VH center_vertex = local_amb_tr.insert(wp); center_vertex->data() = i; if (verbose) @@ -1491,7 +1491,8 @@ next_face: #endif bool does_intersect = does_voronoi_face_and_alpha_tangent_subspace_intersect( - m_points, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); + m_points, m_weights, i, P, curr_neighbors, + m_orth_spaces[i], alpha, m_k); #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) ttt_intersect += 1000000*t_inters.elapsed(); #endif @@ -1534,9 +1535,11 @@ next_face: //std::ofstream off_stream_tr(sstr.str()); //CGAL::export_triangulation_to_off(off_stream_tr, local_amb_tr); } +#endif // CGAL_ALPHA_TC Tangent_space_basis compute_tangent_space( const Point &p + , const std::size_t i , bool normalize_basis = true , Orthogonal_space_basis *p_orth_space_basis = NULL #ifdef CGAL_TC_PERTURB_TANGENT_SPACE @@ -1593,9 +1596,10 @@ next_face: Eigen::MatrixXd cov = centered.adjoint() * centered; Eigen::SelfAdjointEigenSolver eig(cov); + Tangent_space_basis tsb(p); // p = compute_perturbed_point(i) here + // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues - Tangent_space_basis ts; for (int i = m_ambient_dim - 1 ; i >= m_ambient_dim - m_intrinsic_dimension ; --i) @@ -1605,11 +1609,11 @@ next_face: Vector v = constr_vec(m_ambient_dim, eig.eigenvectors().col(i).data(), eig.eigenvectors().col(i).data() + m_ambient_dim); - ts.push_back(normalize_vector(v, m_k)); + tsb.push_back(normalize_vector(v, m_k)); } else { - ts.push_back(constr_vec( + tsb.push_back(constr_vec( m_ambient_dim, eig.eigenvectors().col(i).data(), eig.eigenvectors().col(i).data() + m_ambient_dim)); @@ -1618,6 +1622,7 @@ next_face: if (p_orth_space_basis) { + p_orth_space_basis->origin() = p; for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; i >= 0 ; --i) @@ -1639,14 +1644,15 @@ next_face: } } + m_are_tangent_spaces_computed[i] = true; + //************************************************************************* //Vector n = m_k.point_to_vector_d_object()(p); //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; - return ts; - + return tsb; // CJTODO: this is only for a sphere in R^3 /*double tt1[3] = {-p[1] - p[2], p[0], p[0]}; @@ -1677,7 +1683,8 @@ next_face: //ts.reserve(m_intrinsic_dimension); //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); - //return compute_gram_schmidt_basis(ts, m_k); + //ts = compute_gram_schmidt_basis(ts, m_k); + //return ts; */ } @@ -1699,11 +1706,7 @@ next_face: #else p = m_points[pt_idx]; #endif -#ifdef CGAL_TC_PERTURB_WEIGHT w = m_weights[pt_idx]; -#else - w = 0; -#endif } Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) @@ -1717,16 +1720,12 @@ next_face: #else m_points[pt_idx], #endif -#ifdef CGAL_TC_PERTURB_WEIGHT m_weights[pt_idx]); -#else - 0); -#endif return wp; } - Point unproject_point(const Tr_point &p, const Point &origin, + Point unproject_point(const Tr_point &p, const Tangent_space_basis &tsb, const Tr_traits &tr_traits) { @@ -1737,21 +1736,18 @@ next_face: typename Tr_traits::Compute_coordinate_d coord = tr_traits.compute_coordinate_d_object(); - Point global_point = origin; + Point global_point = tsb.origin(); for (int i = 0 ; i < m_intrinsic_dimension ; ++i) - { - global_point = k_transl( - global_point, - k_scaled_vec(tsb[i], coord(p, i))); - } + global_point = k_transl(global_point, + k_scaled_vec(tsb[i], coord(p, i))); return global_point; } // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p - Tr_bare_point project_point(const Point &p, const Point &origin, - const Tangent_space_basis &ts) const + Tr_bare_point project_point(const Point &p, + const Tangent_space_basis &tsb) const { typename Kernel::Scalar_product_d inner_pdct = m_k.scalar_product_d_object(); @@ -1763,9 +1759,9 @@ next_face: coords.reserve(m_intrinsic_dimension); for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { - // Compute the inner product p * ts[i] - Vector v = diff_points(p, origin); - FT coord = inner_pdct(v, ts[i]); + // Local coords are given by the inner product with the vectors of tsb + Vector v = diff_points(p, tsb.origin()); + FT coord = inner_pdct(v, tsb[i]); coords.push_back(coord); } @@ -1774,21 +1770,21 @@ next_face: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p - Tr_point project_point_and_compute_weight( - const Weighted_point &wp, const Point &origin, const Tangent_space_basis &ts, - const Tr_traits &tr_traits) const + Tr_point project_point_and_compute_weight(const Weighted_point &wp, + const Tangent_space_basis &tsb, + const Tr_traits &tr_traits) const { typename Kernel::Point_drop_weight_d k_drop_w = m_k.point_drop_weight_d_object(); typename Kernel::Point_weight_d k_point_weight = m_k.point_weight_d_object(); return project_point_and_compute_weight( - k_drop_w(wp), k_point_weight(wp), origin, ts, tr_traits); + k_drop_w(wp), k_point_weight(wp), tsb, tr_traits); } - Tr_point project_point_and_compute_weight( - const Point &p, FT w, const Point &origin, const Tangent_space_basis &ts, - const Tr_traits &tr_traits) const + Tr_point project_point_and_compute_weight(const Point &p, const FT w, + const Tangent_space_basis &tsb, + const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); typename Kernel::Scalar_product_d inner_pdct = @@ -1798,21 +1794,21 @@ next_face: typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); - Vector v = diff_points(p, origin); + Vector v = diff_points(p, tsb.origin()); std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(ccci(origin), ccci(origin, 0)); + std::vector p_proj(ccci(tsb.origin()), ccci(tsb.origin(), 0)); coords.reserve(m_intrinsic_dimension); for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { - // Compute the inner product p * ts[i] - FT coord = inner_pdct(v, ts[i]); + // Local coords are given by the inner product with the vectors of tsb + FT coord = inner_pdct(v, tsb[i]); coords.push_back(coord); // p_proj += coord * v; for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += coord * ts[i][j]; + p_proj[j] += coord * tsb[i][j]; } Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); @@ -1903,7 +1899,7 @@ next_face: { // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); + m_weights[point_idx] += m_random_generator.get_double(0., m_sq_half_sparsity); #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE @@ -2105,15 +2101,9 @@ next_face: // space. Could be optimized since it's already been computed before. for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { -#ifdef CGAL_TC_PERTURB_WEIGHT - FT w = m_weights[*it_point_idx]; -#else - FT w = 0; -#endif simplex_pts.push_back(project_point_and_compute_weight( - m_points[*it_point_idx], w, - m_points[tr_index], m_tangent_spaces[tr_index], - local_tr_traits)); + m_points[*it_point_idx], m_weights[*it_point_idx], + m_tangent_spaces[tr_index], local_tr_traits)); } typename Tr_traits::Power_center_d power_center = @@ -2123,7 +2113,6 @@ next_face: Point global_center = unproject_point( power_center(simplex_pts.begin(), simplex_pts.end()), - m_points[tr_index], m_tangent_spaces[tr_index], local_tr_traits); @@ -2317,7 +2306,6 @@ next_face: // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions const Point pt_p = compute_perturbed_point(p_idx); - const Point pt_q = compute_perturbed_point(q_idx); std::set::const_iterator it_point_idx = inconsistent_simplex.begin(); @@ -2331,9 +2319,9 @@ next_face: // No need to lock the Mutex_for_perturb here since this will not be // called while other threads are perturbing the positions simplex_pts_in_Tp.push_back(project_point_and_compute_weight( - wp, pt_p, m_tangent_spaces[p_idx], q_tr_traits)); + wp, m_tangent_spaces[p_idx], q_tr_traits)); simplex_pts_in_Tq.push_back(project_point_and_compute_weight( - wp, pt_q, m_tangent_spaces[q_idx], q_tr_traits)); + wp, m_tangent_spaces[q_idx], q_tr_traits)); } Tr_point Cp = tr_power_center( @@ -2352,14 +2340,13 @@ next_face: #endif Weighted_point global_Cp = k_constr_wp( - unproject_point(Cp, pt_p, m_tangent_spaces[p_idx], q_tr_traits), + unproject_point(Cp, m_tangent_spaces[p_idx], q_tr_traits), circumsphere_sqradius_p); Weighted_point global_Cq = k_constr_wp( - unproject_point(Cq, pt_q, m_tangent_spaces[q_idx], q_tr_traits), + unproject_point(Cq, m_tangent_spaces[q_idx], q_tr_traits), circumsphere_sqradius_q); - // CJTODO TEMP ==================== /*{ INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(global_Cp)); @@ -2422,7 +2409,7 @@ next_face: Orientation o = orient(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end()); auto p = project_point_and_compute_weight( compute_perturbed_weighted_point(neighbor_point_idx), - pt_q, m_tangent_spaces[q_idx], q_tr_traits); + m_tangent_spaces[q_idx], q_tr_traits); auto sid = (o == NEGATIVE ? side(simplex_pts_in_Tq.rbegin(), simplex_pts_in_Tq.rend(), p) : side(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end(), p)); @@ -2446,7 +2433,7 @@ next_face: // CJTODO TEMP DEBUG /*if (inside_pt_indices.empty()) { - //compute_tangent_triangulation(q_idx, true, true); + //compute_tangent_triangulation(q_idx, true); std::cerr << "Error: inside_pt_indices.empty()\n"; std::cerr << "Stars:\n"; for (auto s : m_stars[q_idx]) @@ -2955,9 +2942,7 @@ private: const int m_ambient_dim; Points m_points; -#ifdef CGAL_TC_PERTURB_WEIGHT - Weights_for_perturb m_weights; -#endif + Weights m_weights; #ifdef CGAL_TC_PERTURB_POSITION Translations_for_perturb m_translations; # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) @@ -2969,6 +2954,7 @@ private: #endif Points_ds m_points_ds; + mutable std::vector m_are_tangent_spaces_computed; TS_container m_tangent_spaces; #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) OS_container m_orth_spaces; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index b575f7ff6f1..9c26b2c48e2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -137,22 +137,46 @@ namespace Tangential_complex_ { return v; } - template - std::vector - compute_gram_schmidt_basis( - std::vector const& input_basis, - K const& k) + template + struct Basis { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + typedef typename std::vector::const_iterator const_iterator; + + Point m_origin; //fixme should probably be (const?) ref ? + std::vector m_vectors; + + Point& origin() { return m_origin; } + const Point& origin() const { return m_origin; } + 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(const Point& p) : m_origin(p) { } + Basis(const Point& p, const std::vector& vectors) + : m_origin(p), m_vectors(vectors) + { } + }; + + template + Basis compute_gram_schmidt_basis(Basis const& input_basis, K const& k) + { + typedef Basis Basis; typedef typename K::Vector_d Vector; - typedef std::vector Basis; // Kernel functors - typename K::Squared_length_d sqlen = k.squared_length_d_object(); typename K::Scaled_vector_d scaled_vec = k.scaled_vector_d_object(); typename K::Scalar_product_d inner_pdct = k.scalar_product_d_object(); typename K::Difference_of_vectors_d diff_vec = k.difference_of_vectors_d_object(); - Basis output_basis; + Basis output_basis(input_basis.origin()); typename Basis::const_iterator inb_it = input_basis.begin(); typename Basis::const_iterator inb_it_end = input_basis.end(); @@ -199,16 +223,18 @@ namespace Tangential_complex_ { // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template + template bool does_voronoi_face_and_alpha_tangent_subspace_intersect( - Point_range const& all_points, - std::size_t center_pt_index, - Indexed_point_range const& P, - Indexed_point_range_2 const& Q, - Vector_range const& orthogonal_subspace_basis, - typename K::FT alpha, - K const& k) + Point_range const& all_points, + Weight_range const& all_weights, + std::size_t center_pt_index, + Indexed_point_range const& P, + Indexed_point_range_2 const& Q, + Basis const& orthogonal_subspace_basis, + typename K::FT alpha, + K const& k) { // Notations: // Fv: Voronoi k-face @@ -220,9 +246,10 @@ namespace Tangential_complex_ { typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); + typename K::Compute_coordinate_d coord = k.compute_coordinate_d_object(); Point const& center_pt = all_points[center_pt_index]; - const int ambient_dim = k.point_dimension_d_object()(center_pt); + int const ambient_dim = k.point_dimension_d_object()(center_pt); std::size_t card_P = P.size(); std::size_t card_Q = Q.size(); @@ -239,21 +266,24 @@ namespace Tangential_complex_ { int current_row = 0; //=========== First set of equations =========== - // For point pi in P - // 2(p0 - pi).x = p0^2 - pi^2 + // For points pi in P + // 2(p0 - pi).x = p0^2 - w0 - pi^2 + wi Point const& p0 = center_pt; + FT const w0 = all_weights[center_pt_index]; FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); + for (typename Indexed_point_range::const_iterator it_p = P.begin(), it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { Point const& pi = all_points[*it_p]; + FT const wi = all_weights[*it_p]; for (int k = 0 ; k < ambient_dim ; ++k) - lp.set_a(k, current_row, 2*(p0[k] - pi[k])); + lp.set_a(k, current_row, 2*(coord(p0, k) - coord(pi, k))); - lp.set_b(current_row, - p0_dot_p0 - scalar_pdct(pt_to_vec(pi), pt_to_vec(pi))); + FT pi_dot_pi = scalar_pdct(pt_to_vec(pi), pt_to_vec(pi)); + lp.set_b(current_row, p0_dot_p0 - pi_dot_pi - w0 + wi); lp.set_r(current_row, CGAL::EQUAL); ++current_row; @@ -264,16 +294,18 @@ namespace Tangential_complex_ { for ( ; !pi_pj.finished() ; ++pi_pj) { Point const& pi = P[pi_pj[0]]; + FT wi = all_weights[pi_pj[0]]; Point const& pj = P[pi_pj[1]]; + FT wj = all_weights[pi_pj[1]]; for (int k = 0 ; k < ambient_dim ; ++k) { - FT a = 2*(pi[k] + pj[k]); + FT a = 2*(coord(pi, k) + coord(pj, k)); lp.set_a(k, current_row , -a); lp.set_a(k, current_row + 1, a); } - FT b = scalar_pdct(pi, pi) - scalar_pdct(pj, pj); + FT b = scalar_pdct(pi, pi) - wi - scalar_pdct(pj, pj) + wj; lp.set_b(current_row , -b); lp.set_b(current_row + 1, b); @@ -282,27 +314,29 @@ namespace Tangential_complex_ { //=========== Second set of equations =========== // For each point qi in Q - // 2(qi - p0).x <= qi^2 - p0^2 + // 2(qi - p0).x <= qi^2 - wi - p0^2 + w0 for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), it_q_end = Q.end() ; it_q != it_q_end ; ++it_q) { Point const& qi = all_points[*it_q]; + FT const wi = all_weights[*it_q]; for (int k = 0 ; k < ambient_dim ; ++k) - lp.set_a(k, current_row, 2*(qi[k] - p0[k])); + lp.set_a(k, current_row, 2*(coord(qi, k) - coord(p0, k))); - lp.set_b(current_row, - scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)) - p0_dot_p0); + FT qi_dot_qi = scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)); + lp.set_b(current_row, qi_dot_qi - wi - p0_dot_p0 + w0); ++current_row; } //=========== Third set of equations =========== - // For each vector of OSB + // For each vector bi of OSB, (x-p).bi <= alpha and >= -alpha + // p is the origin of the basis // bi.x <= bi.p + alpha // -bi.x <= -bi.p + alpha - for (typename Vector_range::const_iterator it_osb = + for (typename Basis::const_iterator it_osb = orthogonal_subspace_basis.begin(), it_osb_end = orthogonal_subspace_basis.end() ; it_osb != it_osb_end ; ++it_osb) @@ -315,7 +349,8 @@ namespace Tangential_complex_ { lp.set_a(k, current_row + 1, -bi[k]); } - FT bi_dot_p = scalar_pdct(bi, pt_to_vec(center_pt)); + Point const& basis_origin = orthogonal_subspace_basis.origin(); + FT bi_dot_p = scalar_pdct(bi, pt_to_vec(basis_origin)); lp.set_b(current_row , bi_dot_p + alpha); lp.set_b(current_row + 1, -bi_dot_p + alpha); From 17739d847deebd839647fdaf9f76a7c2463f794d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:39:40 +0200 Subject: [PATCH 181/269] Clean code (trailing whitespace, indentation, etc.) (cherry picked from commit 75b44442cfbc4ba8b69160b98b8115ceda7d07ef) --- .../Tangential_complex/benchmark_tc.cpp | 36 ++++++++-------- .../include/CGAL/Tangential_complex.h | 42 +++++++------------ .../Tangential_complex/Simplicial_complex.h | 42 +++++++++---------- .../include/CGAL/Tangential_complex/config.h | 2 +- .../test_tangential_complex.cpp | 8 ++-- 5 files changed, 58 insertions(+), 72 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ca1513be303..548f0c48949 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -35,7 +35,7 @@ typedef CGAL::Epick_d Kernel; typedef Kernel::FT FT; typedef Kernel::Point_d Point; typedef CGAL::Tangential_complex< - Kernel, CGAL::Dynamic_dimension_tag, + Kernel, CGAL::Dynamic_dimension_tag, CGAL::Parallel_tag> TC; class XML_perf_data @@ -248,18 +248,18 @@ void make_tc(std::vector &points, slash_index, input_name_stripped.find_last_of('.') - slash_index); int ambient_dim = k.point_dimension_d_object()(*points.begin()); - + #ifdef CGAL_TC_PROFILING Wall_clock_timer t_gen; #endif - + #ifdef CGAL_TC_PROFILING std::cerr << "Point set generated in " << t_gen.elapsed() << " seconds." << std::endl; #endif - + CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); - + #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM std::vector points_not_sparse = points; #endif @@ -277,7 +277,7 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity); CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size()); - + //=========================================================================== // Compute Tangential Complex //=========================================================================== @@ -293,7 +293,7 @@ void make_tc(std::vector &points, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - + //=========================================================================== // CJTODO TEMP //=========================================================================== @@ -364,7 +364,7 @@ void make_tc(std::vector &points, best_num_inconsistent_local_tr); CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", final_num_inconsistent_local_tr); - + //========================================================================= // Export to OFF //========================================================================= @@ -379,7 +379,7 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", "N/A"); CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", "N/A"); } - + int max_dim = -1; double fix2_time = -1; double export_after_fix2_time = -1.; @@ -431,7 +431,7 @@ void make_tc(std::vector &points, //=========================================================================== if (collapse) complex.collapse(max_dim); - + //=========================================================================== // Is the result a pure pseudomanifold? //=========================================================================== @@ -480,8 +480,8 @@ void make_tc(std::vector &points, << " - Init + kd-tree = " << init_time << std::endl << " - TC computation = " << computation_time << std::endl << " * Export to OFF (before perturb): " << export_before_time << std::endl - << " * Fix inconsistencies 1: " << perturb_time - << " (" << num_perturb_steps << " steps) ==> " + << " * Fix inconsistencies 1: " << perturb_time + << " (" << num_perturb_steps << " steps) ==> " << (perturb_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl << " * Fix inconsistencies 2: " << fix2_time << std::endl << " * Export to OFF (after perturb): " << export_after_perturb_time << std::endl @@ -525,7 +525,7 @@ int main() int seed = CGAL::default_random.get_int(0, 1<<30); CGAL::default_random = CGAL::Random(); std::cerr << "Random seed = " << seed << std::endl; - + std::ifstream script_file; script_file.open(BENCHMARK_SCRIPT_FILENAME); // Script? @@ -619,13 +619,13 @@ int main() #endif std::cerr << std::endl << "TC #" << i << "..." << std::endl; - + std::vector points; if (input == "generate_moment_curve") { points = generate_points_on_moment_curve( - num_points, ambient_dim, + num_points, ambient_dim, std::atof(param1.c_str()), std::atof(param2.c_str())); } else if (input == "generate_plane") @@ -635,7 +635,7 @@ int main() else if (input == "generate_sphere_d") { points = generate_points_on_sphere_d( - num_points, ambient_dim, + num_points, ambient_dim, std::atof(param1.c_str()), std::atof(param2.c_str())); } @@ -665,12 +665,12 @@ int main() if (!points.empty()) { - make_tc(points, intrinsic_dim, sparsity, + make_tc(points, intrinsic_dim, sparsity, perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', time_limit_for_perturb, input.c_str()); std::cerr << "TC #" << i++ << " done." << std::endl; - std::cerr << std::endl << "---------------------------------" + std::cerr << std::endl << "---------------------------------" << std::endl << std::endl; } else diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 077de236f6e..dd9c1fe3f8e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -94,8 +94,8 @@ private: /// The class Tangential_complex represents a tangential complex template < - typename Kernel, - typename DimensionTag, + typename Kernel, // ambiant dimension + typename DimensionTag, // intrinsic dimension typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Regular_triangulation < @@ -209,7 +209,6 @@ private: } public: - typedef Tangential_complex_::Simplicial_complex Simplicial_complex; /// Constructor for a range of points @@ -366,10 +365,8 @@ public: for ( ; it_p != it_p_end ; ++it_p) { const Point &p = *it_p; - - KNS_range kns_range = m_points_ds.query_ANN( - p, NUM_POINTS_FOR_PCA, false); + KNS_range kns_range = m_points_ds.query_ANN(p, NUM_POINTS_FOR_PCA, false); //******************************* PCA ************************************* // One row = one point @@ -388,7 +385,6 @@ public: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues - Tangent_space_basis ts; for (int i = 0 ; i < m_ambient_dim ; ++i) sum_eigen_values[i] += eig.eigenvalues()[i]; @@ -449,9 +445,6 @@ public: Wall_clock_timer t; - typename Kernel::Point_drop_weight_d drop_w = - m_k.point_drop_weight_d_object(); - #ifdef CGAL_TC_VERBOSE std::cerr << "Fixing inconsistencies..." << std::endl; #endif @@ -590,7 +583,6 @@ public: return TC_FIXED; } - // Return a pair std::pair number_of_inconsistent_simplices( #ifdef CGAL_TC_VERBOSE @@ -607,9 +599,6 @@ public: // For each triangulation for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { - Triangulation const& tr = it_tr->tr(); - Tr_vertex_handle center_vh = it_tr->center_vertex(); - // For each cell Star::const_iterator it_inc_simplex = m_stars[idx].begin(); Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); @@ -660,8 +649,6 @@ public: // For each triangulation for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) { - Triangulation const& tr = it_tr->tr(); - // For each cell of the star Star::const_iterator it_inc_simplex = m_stars[idx].begin(); Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); @@ -843,8 +830,7 @@ public: for (int dim = lowest_dim ; dim <= highest_dim ; ++dim) { - CGAL::Combination_enumerator combi( - dim + 1, 0, m_ambient_dim + 1); + CGAL::Combination_enumerator combi(dim + 1, 0, m_ambient_dim + 1); for ( ; !combi.finished() ; ++combi) { @@ -1401,7 +1387,7 @@ private: // Fill faces_and_neighbors // Let's first take care of the D-faces typename std::vector::const_iterator it_c = incident_cells.begin(); - typename std::vector::const_iterator it_c_end= incident_cells.end(); + typename std::vector::const_iterator it_c_end = incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { @@ -1694,7 +1680,7 @@ next_face: return m_k.translated_point_d_object()( m_points[pt_idx], m_translations[pt_idx]); #else - return m_points[pt_idx]; + return m_points[pt_idx]; #endif } @@ -1914,17 +1900,17 @@ next_face: CGAL::Random_points_on_sphere_d tr_point_on_sphere_generator(m_ambient_dim, 1); // Parallel -# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) - Vector transl = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), m_half_sparsity); +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) + Vector transl = k_scaled_vec(k_pt_to_vec(*tr_point_on_sphere_generator++), + m_half_sparsity); m_p_perturb_mutexes[point_idx].lock(); m_translations[point_idx] = transl; m_p_perturb_mutexes[point_idx].unlock(); // Sequential -# else +# else m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( *tr_point_on_sphere_generator++), m_half_sparsity); -# endif +# endif # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL const Tr_traits &local_tr_traits = @@ -1954,14 +1940,14 @@ next_face: ); } // Parallel -# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) +# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) m_p_perturb_mutexes[point_idx].lock(); m_translations[point_idx] = global_transl; m_p_perturb_mutexes[point_idx].unlock(); // Sequential -# else +# else m_translations[point_idx] = global_transl; -# endif +# endif # endif // CGAL_TC_PERTURB_POSITION_TANGENTIAL #endif // CGAL_TC_PERTURB_POSITION diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index efd3e7646a0..73422444aa2 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -119,7 +119,7 @@ public: #endif // We note k = max_simplex_dim - 1 int k = max_simplex_dim - 1; - + typedef Complex::iterator Simplex_iterator; typedef std::vector Simplex_iterator_list; typedef std::map Cofaces_map; @@ -127,9 +127,9 @@ public: // 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(), + for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; - it_simplex != it_simplex_end ; + it_simplex != it_simplex_end ; ++it_simplex) { if (it_simplex->size() > k + 1) @@ -157,7 +157,7 @@ public: if (it_map_elt->second.size() == 1) { std::vector k_faces; - const Simplex_iterator_list::value_type &it_Cf = + 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 @@ -177,10 +177,10 @@ public: { Simplex_iterator_list::iterator it = std::find( it_comb_in_map->second.begin(), - it_comb_in_map->second.end(), + it_comb_in_map->second.end(), it_Cf); CGAL_assertion(it != it_comb_in_map->second.end()); - it_comb_in_map->second.erase(it); + it_comb_in_map->second.erase(it); } } } @@ -201,8 +201,8 @@ public: void display_stats() const { std::cerr << "==========================================================\n"; - std::cerr << "Complex stats:\n"; - + std::cerr << "Complex stats:\n"; + if (m_complex.empty()) { std::cerr << "No simplices.\n"; @@ -212,18 +212,18 @@ public: // Number of simplex for each dimension std::map simplex_stats; - for (Complex::const_iterator it_simplex = m_complex.begin(), + for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; - it_simplex != it_simplex_end ; + it_simplex != it_simplex_end ; ++it_simplex) { ++simplex_stats[static_cast(it_simplex->size()) - 1]; } - + for (std::map::const_iterator it_map = simplex_stats.begin() ; it_map != simplex_stats.end() ; ++it_map) { - std::cerr << " * " << it_map->first << "-simplices: " + std::cerr << " * " << it_map->first << "-simplices: " << it_map->second << std::endl; } } @@ -234,31 +234,31 @@ public: // verbose_level = 0, 1 or 2 bool is_pure_pseudomanifold__do_not_check_if_stars_are_connected( int simplex_dim, - bool exit_at_the_first_problem = 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) { typedef std::set K_1_face; typedef std::map 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(), + for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; - it_simplex != it_simplex_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 = " + std::cerr << "Found a simplex with dim = " << it_simplex->size() - 1 << std::endl; ++num_wrong_dim_simplices; } @@ -283,7 +283,7 @@ public: if (it_map_elt->second != 2) { if (verbose_level >= 2) - std::cerr << "Found a k-1-face with " + std::cerr << "Found a k-1-face with " << it_map_elt->second << " cofaces\n"; if (exit_at_the_first_problem) @@ -300,9 +300,9 @@ public: std::cerr << "is_pure_manifold: " << (ret ? "YES" : "NO") << std::endl; if (!ret) { - std::cerr << " * Number of wrong dimension simplices: " + std::cerr << " * Number of wrong dimension simplices: " << num_wrong_dim_simplices << std::endl - << " * Number of wrong number of cofaces: " + << " * Number of wrong number of cofaces: " << num_wrong_number_of_cofaces << std::endl; } } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 1ba33d4eead..9c53d41b69b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -23,7 +23,7 @@ #include -// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false +// 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 diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index cc9536db937..691f5429c78 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -52,9 +52,9 @@ int main() typedef Kernel::FT FT; typedef Kernel::Point_d Point; typedef CGAL::Tangential_complex< - Kernel, CGAL::Dimension_tag, + Kernel, CGAL::Dimension_tag, CGAL::Parallel_tag> TC; - + int i = 0; bool stop = false; //for ( ; !stop ; ++i) @@ -149,8 +149,8 @@ int main() << " - 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 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 From b4f28869cff635fa20906541693e37bffc5c4160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:40:53 +0200 Subject: [PATCH 182/269] Add an example of aniso meshing with /Tangential_complex (first draft, missing a couple functions) (cherry picked from commit a6fdf30f850fbbf8cf3a3c0da902bda258c4fb41) --- .../test/Tangential_complex/CMakeLists.txt | 2 + .../test/Tangential_complex/aniso_TC.cpp | 271 ++++++++++++++++++ 2 files changed, 273 insertions(+) create mode 100644 Tangential_complex/test/Tangential_complex/aniso_TC.cpp diff --git a/Tangential_complex/test/Tangential_complex/CMakeLists.txt b/Tangential_complex/test/Tangential_complex/CMakeLists.txt index 230af037117..b0cf36ef8ee 100644 --- a/Tangential_complex/test/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/test/Tangential_complex/CMakeLists.txt @@ -62,11 +62,13 @@ if ( CGAL_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() diff --git a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp new file mode 100644 index 00000000000..09534985fef --- /dev/null +++ b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp @@ -0,0 +1,271 @@ +#include +#include +#include +#include + +#include "../../test/Tangential_complex/test_utilities.h" + +#include // Anisotropic metrics + +#include +#include +#include + +const int k = 2; // intrinsic +const int d = 5; // ambiant + +typedef CGAL::Epick_d< CGAL::Dimension_tag > Kk; +typedef CGAL::Epick_d< CGAL::Dimension_tag > 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, + CGAL::Parallel_tag> TC; + +typedef CGAL::Tangential_complex_::Basis Basis; +typedef CGAL::Anisotropic_mesh_TC::Metric_base Metric; +typedef CGAL::Anisotropic_mesh_TC::Metric_field Metric_field; + +typedef typename Metric::E_Matrix E_Matrix_k; +typedef typename Metric::E_Vector E_Vector_k; +typedef Eigen::Matrix E_Vector_d; +typedef Eigen::Matrix E_Matrix_dk; + +void read_points(std::vector& 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 ids; + for(int j=0; j> 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 const & points_k, + Metric_field const * const mf, + std::vector& points_d, + std::vector& 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; icompute_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& 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& points_k, + Metric_field const * const mf) +{ + Kd ker_d; + + std::vector points_d; + std::vector 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(); + + translate_connectivity_to_original_point_set(); + return; +} + +int main() +{ + CGAL::default_random = CGAL::Random(); + std::vector points_k; + + Metric_field* mf = NULL; + + read_points(points_k); + make_tc(points_k, mf); + + return 0; +} From 83e01e3a910c0942f2378ab8d56b8f4c41e03bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 26 Apr 2015 17:57:40 +0200 Subject: [PATCH 183/269] Add a tiny comment (cherry picked from commit 5a3b3edd6a6cbab4f5d56b08474ef8f4b4cbab7b) --- Tangential_complex/include/CGAL/Tangential_complex.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index dd9c1fe3f8e..f561db9e546 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1283,6 +1283,12 @@ private: // called while other threads are perturbing the positions Weighted_point neighbor_wp = compute_perturbed_weighted_point(neighbor_point_idx); +// fixme ? +// Above seems incorrect since we later pass m_points[] to +// "does_voronoi_face_and_alpha_tangent_subspace_intersect()" and we lose +// the possible position pertubation of wp. +// Either we ignore the translations and it's neighbor_wp = points[idx]+weight +// or need to give m_translations to the voronoi intersections computations // "4*m_sq_half_sparsity" because both points can be perturbed if (squared_star_sphere_radius_plus_margin From ff00de4e22015c455d925fefa97b6a43e67a46f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 27 Apr 2015 14:28:29 +0200 Subject: [PATCH 184/269] Fix const correctness (cherry picked from commit 6b52e73a677f322bf3a2f17ec9eee7106b44d924) --- .../include/CGAL/Tangential_complex.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f561db9e546..3568ca7e5a4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -351,7 +351,7 @@ public: #endif } - void estimate_intrinsic_dimension() + void estimate_intrinsic_dimension() const { // Kernel functors typename Kernel::Compute_coordinate_d coord = @@ -590,7 +590,7 @@ public: #else bool verbose = false #endif - ) + ) const { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; @@ -787,7 +787,7 @@ public: bool check_if_all_simplices_are_in_the_ambient_delaunay( const Simplicial_complex *p_complex = NULL, bool check_for_any_dimension_simplices = true, - std::set > * incorrect_simplices = NULL) + std::set > * incorrect_simplices = NULL) const { typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; @@ -1537,7 +1537,7 @@ next_face: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE , bool perturb = false #endif - ) const + ) { //******************************* PCA ************************************* @@ -1690,7 +1690,7 @@ next_face: #endif } - void compute_perturbed_weighted_point(std::size_t pt_idx, Point &p, FT &w) + void compute_perturbed_weighted_point(std::size_t pt_idx, Point &p, FT &w) const { #ifdef CGAL_TC_PERTURB_POSITION p = m_k.translated_point_d_object()( @@ -1701,7 +1701,7 @@ next_face: w = m_weights[pt_idx]; } - Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) + Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) const { typename Kernel::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); @@ -1719,7 +1719,7 @@ next_face: Point unproject_point(const Tr_point &p, const Tangent_space_basis &tsb, - const Tr_traits &tr_traits) + const Tr_traits &tr_traits) const { typename Kernel::Translated_point_d k_transl = m_k.translated_point_d_object(); @@ -2781,6 +2781,7 @@ next_face: return os; } +public: std::ostream &export_simplices_to_off( const Simplicial_complex &complex, std::ostream & os, std::size_t &num_simplices, @@ -2946,7 +2947,7 @@ private: #endif Points_ds m_points_ds; - mutable std::vector m_are_tangent_spaces_computed; + std::vector m_are_tangent_spaces_computed; TS_container m_tangent_spaces; #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) OS_container m_orth_spaces; From 3a2a4f1863c84c5b381b25111b3026b814d0e970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 27 Apr 2015 18:55:54 +0200 Subject: [PATCH 185/269] Added the necessary functions for aniso using /Tangential_complex Non-alpha version for now. /Anisotropic_mesh_TC and aniso using /Tangential_complex give the same results (which is a good thing). (cherry picked from commit 1fe5556389966b912234dafe2be54502d6398c34) --- .../test/Tangential_complex/aniso_TC.cpp | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp index 09534985fef..586c63b0bdc 100644 --- a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp +++ b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp @@ -6,6 +6,8 @@ #include "../../test/Tangential_complex/test_utilities.h" #include // Anisotropic metrics +#include +#include #include #include @@ -34,6 +36,9 @@ typedef typename Metric::E_Vector E_Vector_k; typedef Eigen::Matrix E_Vector_d; typedef Eigen::Matrix E_Matrix_dk; +typedef CGAL::Anisotropic_mesh_TC::Euclidean_metric_field Euclidean_mf; +typedef CGAL::Anisotropic_mesh_TC::Custom_metric_field Custom_mf; + void read_points(std::vector& points, const Kk kerk = Kk()) { @@ -169,12 +174,13 @@ void compute_and_set_tangent_planes(TC& tc, E_Matrix_dk ts_m = E_Matrix_dk::Zero(); // 'first' part: x y z etc. derivates for(int i=0; i& 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, @@ -253,7 +278,7 @@ void make_tc(std::vector& points_k, &num_wrong_number_of_cofaces); complex.display_stats(); - translate_connectivity_to_original_point_set(); + export_complex_in_origin_space(tc, complex, points_k); return; } @@ -262,7 +287,8 @@ int main() CGAL::default_random = CGAL::Random(); std::vector points_k; - Metric_field* mf = NULL; + //Custom_mf* mf = new Custom_mf(); + Euclidean_mf* mf = new Euclidean_mf(); read_points(points_k); make_tc(points_k, mf); From 05500a49e02969889a6995c85db741668236d93f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 28 Apr 2015 11:52:53 +0200 Subject: [PATCH 186/269] Add point weights memory This is done to prevent consecutive weight perturbations from accumulating (cherry picked from commit 6f23a80ae682d515b301e0ac6c7f068005e18a64) --- .../include/CGAL/Tangential_complex.h | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3568ca7e5a4..652777aeb66 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -136,9 +136,15 @@ class Tangential_complex typedef tbb::mutex Mutex_for_perturb; typedef Vector Translation_for_perturb; typedef std::vector > Weights; + #ifdef CGAL_TC_PERTURB_WEIGHT + typedef std::vector > Weights_memory; + #endif #else typedef Vector Translation_for_perturb; typedef std::vector Weights; + #ifdef CGAL_TC_PERTURB_WEIGHT + typedef std::vector Weights_memory; + #endif #endif typedef std::vector Translations_for_perturb; @@ -227,6 +233,9 @@ public: m_ambient_dim(k.point_dimension_d_object()(*first)), m_points(first, last), m_weights(m_points.size(), FT(0)) +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights_memory(m_points.size(), FT(0)) +#endif # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) @@ -266,9 +275,12 @@ public: return m_points.size(); } - void set_weights(std::vector const& weights) + void set_weights(const Weights& weights) { m_weights = weights; +#ifdef CGAL_TC_PERTURB_WEIGHT + m_weights_memory = weights; +#endif } void set_tangent_planes(const TS_container& tangent_spaces @@ -1891,7 +1903,8 @@ next_face: { // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] += m_random_generator.get_double(0., m_sq_half_sparsity); + m_weights[point_idx] = m_weights_memory[point_idx] + + m_random_generator.get_double(0., m_sq_half_sparsity); #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE @@ -2936,6 +2949,9 @@ private: Points m_points; Weights m_weights; +#ifdef CGAL_TC_PERTURB_WEIGHT + Weights_memory m_weights_memory; +#endif #ifdef CGAL_TC_PERTURB_POSITION Translations_for_perturb m_translations; # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) From 9cfc9ea8ea4b9b56a303a1652af3ce0144489f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 28 Apr 2015 16:31:06 +0200 Subject: [PATCH 187/269] Avoid an unecessary initialization If external weights aren't set, the memory vector of weights will be full of 0 and isn't needed. (cherry picked from commit f6a4ba6169d792bf73a9121a7102d11a53469e24) --- Tangential_complex/include/CGAL/Tangential_complex.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 652777aeb66..5aee87487f8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -234,7 +234,7 @@ public: m_points(first, last), m_weights(m_points.size(), FT(0)) #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights_memory(m_points.size(), FT(0)) + m_weights_memory() #endif # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) @@ -1903,8 +1903,9 @@ next_face: { // Perturb the weight? #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights[point_idx] = m_weights_memory[point_idx] + - m_random_generator.get_double(0., m_sq_half_sparsity); + m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); + if(m_weights_memory.size() > 0) // external weights were initially set + m_weights[point_idx] += m_weights_memory[point_idx] #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE From 7ff3c99876fc6eb00a4ea1eb5e189a4379eeae3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 28 Apr 2015 18:59:25 +0200 Subject: [PATCH 188/269] Avoid an unnecessary projection on tangent planes If the center of the star is the origin of the tangent basis, there is no need to compute a projection (it'll be the origin, locally) (cherry picked from commit e04c440477a43498aa79fa10e36f07893bcf572b) --- .../include/CGAL/Tangential_complex.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5aee87487f8..e035aa7c77c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1057,9 +1057,21 @@ private: //*************************************************** // Insert p - const Weighted_point wp = compute_perturbed_weighted_point(i); - Tr_point proj_wp = project_point_and_compute_weight(wp, m_tangent_spaces[i], - local_tr_traits); + typename Kernel::Equal_d eq = m_k.equal_d_object(); + + Tr_point proj_wp; + if(eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) + { + proj_wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(m_intrinsic_dimension, ORIGIN), + m_weights[i]); + } + else + { + const Weighted_point& wp = compute_perturbed_weighted_point(i); + proj_wp = project_point_and_compute_weight(wp, m_tangent_spaces[i], + local_tr_traits); + } center_vertex = local_tr.insert(proj_wp); center_vertex->data() = i; From e5407e014243b983e6c2d7532b9d7df8a5e8b282 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 17:39:09 +0200 Subject: [PATCH 189/269] Solve ambiguity on "i" --- .../include/CGAL/Tangential_complex.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index e035aa7c77c..38e7d1aa53f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1639,23 +1639,23 @@ next_face: if (p_orth_space_basis) { p_orth_space_basis->origin() = p; - for (int i = m_ambient_dim - m_intrinsic_dimension - 1 ; - i >= 0 ; - --i) + for (int j = m_ambient_dim - m_intrinsic_dimension - 1 ; + j >= 0 ; + --j) { if (normalize_basis) { Vector v = constr_vec(m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim); + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); p_orth_space_basis->push_back(normalize_vector(v, m_k)); } else { p_orth_space_basis->push_back(constr_vec( m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim)); + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); } } } From 3ceb5992b07fabf29a4ae0437624851cb81fe18e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 29 Apr 2015 17:55:06 +0200 Subject: [PATCH 190/269] fix_inconsistencies => fix_inconsistencies_using_perturbation --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 2 +- Tangential_complex/include/CGAL/Tangential_complex.h | 8 ++++---- .../test/Tangential_complex/test_tangential_complex.cpp | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 548f0c48949..9cf7efbb3e4 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -352,7 +352,7 @@ void make_tc(std::vector &points, 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( + 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); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 38e7d1aa53f..d484bc65b94 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -445,7 +445,7 @@ public: } // time_limit in seconds: 0 = no fix to do, < 0 = no time limit - Fix_inconsistencies_status fix_inconsistencies( + Fix_inconsistencies_status fix_inconsistencies_using_perturbation( unsigned int &num_steps, std::size_t &initial_num_inconsistent_local_tr, std::size_t &best_num_inconsistent_local_tr, @@ -533,7 +533,7 @@ public: << "Inconsistencies (detailed stats):\n" << " * Number of vertices: " << m_points.size() << std::endl << std::endl - << " * BEFORE fix_inconsistencies:" << std::endl + << " * BEFORE fix_inconsistencies_using_perturbation:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_before.first << std::endl << " - Num inconsistent simplices in stars (incl. duplicates): " @@ -545,7 +545,7 @@ public: << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl << std::endl - << " * AFTER fix_inconsistencies:" << std::endl + << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_after.first << std::endl << " - Num inconsistent simplices in stars (incl. duplicates): " @@ -563,7 +563,7 @@ public: std::cerr << std::endl << "==========================================================" << std::endl - << "fix_inconsistencies():\n" + << "fix_inconsistencies_using_perturbation():\n" << " * " << m_points.size() << " vertices" << std::endl << " * " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 691f5429c78..9ac1d555c5c 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -120,9 +120,10 @@ int main() 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( - num_fix_steps, initial_num_inconsistent_local_tr, - best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, 1000.); + 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.; From 065d3554421005468410b3fbcd0d51d9c667f7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 20 Mar 2015 12:15:50 +0100 Subject: [PATCH 191/269] Fix compilation issues (cherry picked from commit 444c982540a1b4301d829556027784d81ffe0f55) Conflicts: Tangential_complex/include/CGAL/Tangential_complex.h --- Tangential_complex/include/CGAL/Tangential_complex.h | 4 ++-- .../include/CGAL/Tangential_complex/utilities.h | 2 +- Tangential_complex/test/Tangential_complex/test_utilities.h | 2 ++ Triangulation/include/CGAL/Triangulation_data_structure.h | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d484bc65b94..ae757607225 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -371,8 +371,8 @@ public: std::vector sum_eigen_values(m_ambient_dim, FT(0)); - Points::const_iterator it_p = m_points.begin(); - Points::const_iterator it_p_end = m_points.end(); + typename Points::const_iterator it_p = m_points.begin(); + typename Points::const_iterator it_p_end = m_points.end(); // For each point p for ( ; it_p != it_p_end ; ++it_p) { diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 9c26b2c48e2..b547125a1ef 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -210,7 +210,7 @@ namespace Tangential_complex_ { do { std::set combination; - Elements_container::const_iterator it_elt = elements.begin(); + typename Elements_container::const_iterator it_elt = elements.begin(); for (std::size_t i = 0 ; i < n ; ++i, ++it_elt) { if (booleans[i]) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 695d7a93e86..354e7bf5f2a 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -33,6 +33,8 @@ #include #include +#include + // 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 diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index ef10428a5c3..895a6f11b51 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -611,7 +611,8 @@ public: return incident_faces(v, dim, out, cmp, true); } template< typename OutputIterator, typename Comparator = std::less > - OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false); + 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()) From d0fe1db9dbdc28d090f22c49e07aee1b778ce02b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 6 May 2015 19:13:11 +0200 Subject: [PATCH 192/269] Added generators for tori --- .../test/Tangential_complex/test_utilities.h | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 354e7bf5f2a..4847a55c8bc 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -131,6 +131,18 @@ typename Kernel::Point_d construct_point( return k.construct_point_d_object()(5, &tab[0], &tab[5]); } +// construct_point: dim 6 +template +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 std::vector sparsify_point_set( @@ -286,6 +298,128 @@ std::vector generate_points_on_moment_curve( return points; } + +// R = big radius, r = small radius +template +std::vector generate_points_on_torus_3D( + std::size_t num_points, double R, double r, 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 points; + points.reserve(num_points); +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > 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 + } + return points; +} + +template +static void generate_uniform_points_on_torus_d( + const Kernel &k, int dim, std::size_t num_slices, OutputIterator out, + std::vector current_point = std::vector()) +{ + if (current_point.size() == 2*dim) + { + *out++ = k.construct_point_d_object()( + current_point.size(), current_point.begin(), current_point.end()); + } + else + { + for (std::size_t slice_idx = 0 ; slice_idx < num_slices ; ++slice_idx) + { + std::vector cp2 = current_point; + FT alpha = 6.2832 * slice_idx / num_slices; + cp2.push_back(std::cos(alpha)); + cp2.push_back(std::sin(alpha)); + generate_uniform_points_on_torus_d( + k, dim, num_slices, out, cp2); + } + } +} + +template +std::vector generate_points_on_torus_d( + std::size_t num_points, int dim, 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_slices = (std::size_t)std::pow(num_points, 1./dim); + + std::vector points; + points.reserve(num_points); + if (uniform) + { + generate_uniform_points_on_torus_d( + k, dim, num_slices, std::back_inserter(points)); + } + else + { +#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER + Point_sparsifier > sparsifier(points); +#endif + for (std::size_t i = 0 ; i < num_points ; ) + { + std::vector pt; + for (int curdim = 0 ; curdim < dim ; ++curdim) + { + FT alpha = rng.get_double(0, 6.2832); + pt.push_back(std::cos(alpha)); + pt.push_back(std::sin(alpha)); + } + + Point p = k.construct_point_d_object()(pt.size(), 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 std::vector generate_points_on_sphere_d( std::size_t num_points, int dim, double radius, From 8fb2b9266345b1e584896baaba31faaf769e7668 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:44:14 +0200 Subject: [PATCH 193/269] Fix compilation + code clean-up --- .../include/CGAL/Tangential_complex.h | 103 ++++++++++++------ 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ae757607225..0c7457c7d7a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -65,13 +65,17 @@ #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) -#define CGAL_ALPHA_TC +//#define CGAL_ALPHA_TC const double ALPHA = 0.3; #ifdef CGAL_LINKED_WITH_TBB tbb::atomic ttt_star; // CJTODO TEMP tbb::atomic ttt_intersect; #endif +//CJTODO: debug +//#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 +//#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D + namespace CGAL { using namespace Tangential_complex_; @@ -234,12 +238,12 @@ public: m_points(first, last), m_weights(m_points.size(), FT(0)) #ifdef CGAL_TC_PERTURB_WEIGHT - m_weights_memory() + , m_weights_memory() #endif -# if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ +#if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_PERTURB_POSITION) \ && defined(CGAL_TC_GLOBAL_REFRESH) , m_p_perturb_mutexes(NULL) -# endif +#endif , m_points_ds(m_points) , m_are_tangent_spaces_computed(m_points.size(), false) , m_tangent_spaces(m_points.size(), Tangent_space_basis()) @@ -294,11 +298,12 @@ public: << " tangent spaces manually at the same time" << std::endl; std::exit(EXIT_FAILURE); #endif - CGAL_assertion(m_points.size() == tangent_spaces.size() #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - && m_points.size() == orthogonal_spaces.size() + CGAL_assertion(m_points.size() == tangent_spaces.size() + && m_points.size() == orthogonal_spaces.size()); +#else + CGAL_assertion(m_points.size() == tangent_spaces.size()); #endif - ); m_tangent_spaces = tangent_spaces; #if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_orth_spaces = orthogonal_spaces; @@ -540,7 +545,7 @@ public: << stats_before.second << " (" << 100. * stats_before.second / stats_before.first << "%)" << std::endl - << " * Num inconsistent local triangulations: " + << " * Num inconsistent stars: " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl @@ -567,7 +572,7 @@ public: << " * " << m_points.size() << " vertices" << std::endl << " * " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" - << " inconsistent triangulations encountered" << std::endl + << " inconsistent stars encountered" << std::endl << "==========================================================" << std::endl; # endif @@ -1563,7 +1568,50 @@ next_face: #endif ) { +#ifdef CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 + + // CJTODO: this is only for a sphere in R^3 + double tt1[3] = {-p[1] - p[2], p[0], p[0]}; + double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], + p[2] * tt1[0] - p[0] * tt1[2], + p[0] * tt1[1] - p[1] * tt1[0]}; + Vector t1(3, &tt1[0], &tt1[3]); + Vector t2(3, &tt2[0], &tt2[3]); + + // Normalize t1 and t2 + typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + + Tangent_space_basis ts; + ts.reserve(m_intrinsic_dimension); + ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); + ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); + + m_are_tangent_spaces_computed[i] = true; + + return ts; + +#elif defined(CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D) + + // CJTODO: this is only for torus_d + Tangent_space_basis ts(p); + ts.reserve(m_intrinsic_dimension); + for (int dim = 0 ; dim < m_intrinsic_dimension ; ++dim) + { + std::vector tt(m_ambient_dim, 0.); + tt[2*dim] = -p[2*dim + 1]; + tt[2*dim + 1] = p[2*dim]; + Vector t(2*m_intrinsic_dimension, tt.begin(), tt.end()); + ts.push_back(t); + } + + m_are_tangent_spaces_computed[i] = true; + + //return compute_gram_schmidt_basis(ts, m_k); + return ts; //******************************* PCA ************************************* + +#else // Kernel functors typename Kernel::Construct_vector_d constr_vec = @@ -1616,23 +1664,23 @@ next_face: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues - for (int i = m_ambient_dim - 1 ; - i >= m_ambient_dim - m_intrinsic_dimension ; - --i) + for (int j = m_ambient_dim - 1 ; + j >= m_ambient_dim - m_intrinsic_dimension ; + --j) { if (normalize_basis) { Vector v = constr_vec(m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim); + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); tsb.push_back(normalize_vector(v, m_k)); } else { tsb.push_back(constr_vec( m_ambient_dim, - eig.eigenvectors().col(i).data(), - eig.eigenvectors().col(i).data() + m_ambient_dim)); + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); } } @@ -1669,25 +1717,8 @@ next_face: //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; return tsb; - - // CJTODO: this is only for a sphere in R^3 - /*double tt1[3] = {-p[1] - p[2], p[0], p[0]}; - double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], - p[2] * tt1[0] - p[0] * tt1[2], - p[0] * tt1[1] - p[1] * tt1[0]}; - Vector t1(3, &tt1[0], &tt1[3]); - Vector t2(3, &tt2[0], &tt2[3]); - - // Normalize t1 and t2 - typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - - Tangent_space_basis ts; - ts.reserve(m_intrinsic_dimension); - ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); - ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); - - return ts;*/ + +#endif /* // Alternative code (to be used later) @@ -1917,7 +1948,7 @@ next_face: #ifdef CGAL_TC_PERTURB_WEIGHT m_weights[point_idx] = m_random_generator.get_double(0., m_sq_half_sparsity); if(m_weights_memory.size() > 0) // external weights were initially set - m_weights[point_idx] += m_weights_memory[point_idx] + m_weights[point_idx] = m_weights[point_idx] + m_weights_memory[point_idx]; #endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE From 9b0fca5019b5e3bdcc942bbce49d0e31fbce80f7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:46:40 +0200 Subject: [PATCH 194/269] Replaced NUM_POINTS_FOR_PCA by BASE_VALUE_FOR_PCA^intrinsic_dim --- .../include/CGAL/Tangential_complex.h | 21 ++++++++++++------- .../include/CGAL/Tangential_complex/config.h | 4 +++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 0c7457c7d7a..87278749384 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -375,6 +375,8 @@ public: m_k.compute_coordinate_d_object(); std::vector sum_eigen_values(m_ambient_dim, FT(0)); + std::size_t num_points_for_pca = + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dimension); typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -383,14 +385,14 @@ public: { const Point &p = *it_p; - KNS_range kns_range = m_points_ds.query_ANN(p, NUM_POINTS_FOR_PCA, false); + KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); //******************************* PCA ************************************* // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambient_dim); + Eigen::MatrixXd mat_points(num_points_for_pca, m_ambient_dim); KNS_iterator nn_it = kns_range.begin(); for (int j = 0 ; - j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + j < num_points_for_pca && nn_it != kns_range.end() ; ++j, ++nn_it) { for (int i = 0 ; i < m_ambient_dim ; ++i) @@ -1613,6 +1615,9 @@ next_face: #else + unsigned int num_points_for_pca = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dimension)); + // Kernel functors typename Kernel::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); @@ -1631,18 +1636,18 @@ next_face: #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM KNS_range kns_range = m_points_ds_for_tse.query_ANN( - p, NUM_POINTS_FOR_PCA, false); + p, num_points_for_pca, false); const Points &points_for_pca = m_points_for_tse; #else - KNS_range kns_range = m_points_ds.query_ANN(p, NUM_POINTS_FOR_PCA, false); + KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); const Points &points_for_pca = m_points; #endif // One row = one point - Eigen::MatrixXd mat_points(NUM_POINTS_FOR_PCA, m_ambient_dim); + Eigen::MatrixXd mat_points(num_points_for_pca, m_ambient_dim); KNS_iterator nn_it = kns_range.begin(); - for (int j = 0 ; - j < NUM_POINTS_FOR_PCA && nn_it != kns_range.end() ; + for (unsigned int j = 0 ; + j < num_points_for_pca && nn_it != kns_range.end() ; ++j, ++nn_it) { for (int i = 0 ; i < m_ambient_dim ; ++i) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 9c53d41b69b..060b1b75feb 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -65,6 +65,8 @@ //#define CGAL_TC_PERTURB_TANGENT_SPACE //========================= Parameters ======================================== -const std::size_t NUM_POINTS_FOR_PCA = 20; + +// PCA will use BASE_VALUE_FOR_PCA^intrinsic_dim points +const std::size_t BASE_VALUE_FOR_PCA = 5; #endif // CGAL_TC_CONFIG_H From fb0e11a2aa8e944c4d33894da9819523f9a79391 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:47:34 +0200 Subject: [PATCH 195/269] Fix collapse --- .../Tangential_complex/Simplicial_complex.h | 115 ++++++++++-------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 73422444aa2..ecdea36ce3a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -124,69 +124,76 @@ public: typedef std::vector Simplex_iterator_list; typedef std::map Cofaces_map; - // 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) + std::size_t num_collapsed_maximal_simplices = 0; + do { - if (it_simplex->size() > k + 1) + 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) { - std::vector 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 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 + if (it_simplex->size() > k + 1) { - // Skip F - if (f2 != it_map_elt->first) + std::vector 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 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 { - Cofaces_map::iterator it_comb_in_map = cofaces_map.find(f2); - if (it_comb_in_map->second.size() == 1) + // Skip F + if (f2 != it_map_elt->first) { - 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); + 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; } - m_complex.erase(it_Cf); } - } + // Repeat until no maximal simplex got removed + } while (num_collapsed_maximal_simplices > 0); // Collapse the lower dimension simplices if (k > 0) From 5b0a2a284dce16751aee08435068e3f5befe8ca8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:48:43 +0200 Subject: [PATCH 196/269] Benchmark: added torus + minor fixes --- .../Tangential_complex/benchmark_tc.cpp | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 9cf7efbb3e4..75b43d6c36d 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -164,7 +165,9 @@ bool export_to_off( std::stringstream output_filename; output_filename << "output/" << input_name_stripped << "_" << tc.intrinsic_dimension() << "_in_R" - << tc.ambient_dimension() << suffix << ".off"; + << tc.ambient_dimension() << "_" + << tc.number_of_vertices() << "v" + << suffix << ".off"; std::ofstream off_stream(output_filename.str().c_str()); if (p_complex) @@ -372,6 +375,10 @@ void make_tc(std::vector &points, bool exported = export_to_off(tc, input_name_stripped, "_AFTER_FIX", true); 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 { @@ -522,8 +529,8 @@ int main() # endif #endif - int seed = CGAL::default_random.get_int(0, 1<<30); - CGAL::default_random = CGAL::Random(); + int seed = time(NULL); + CGAL::default_random = CGAL::Random(seed); std::cerr << "Random seed = " << seed << std::endl; std::ifstream script_file; @@ -639,6 +646,21 @@ int main() std::atof(param1.c_str()), std::atof(param2.c_str())); } + else if (input == "generate_torus_3D") + { + points = generate_points_on_torus_3D( + 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( + num_points, + intrinsic_dim, + param1 == "Y"); + } else if (input == "generate_klein_bottle_3D") { points = generate_points_on_klein_bottle_3D( From a015ca547c83247ebb6c923c736aa71f26f1861a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:49:36 +0200 Subject: [PATCH 197/269] Minor optimizations in generate_points_on_torus_d --- Tangential_complex/test/Tangential_complex/test_utilities.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 4847a55c8bc..2bd2ccc5049 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -382,13 +382,11 @@ std::vector generate_points_on_torus_d( Kernel k; CGAL::Random rng; - // if uniform - std::size_t num_slices = (std::size_t)std::pow(num_points, 1./dim); - std::vector 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)); } @@ -400,6 +398,7 @@ std::vector generate_points_on_torus_d( for (std::size_t i = 0 ; i < num_points ; ) { std::vector pt; + pt.reserve(dim*2); for (int curdim = 0 ; curdim < dim ; ++curdim) { FT alpha = rng.get_double(0, 6.2832); From 045b463cff650325306afa9a3c1bb0f722874f5f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:51:16 +0200 Subject: [PATCH 198/269] export_inconsistent_stars_to_OFF_files --- .../include/CGAL/Tangential_complex.h | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 87278749384..fb8e12dfb3f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -802,6 +802,52 @@ public: return os; } + + // Return a pair + void export_inconsistent_stars_to_OFF_files( + std::string const& filename_base) const + { + std::size_t num_simplices = 0; + std::size_t num_inconsistent_simplices = 0; + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + { + // We build a SC along the way in case it's inconsistent + Simplicial_complex sc; + // For each cell + bool is_inconsistent = false; + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; + ++it_inc_simplex) + { + // Skip infinite cells + if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + continue; + + std::set c = *it_inc_simplex; + c.insert(idx); // Add the missing index + + sc.add_simplex(c); + + // If we do not already know this star is inconsistent, test it + if (!is_inconsistent && !is_simplex_consistent(c)) + is_inconsistent = true; + } + + if (is_inconsistent) + { + // Export star to OFF file + std::stringstream output_filename; + output_filename << filename_base << "_" << idx << ".off"; + std::ofstream off_stream(output_filename.str().c_str()); + export_to_off(sc, off_stream); + } + } + } + bool check_if_all_simplices_are_in_the_ambient_delaunay( const Simplicial_complex *p_complex = NULL, From 002748790e00e60260f743871de4791f223bf1f8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:53:49 +0200 Subject: [PATCH 199/269] Fix perturb (the size of the translation was always m_half_radius) --- .../include/CGAL/Tangential_complex.h | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index fb8e12dfb3f..9811d2ceb79 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1703,7 +1703,8 @@ next_face: mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); #ifdef CGAL_TC_PERTURB_TANGENT_SPACE if (perturb) - mat_points(j, i) += m_random_generator.get_double(-0.3, 0.3); + mat_points(j, i) += m_random_generator.get_double( + -m_half_sparsity, m_half_sparsity); #endif } } @@ -2012,18 +2013,17 @@ next_face: typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(m_ambient_dim, 1); + tr_point_on_sphere_generator( + m_ambient_dim, m_random_generator.get_double(0., m_half_sparsity)); // Parallel # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) - Vector transl = k_scaled_vec(k_pt_to_vec(*tr_point_on_sphere_generator++), - m_half_sparsity); + Vector transl = k_pt_to_vec(*tr_point_on_sphere_generator); m_p_perturb_mutexes[point_idx].lock(); m_translations[point_idx] = transl; m_p_perturb_mutexes[point_idx].unlock(); // Sequential # else - m_translations[point_idx] = k_scaled_vec(k_pt_to_vec( - *tr_point_on_sphere_generator++), m_half_sparsity); + m_translations[point_idx] = k_pt_to_vec(*tr_point_on_sphere_generator); # endif # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL @@ -2038,19 +2038,21 @@ next_face: typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator(m_intrinsic_dimension, 1); + CGAL::Random_points_on_sphere_d + tr_point_on_sphere_generator( + m_intrinsic_dimension, + m_random_generator.get_double(0., m_half_sparsity)); Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( - *tr_point_on_sphere_generator++, 0); + *tr_point_on_sphere_generator, 0); Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) { global_transl = k_transl( global_transl, - k_scaled_vec(tsb[i], m_half_sparsity*coord(local_random_transl, i)) + k_scaled_vec(tsb[i], coord(local_random_transl, i)) ); } // Parallel From 04136b980ce6d8a70920558a2059fa76a2cf965d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:54:58 +0200 Subject: [PATCH 200/269] Improved export to OFF files --- .../include/CGAL/Tangential_complex.h | 73 +++++++++++-------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 9811d2ceb79..5c7ebc1eeea 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1704,7 +1704,7 @@ next_face: #ifdef CGAL_TC_PERTURB_TANGENT_SPACE if (perturb) mat_points(j, i) += m_random_generator.get_double( - -m_half_sparsity, m_half_sparsity); + -0.5*m_half_sparsity, 0.5*m_half_sparsity); #endif } } @@ -2700,7 +2700,7 @@ next_face: } std::ostream &export_simplices_to_off( - std::ostream & os, std::size_t &num_simplices, + std::ostream & os, std::size_t &num_OFF_simplices, bool color_inconsistencies = false, std::set > const *p_simpl_to_color_in_red = NULL, std::set > const *p_simpl_to_color_in_green = NULL, @@ -2709,8 +2709,9 @@ next_face: { // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) - num_simplices = 0; - std::size_t num_inconsistent_simplices = 0; + num_OFF_simplices = 0; + std::size_t num_maximal_simplices = 0; + std::size_t num_inconsistent_maximal_simplices = 0; std::size_t num_inconsistent_stars = 0; typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); @@ -2743,15 +2744,16 @@ next_face: std::set c = *it_inc_simplex; c.insert(idx); std::size_t num_vertices = c.size(); + ++num_maximal_simplices; int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue - if (color_inconsistencies) + if (color_inconsistencies && !is_simplex_consistent(c)) { - is_star_inconsistent = !is_simplex_consistent(c); - color_simplex = (is_star_inconsistent ? 0 : -1); + ++num_inconsistent_maximal_simplices; + color_simplex = 0; + is_star_inconsistent = true; } - - if (color_simplex == -1) + else { if (p_simpl_to_color_in_red && std::find( @@ -2844,7 +2846,8 @@ next_face: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != idx && color_simplex == -1) + if (*c.begin() != (m_intrinsic_dimension == 1 ? 2*idx : idx) + && color_simplex == -1) continue; os << 3 << " " << sstr_c.str(); @@ -2853,14 +2856,14 @@ next_face: { switch (color_simplex) { - case 0: os << " 255 255 0"; ++num_inconsistent_simplices; break; + case 0: os << " 255 255 0"; break; case 1: os << " 255 0 0"; break; case 2: os << " 0 255 0"; break; case 3: os << " 0 0 255"; break; default: os << " " << color.str(); break; } } - ++num_simplices; + ++num_OFF_simplices; os << std::endl; } if (is_star_inconsistent) @@ -2871,21 +2874,27 @@ next_face: std::cerr << std::endl << "==========================================================" << std::endl - << "Export to OFF:\n" + << "Export from list of stars to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices: " << num_simplices << std::endl - << " * Number of inconsistent stars: " - << num_inconsistent_stars << " (" - << (m_points.size() > 0 ? - 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)" - << std::endl - << " * Number of inconsistent simplices: " - << num_inconsistent_simplices << " (" - << (num_simplices > 0 ? - 100. * num_inconsistent_simplices / num_simplices : 0.) << "%)" - << std::endl - << "==========================================================" + << " * Total number of maximal simplices: " << num_maximal_simplices << std::endl; + if (color_inconsistencies) + { + std::cerr + << " * Number of inconsistent stars: " + << num_inconsistent_stars << " (" + << (m_points.size() > 0 ? + 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)" + << std::endl + << " * Number of inconsistent maximal simplices: " + << num_inconsistent_maximal_simplices << " (" + << (num_maximal_simplices > 0 ? + 100. * num_inconsistent_maximal_simplices / num_maximal_simplices + : 0.) << "%)" + << std::endl; + } + std::cerr << "==========================================================" + << std::endl; #endif return os; @@ -2894,7 +2903,7 @@ next_face: public: std::ostream &export_simplices_to_off( const Simplicial_complex &complex, - std::ostream & os, std::size_t &num_simplices, + std::ostream & os, std::size_t &num_OFF_simplices, std::set > const *p_simpl_to_color_in_red = NULL, std::set > const *p_simpl_to_color_in_green = NULL, std::set > const *p_simpl_to_color_in_blue = NULL) @@ -2905,7 +2914,9 @@ public: // If m_intrinsic_dimension = 1, each point is output two times // (see export_vertices_to_off) - num_simplices = 0; + num_OFF_simplices = 0; + std::size_t num_maximal_simplices = 0; + typename Simplex_range::const_iterator it_s = complex.simplex_range().begin(); typename Simplex_range::const_iterator it_s_end = @@ -2914,6 +2925,7 @@ public: for ( ; it_s != it_s_end ; ++it_s) { Simplex c = *it_s; + ++num_maximal_simplices; int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue if (p_simpl_to_color_in_red && @@ -3018,7 +3030,7 @@ public: } } - ++num_simplices; + ++num_OFF_simplices; os << std::endl; } } @@ -3027,9 +3039,10 @@ public: std::cerr << std::endl << "==========================================================" << std::endl - << "Export to OFF:\n" + << "Export from complex to OFF:\n" << " * Number of vertices: " << m_points.size() << std::endl - << " * Total number of simplices: " << num_simplices << std::endl + << " * Total number of maximal simplices: " << num_maximal_simplices + << std::endl << "==========================================================" << std::endl; #endif From c1c3e3c58bab7b1bd7bd0d11cff7cdb54833129c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 May 2015 17:55:33 +0200 Subject: [PATCH 201/269] Updated benchmark script --- .../Tangential_complex/benchmark_script.txt | 93 +++++++++++-------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 1b050e0eccf..3deaec7d390 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -2,54 +2,69 @@ # Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- -#---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- -#generate_sphere_d 4 - - 20 3 2 0.05 N N Y 60 1 -#generate_sphere_d 3 - - 70 3 2 0.05 Y Y Y 60 1 -#generate_sphere_d 3 - - 1000 3 2 0.05 Y Y Y 60 1 -#generate_sphere_d 3 - - 70 4 3 0.05 Y Y Y 60 1 -#generate_sphere_d 3 - - 70 5 4 0.05 Y Y Y 60 1 -#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 Y Y Y 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.7 Y Y Y 60 1 -#generate_moment_curve 0 1 - 30 3 1 0.005 Y Y Y 60 1 - #---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ #generate_sphere_d 0.302 - - 70 2 1 0.005 N N Y 60 1 #generate_sphere_d 0.5 - - 70 2 1 0.005 N N Y 60 1 -generate_sphere_d 3 2 - 100 3 2 0.05 N N Y 60 1 -#generate_klein_bottle_4D 40 15 - 130 4 2 0.2 N N Y 60 1 -#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 Y Y Y 60 1 #Takes forever +#generate_sphere_d 3 2 - 1000 3 2 0.05 N N Y 60 1 +#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N Y 60 1 +#generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N Y 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever + +#---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- +#generate_sphere_d 4 - - 20 3 2 0.05 N Y N 60 1 +#generate_sphere_d 3 - - 70 3 2 0.05 N Y N 60 1 +#generate_sphere_d 3 - - 1000 3 2 0.05 N Y N 60 1 +#generate_sphere_d 3 - - 70 4 3 0.05 N Y N 60 1 +#generate_sphere_d 3 - - 70 5 4 0.05 N Y N 60 1 +#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 N Y N 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.7 N Y N 60 1 +#generate_moment_curve 0 1 - 30 3 1 0.005 N Y N 60 1 +#generate_torus_3D 2 1 Y 150 3 2 0.05 Y N N 600 1 +#generate_torus_d N - - 30 2 1 0.01 Y N N 30 1 +#generate_torus_d Y - - 70 4 2 0.05 Y N N 30 1 +#generate_torus_d N - - 200 4 2 0.05 Y N N 30 1 +#generate_torus_d N - - 20000 4 2 0.65 Y N N 30 1 +#generate_torus_d N - - 10000 6 3 0.05 Y N N 300 1 +#generate_torus_d N - - 50000 6 3 0.05 Y N N 7000 1 +#generate_torus_d N - - 100000 6 3 0.05 Y N N 7000 1 +generate_torus_d N - - 1000000 6 3 0.3 Y N N 3000 1 +#generate_torus_d Y - - 10000 8 4 0.05 Y N N 3600 1 #------------------------------------------------------------------ From files -------------------------------------------------------------------------- -#data/SO3_50000.txt - - - 0 9 3 0.2 Y Y Y 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.05 Y Y Y 60 1 -#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 Y Y Y 3000 1 -#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 Y Y Y 3000 1 -#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 Y Y Y 3000 1 -#data/Cy8.txt - - - 0 24 2 0.1 Y Y Y 60 1 -#data/Kl.txt - - - 0 5 2 0.05 Y Y Y 60 1 -#data/S3.txt - - - 0 4 3 0.05 Y Y Y 60 1 +#data/SO3_50000.txt - - - 0 9 3 0.05 Y Y N 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.05 Y N N 60 1 +#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 N Y N 3000 1 +#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 N Y N 3000 1 +#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 N Y N 3000 1 +#data/Cy8.txt - - - 0 24 2 0.1 N Y N 60 1 +#data/Kl.txt - - - 0 5 2 0.05 N Y N 60 1 +#data/S3.txt - - - 0 4 3 0.05 N Y N 60 1 #---------------------------------------------------------------------- 3D meshes ----------------------------------------------------------------------- -#data/buddha_100kv.txt - - - 0 3 2 0.005 Y Y Y 60 1 -#data/fandisk.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/fertility.txt - - - 0 3 2 0.4 Y Y Y 60 1 -#data/bunny.txt - - - 0 3 2 0.5 Y Y Y 60 1 -#data/blob.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/3holes.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/785_hand_2500v.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/785_hand_50kv.txt - - - 0 3 2 0.01 Y Y Y 60 1 -#data/bumpy_sphere.txt - - - 0 3 2 0.01 Y Y Y 60 1 +#data/buddha_100kv.txt - - - 0 3 2 0.005 N Y N 120 1 +#data/fandisk.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/fertility.txt - - - 0 3 2 0.4 N Y N 60 1 +#data/bunny.txt - - - 0 3 2 0.5 N Y N 60 1 +#data/blob.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/3holes.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/785_hand_2500v.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/785_hand_50kv.txt - - - 0 3 2 0.01 N Y N 60 1 +#data/bumpy_sphere.txt - - - 0 3 2 0.01 N Y N 60 1 #----------------------------------------------------------- Generated point sets ----------------------------------------------------------------------- -#generate_sphere_d 3 - - 4 3 2 0.05 Y Y Y 3000 1 -#generate_sphere_d 3 - - 30000 2 1 0.005 Y Y Y 3000 1 -#generate_sphere_d 3 - - 30000 3 2 0.005 Y Y Y 3000 1 -#generate_sphere_d 3 - - 30000 4 3 0.05 Y Y Y 3000 1 -#generate_plane - - - 30000 3 2 0.005 Y Y Y 3000 1 -#generate_moment_curve 0 1 - 30000 6 1 0.005 Y Y Y 60 1 -#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 Y Y Y 60 1 -#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 Y Y Y 60 1 +#generate_sphere_d 3 - - 4 3 2 0.05 N Y N 3000 1 +#generate_sphere_d 3 - - 30000 2 1 0.005 N Y N 3000 1 +#generate_sphere_d 3 - - 30000 3 2 0.005 N Y N 3000 1 +#generate_sphere_d 3 - - 30000 4 3 0.05 N Y N 3000 1 +#generate_sphere_d 3 0 - 3000 3 2 0.005 N Y N 60 1 +#generate_sphere_d 3 4 - 3000 3 2 0.005 N Y N 60 1 +#generate_sphere_d 3 7 - 3000 3 2 0.005 N Y N 60 1 +#generate_plane - - - 30000 3 2 0.005 N Y N 3000 1 +#generate_moment_curve 0 1 - 30000 6 1 0.005 N Y N 60 1 +#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 N Y N 60 1 +#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 N Y N 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever #----------------------------------------------------------- Performance testing ------------------------------------------------------------------------ # TC: 5.55 / 1st fix step : 0.2 -#data/fertility.txt - - - 0 3 2 0.1 Y Y Y 100 1 \ No newline at end of file +#data/fertility.txt - - - 0 3 2 0.1 N Y N 100 1 \ No newline at end of file From f84b0ed529e294e1d835875efd3ea9100d99bb62 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 28 May 2015 17:04:17 +0200 Subject: [PATCH 202/269] Add a spatial searching benchmarking function in test_utilities.h Updated Point_cloud.h to use nanoflann correctly --- .../Tangential_complex/benchmark_script.txt | 26 +- .../Tangential_complex/benchmark_tc.cpp | 9 +- .../CGAL/Tangential_complex/Point_cloud.h | 341 +++++++++--------- .../include/CGAL/Tangential_complex/config.h | 2 +- .../test/Tangential_complex/test_utilities.h | 73 ++++ 5 files changed, 261 insertions(+), 190 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 3deaec7d390..fa30a289ffd 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -9,6 +9,22 @@ #generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N Y 60 1 #generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N Y 60 1 #generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever +#generate_torus_3D 2 1 Y 150 3 2 0.05 Y N N 600 1 +#generate_torus_d N - - 30 2 1 0.01 Y N N 30 1 +#generate_torus_d Y - - 70 4 2 0.05 Y N N 30 1 +#generate_torus_d N - - 200 4 2 0.05 Y N N 30 1 +#generate_torus_d N - - 20000 4 2 0.65 Y N N 30 1 +#generate_torus_d N - - 10000 6 3 0.05 Y N N 300 1 +#generate_torus_d N - - 50000 6 3 0.05 Y N N 7000 1 +#generate_torus_d N - - 100000 6 3 0.05 Y N N 7000 1 +#generate_torus_d N - - 1000000 6 3 0.3 Y N N 3000 1 +#generate_torus_d Y - - 10000 8 4 0.05 Y N N 3600 1 + +#---------------------------------------------------------- Spatial search benchmarking -------------------------------------------------------------- +generate_torus_d Y - - 1000000 30 15 0 Y N N 3600 1 +data/SO3_50000.txt - - - 0 9 3 0 Y Y N 60 1 +data/Cy8.txt - - - 0 24 2 0 N Y N 60 1 +data/buddha_100kv.txt - - - 0 3 2 0 N Y N 120 1 #---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- #generate_sphere_d 4 - - 20 3 2 0.05 N Y N 60 1 @@ -19,16 +35,6 @@ #generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 N Y N 60 1 #data/SO3_10000.txt - - - 0 9 3 0.7 N Y N 60 1 #generate_moment_curve 0 1 - 30 3 1 0.005 N Y N 60 1 -#generate_torus_3D 2 1 Y 150 3 2 0.05 Y N N 600 1 -#generate_torus_d N - - 30 2 1 0.01 Y N N 30 1 -#generate_torus_d Y - - 70 4 2 0.05 Y N N 30 1 -#generate_torus_d N - - 200 4 2 0.05 Y N N 30 1 -#generate_torus_d N - - 20000 4 2 0.65 Y N N 30 1 -#generate_torus_d N - - 10000 6 3 0.05 Y N N 300 1 -#generate_torus_d N - - 50000 6 3 0.05 Y N N 7000 1 -#generate_torus_d N - - 100000 6 3 0.05 Y N N 7000 1 -generate_torus_d N - - 1000000 6 3 0.3 Y N N 3000 1 -#generate_torus_d Y - - 10000 8 4 0.05 Y N N 3600 1 #------------------------------------------------------------------ From files -------------------------------------------------------------------------- #data/SO3_50000.txt - - - 0 9 3 0.05 Y Y N 60 1 diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 75b43d6c36d..ef4863051cf 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -210,6 +210,8 @@ void make_tc(std::vector &points, double time_limit_for_perturb = 0., const char *input_name = "tc") { + Kernel k; + // CJTODO TEMP TEST //TC::Simplicial_complex compl; //{std::size_t ss[] = {0, 1, 2}; compl.add_simplex(std::set(ss, ss + 3)); } @@ -232,10 +234,13 @@ void make_tc(std::vector &points, //compl.is_pure_pseudomanifold(3, 9, false, 10); // /CJTODO TEMP TEST + // CJTODO TEMP TEST + benchmark_spatial_search(points, k); + return; + //=========================================================================== // Init //=========================================================================== - Kernel k; Wall_clock_timer t; // Get input_name_stripped @@ -529,7 +534,7 @@ int main() # endif #endif - int seed = time(NULL); + unsigned int seed = static_cast(time(NULL)); CGAL::default_random = CGAL::Random(seed); std::cerr << "Random seed = " << seed << std::endl; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 0ea59a5f208..18452493061 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -22,183 +22,8 @@ #define POINT_CLOUD_H #include -#include #include -#ifdef CGAL_TC_USE_NANOFLANN - -#include "nanoflann.hpp" - -#include -#include -#include - -namespace CGAL { -namespace Tangential_complex_ { - -// "dataset to kd-tree" adaptor class -template -class Point_cloud_adaptator -{ -public: - typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - - /// The constructor that sets the data set source - Point_cloud_adaptator(Point_container_ &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 - bool kdtree_get_bbox(Bbox &bb) const - { - return false; - } - - Kernel const& kernel() const - { - return m_k; - } - -protected: - Point_container_& m_points; //!< A ref to the data set origin - Kernel const& m_k; //!< A const ref to the kernel - -}; - -template -class Point_cloud_data_structure -{ -public: - typedef typename Point_container_::value_type Point; - typedef typename K Kernel; - typedef typename Kernel::FT FT; - - static const int AMB_DIM = Ambient_dimension::value; // CJTODO: use Point_dimension_d or similar - - /// Constructor - /// "points" must not be empty - Point_cloud_data_structure(Point_container_ &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 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 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 > &neighbors, - bool sort_output = true) - { - std::vector 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 Adaptor; - typedef nanoflann::KDTreeSingleIndexAdaptor< - nanoflann::L2_Simple_Adaptor , - Adaptor, - AMB_DIM // dim - > Kd_tree; - - Adaptor m_adaptor; - Kd_tree m_kd_tree; -}; - -} // namespace Tangential_complex_ -} //namespace CGAL - -#else // !CGAL_TC_USE_NANOFLANN => use CGAL Spatial searching - #include #include #include @@ -211,7 +36,6 @@ protected: #include #include -#include namespace CGAL { namespace Tangential_complex_ { @@ -325,9 +149,172 @@ protected: Tree m_tree; }; + +#ifdef CGAL_TC_NANOFLANN_IS_AVAILABLE + +#include "nanoflann.hpp" + +// "dataset to kd-tree" adaptor class +template +class Point_cloud_adaptator__nanoflann +{ +public: + typedef typename Point_container_::value_type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + + /// The constructor that sets the data set source + Point_cloud_adaptator__nanoflann(const Point_container_ &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 + 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 +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 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 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 > &neighbors, + bool sort_output = true) + { + std::vector 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 Adaptor; + typedef nanoflann::KDTreeSingleIndexAdaptor< + nanoflann::L2_Simple_Adaptor , + Adaptor, + -1 // dim + > Kd_tree; + + Adaptor m_adaptor; + Kd_tree m_kd_tree; +}; + +#endif //CGAL_TC_NANOFLANN_IS_AVAILABLE + } // namespace Tangential_complex_ } //namespace CGAL -#endif // CGAL_TC_USE_NANOFLANN #endif // POINT_CLOUD_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 060b1b75feb..9053edefd5a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -50,7 +50,7 @@ //========================= Strategy ========================================== -//#define CGAL_TC_USE_NANOFLANN +#define CGAL_TC_NANOFLANN_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 diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 2bd2ccc5049..d3df879a0d7 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -615,4 +615,77 @@ generate_points_on_klein_bottle_variant_5D( return points; } +template +void benchmark_spatial_search( + const std::vector &points, const Kernel &k) +{ + 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 Points; + + CGAL::Random random_generator; + Wall_clock_timer t; + + //****************************** CGAL *************************************** + { + std::cout << "\n=== CGAL ===\n"; + + typedef CGAL::Tangential_complex_::Point_cloud_data_structure + 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; + } + //**************************** nanoflann ************************************ + { + std::cout << "\n=== nanoflann ===\n"; + + typedef CGAL::Tangential_complex_:: + Point_cloud_data_structure__nanoflann + 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; + } +} #endif // CGAL_MESH_3_TEST_TEST_UTILITIES_H From b1e98606895b94cde824005da09d66d48b613d03 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 29 May 2015 14:58:09 +0200 Subject: [PATCH 203/269] Fix point set creation timing + #ifdef for KNN benchmark --- .../Tangential_complex/benchmark_tc.cpp | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ef4863051cf..53f6c499246 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -39,6 +39,12 @@ typedef CGAL::Tangential_complex< Kernel, CGAL::Dynamic_dimension_tag, CGAL::Parallel_tag> TC; +//#define JUST_BENCHMARK_SPATIAL_SEARCH // CJTODO: test + +#ifdef JUST_BENCHMARK_SPATIAL_SEARCH +std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); +#endif + class XML_perf_data { public: @@ -234,9 +240,10 @@ void make_tc(std::vector &points, //compl.is_pure_pseudomanifold(3, 9, false, 10); // /CJTODO TEMP TEST - // CJTODO TEMP TEST - benchmark_spatial_search(points, k); +#ifdef JUST_BENCHMARK_SPATIAL_SEARCH + benchmark_spatial_search(points, k, spatial_search_csv_file); return; +#endif //=========================================================================== // Init @@ -257,15 +264,6 @@ void make_tc(std::vector &points, int ambient_dim = k.point_dimension_d_object()(*points.begin()); -#ifdef CGAL_TC_PROFILING - Wall_clock_timer t_gen; -#endif - -#ifdef CGAL_TC_PROFILING - std::cerr << "Point set generated in " << t_gen.elapsed() - << " seconds." << std::endl; -#endif - CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM @@ -631,6 +629,10 @@ int main() #endif std::cerr << std::endl << "TC #" << i << "..." << std::endl; + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_gen; +#endif std::vector points; @@ -690,6 +692,11 @@ int main() input, std::back_inserter(points)/*, 600*/); } +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set generated/loaded in " << t_gen.elapsed() + << " seconds." << std::endl; +#endif + if (!points.empty()) { make_tc(points, intrinsic_dim, sparsity, From 67e9c3a6919cb6ebc66423ac165ac5417a3e7f9a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 2 Jun 2015 17:54:14 +0200 Subject: [PATCH 204/269] New generators + benchmark ANN --- .../Tangential_complex/benchmark_tc.cpp | 16 ++ .../test/Tangential_complex/test_utilities.h | 160 +++++++++++++++++- 2 files changed, 173 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 53f6c499246..ef920ed2f2f 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -653,6 +653,22 @@ int main() std::atof(param1.c_str()), std::atof(param2.c_str())); } + else if (input == "generate_two_spheres_d") + { + points = generate_points_on_two_spheres_d( + 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( + num_points, + std::atof(param1.c_str())); + } else if (input == "generate_torus_3D") { points = generate_points_on_torus_3D( diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index d3df879a0d7..1b0d0ff4ed1 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -300,14 +300,18 @@ std::vector generate_points_on_moment_curve( // R = big radius, r = small radius -template +template std::vector generate_points_on_torus_3D( - std::size_t num_points, double R, double r, bool uniform = false) + std::size_t num_points, double R, double r, bool uniform = false + /*, std::vector *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); @@ -345,6 +349,20 @@ std::vector generate_points_on_torus_3D( 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; } @@ -461,6 +479,111 @@ std::vector generate_points_on_sphere_d( return points; } +template +std::vector 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 generator(dim, radius); + std::vector points; + points.reserve(num_points); + + std::vector 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 > 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 +std::vector 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 generator(3, sphere_radius); + std::vector 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 > 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 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 std::vector generate_points_on_klein_bottle_3D( @@ -617,7 +740,8 @@ generate_points_on_klein_bottle_variant_5D( template void benchmark_spatial_search( - const std::vector &points, const Kernel &k) + const std::vector &points, const Kernel &k, + std::ostream & csv_file) { std::cout << "****************************************\n" @@ -660,6 +784,7 @@ void benchmark_spatial_search( double queries_time = t.elapsed(); std::cout << NUM_QUERIES << " queries among " << points.size() << " points: " << queries_time << std::endl; + csv_file << queries_time << ";"; } //**************************** nanoflann ************************************ { @@ -686,6 +811,35 @@ void benchmark_spatial_search( 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 + 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 From 5341a983c289b695249fe3136ef0f3537a7918bf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Jun 2015 14:31:30 +0200 Subject: [PATCH 205/269] Add check_correlation_between_inconsistencies_and_fatness --- .../include/CGAL/Tangential_complex.h | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5c7ebc1eeea..19a10e02213 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -47,6 +47,7 @@ #include #include +#include #include #include @@ -1931,6 +1932,61 @@ next_face: } return is_simplex_consistent(c); } + + // A simplex here is a list of point indices + template + double compute_simplex_fatness(IndexRange const& simplex) const + { + // Kernel functors + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename Kernel::Squared_distance_d sqdist = + m_k.squared_distance_d_object(); + typename Kernel::Difference_of_points_d diff_pts = + m_k.difference_of_points_d_object(); + + typename Tr_traits::Difference_of_points_d tr_diff_pts = + m_triangulations[0].tr().geom_traits().difference_of_points_d_object(); + + std::vector s(simplex.begin(), simplex.end()); + + // Compute basis + Tangent_space_basis basis(m_points[s[0]]); + for (int j = 0 ; j < m_intrinsic_dimension ; ++j) + { + Vector e = diff_pts( + m_points[s[j+1]], m_points[s[0]]); + basis.push_back(e); + } + basis = compute_gram_schmidt_basis(basis, m_k); + + // Compute the volume of the simplex: determinant + Eigen::MatrixXd m(m_intrinsic_dimension, m_intrinsic_dimension); + for (int j = 0 ; j < m_intrinsic_dimension ; ++j) + { + Tr_vector v_j = tr_diff_pts( + project_point(m_points[s[j+1]], basis), + project_point(m_points[s[0]], basis)); + for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + m(j, i) = CGAL::to_double(coord(v_j, i)); + } + double volume = + std::abs(m.determinant()) + / boost::math::factorial(m_intrinsic_dimension); + + // Compute the longest edge of the simplex + CGAL::Combination_enumerator combi(2, 0, m_intrinsic_dimension+1); + FT max_sq_length = FT(0); + for ( ; !combi.finished() ; ++combi) + { + FT sq_length = sqdist( + m_points[s[combi[0]]], m_points[s[combi[1]]]); + if (sq_length > max_sq_length) + max_sq_length = sq_length; + } + + return volume / std::pow(CGAL::sqrt(max_sq_length), m_intrinsic_dimension); + } // A simplex here is a list of point indices bool is_simplex_consistent(std::set const& simplex) const @@ -3050,6 +3106,78 @@ public: return os; } + // Return a pair + void check_correlation_between_inconsistencies_and_fatness() const + { + std::ofstream csv_consistent("output/correlation_consistent.csv"); // CJTODO TEMP + std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO TEMP + if (m_intrinsic_dimension < 3) + { + std::cerr << std::endl + << "==========================================================" << std::endl + << "check_correlation_between_inconsistencies_and_slivers():" << std::endl + << "Intrinsic dimension should be >= 3." << std::endl + << "==========================================================" << std::endl + << std::endl; + } + + std::size_t num_consistent_simplices = 0; + double sum_vol_edge_ratio_consistent = 0.; + std::size_t num_inconsistent_simplices = 0; + double sum_vol_edge_ratio_inconsistent = 0.; + typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); + // For each triangulation + for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + { + // For each cell + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + // Don't check infinite cells + if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + continue; + + std::set c = *it_inc_simplex; + c.insert(idx); // Add the missing index + + double fatness = compute_simplex_fatness(c); + + if (!is_simplex_consistent(c)) + { + ++num_inconsistent_simplices; + sum_vol_edge_ratio_inconsistent += fatness; + csv_inconsistent << fatness << std::endl; + } + else + { + ++num_consistent_simplices; + sum_vol_edge_ratio_consistent += fatness; + csv_consistent << fatness << std::endl; + } + } + } + + double avg_vol_edge_ratio_inconsistent = + sum_vol_edge_ratio_inconsistent / num_inconsistent_simplices; + double avg_vol_edge_ratio_consistent = + sum_vol_edge_ratio_consistent / num_consistent_simplices; + + std::cerr << std::endl + << "==========================================================" + << std::endl + << "check_correlation_between_inconsistencies_and_slivers()\n" + << " * Avg. volume/longest_edge^d ratio of consistent simplices: " + << avg_vol_edge_ratio_consistent + << " (" << num_consistent_simplices << " simplices)" << std::endl + << " * Avg. volume/longest_edge^d ratio of inconsistent simplices: " + << avg_vol_edge_ratio_inconsistent + << " (" << num_inconsistent_simplices << " simplices)" << std::endl + << "==========================================================" + << std::endl; + } + private: const Kernel m_k; const int m_intrinsic_dimension; From c284f2f626e36e3db3df40dc7fa48cd8e160f414 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 11:28:17 +0200 Subject: [PATCH 206/269] Add ANN option --- .../CGAL/Tangential_complex/Point_cloud.h | 81 +++++++++++++++++-- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 18452493061..6a273ce28fe 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -37,6 +37,14 @@ #include +#ifdef CGAL_TC_ANN_IS_AVAILABLE +# include +#endif + +#ifdef CGAL_TC_NANOFLANN_IS_AVAILABLE +# include "nanoflann.hpp" +#endif + namespace CGAL { namespace Tangential_complex_ { @@ -75,7 +83,10 @@ public: boost::counting_iterator(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 Point_cloud_data_structure( @@ -88,6 +99,8 @@ public: 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() @@ -149,11 +162,12 @@ protected: Tree m_tree; }; +//***************************************************************************** +//***************************************************************************** +//***************************************************************************** #ifdef CGAL_TC_NANOFLANN_IS_AVAILABLE -#include "nanoflann.hpp" - // "dataset to kd-tree" adaptor class template class Point_cloud_adaptator__nanoflann @@ -164,7 +178,7 @@ public: typedef typename Kernel::FT FT; /// The constructor that sets the data set source - Point_cloud_adaptator__nanoflann(const Point_container_ &points, Kernel const& k) + Point_cloud_adaptator__nanoflann(Point_container_ const& points, Kernel const& k) : m_points(points), m_k(k) {} @@ -313,8 +327,65 @@ protected: #endif //CGAL_TC_NANOFLANN_IS_AVAILABLE +//***************************************************************************** +//***************************************************************************** +//***************************************************************************** + +#ifdef CGAL_TC_ANN_IS_AVAILABLE + +template +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 From 6e743bc6c58602466af4f57ef09c36557d383d7d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 11:28:52 +0200 Subject: [PATCH 207/269] Add ANN option in config.h --- Tangential_complex/include/CGAL/Tangential_complex/config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 9053edefd5a..19804ffaa84 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -51,6 +51,7 @@ //========================= 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 From 0c5432cd060809a1b56f7d522c5f6cd53c581e52 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 11:30:23 +0200 Subject: [PATCH 208/269] Clean-up debugging code --- .../include/CGAL/Tangential_complex.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 19a10e02213..f96fd626ece 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -68,10 +68,6 @@ //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) //#define CGAL_ALPHA_TC const double ALPHA = 0.3; -#ifdef CGAL_LINKED_WITH_TBB -tbb::atomic ttt_star; // CJTODO TEMP -tbb::atomic ttt_intersect; -#endif //CJTODO: debug //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 @@ -317,8 +313,6 @@ public: { #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) Wall_clock_timer t; - ttt_intersect = 0; - ttt_star = 0; #endif // We need to do that because we don't want the container to copy the @@ -364,8 +358,6 @@ public: #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) std::cerr << "Tangential complex computed in " << t.elapsed() << " seconds." << std::endl; - std::cerr << "Intersect: " << ((double)ttt_intersect)/1000000 << " s\n" - << "Star: " << ((double)ttt_star)/1000000 << " s\n"; #endif } @@ -1440,10 +1432,6 @@ private: } } -#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) - ttt_star += 1000000*t_star.elapsed(); -#endif - //*************************************************** // Parse the faces of the star and add the ones that are in the // restriction to alpha-Tp @@ -1563,9 +1551,6 @@ next_face: does_voronoi_face_and_alpha_tangent_subspace_intersect( m_points, m_weights, i, P, curr_neighbors, m_orth_spaces[i], alpha, m_k); -#if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) - ttt_intersect += 1000000*t_inters.elapsed(); -#endif if (does_intersect) { star.push_back(current_DT_face); From b8914ccb4466facd97f23f076c3cb9a431e235b5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 11:32:31 +0200 Subject: [PATCH 209/269] Use Random_points_in_ball_d --- .../include/CGAL/Tangential_complex.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index f96fd626ece..0d87a1bf90c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -2053,18 +2053,18 @@ next_face: # ifdef CGAL_TC_PERTURB_POSITION_GLOBAL typename Kernel::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator( - m_ambient_dim, m_random_generator.get_double(0., m_half_sparsity)); + CGAL::Random_points_in_ball_d + tr_point_in_ball_generator( + m_ambient_dim, m_half_sparsity); // Parallel # if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) - Vector transl = k_pt_to_vec(*tr_point_on_sphere_generator); + Vector transl = k_pt_to_vec(*tr_point_in_ball_generator++); m_p_perturb_mutexes[point_idx].lock(); m_translations[point_idx] = transl; m_p_perturb_mutexes[point_idx].unlock(); // Sequential # else - m_translations[point_idx] = k_pt_to_vec(*tr_point_on_sphere_generator); + m_translations[point_idx] = k_pt_to_vec(*tr_point_in_ball_generator++); # endif # else // CGAL_TC_PERTURB_POSITION_TANGENTIAL @@ -2079,14 +2079,14 @@ next_face: typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - CGAL::Random_points_on_sphere_d - tr_point_on_sphere_generator( + CGAL::Random_points_in_ball_d + tr_point_in_ball_generator( m_intrinsic_dimension, m_random_generator.get_double(0., m_half_sparsity)); Tr_point local_random_transl = local_tr_traits.construct_weighted_point_d_object()( - *tr_point_on_sphere_generator, 0); + *tr_point_in_ball_generator++, 0); Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; for (int i = 0 ; i < m_intrinsic_dimension ; ++i) From 1be9e245bef9995c8d769440fa9a279c2548739b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 13:22:57 +0200 Subject: [PATCH 210/269] CGAL_ALPHA_TC => CGAL_FIXED_ALPHA_TC --- .../include/CGAL/Tangential_complex.h | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 0d87a1bf90c..4d1e89e3c3a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -66,7 +66,7 @@ #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) -//#define CGAL_ALPHA_TC +//#define CGAL_FIXED_ALPHA_TC const double ALPHA = 0.3; //CJTODO: debug @@ -244,7 +244,7 @@ public: , m_points_ds(m_points) , m_are_tangent_spaces_computed(m_points.size(), false) , m_tangent_spaces(m_points.size(), Tangent_space_basis()) -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) #endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM @@ -285,7 +285,7 @@ public: } void set_tangent_planes(const TS_container& tangent_spaces -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) , const OS_container& orthogonal_spaces #endif ) @@ -295,14 +295,14 @@ public: << " tangent spaces manually at the same time" << std::endl; std::exit(EXIT_FAILURE); #endif -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) CGAL_assertion(m_points.size() == tangent_spaces.size() && m_points.size() == orthogonal_spaces.size()); #else CGAL_assertion(m_points.size() == tangent_spaces.size()); #endif m_tangent_spaces = tangent_spaces; -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) m_orth_spaces = orthogonal_spaces; #endif for(std::size_t i=0; i m_are_tangent_spaces_computed; TS_container m_tangent_spaces; -#if defined(CGAL_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) OS_container m_orth_spaces; #endif Tr_container m_triangulations; // Contains the triangulations From f0b2722903dbd3daff1dd16d00470197975ad842 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 13:23:54 +0200 Subject: [PATCH 211/269] Added an option to perturb tangent planes --- Tangential_complex/include/CGAL/Tangential_complex.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 4d1e89e3c3a..5bae49d9a7f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -72,6 +72,7 @@ const double ALPHA = 0.3; //CJTODO: debug //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D +//#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE namespace CGAL { @@ -1687,6 +1688,10 @@ next_face: //const Point p = transl( // m_points[nn_it->first], m_translations[nn_it->first]); mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); +#ifdef CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE + mat_points(j, i) += m_random_generator.get_double( + -0.5*m_half_sparsity, 0.5*m_half_sparsity); +#endif #ifdef CGAL_TC_PERTURB_TANGENT_SPACE if (perturb) mat_points(j, i) += m_random_generator.get_double( From b78cb7ecf81897b619948a9f6e3b2713e490f0f2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 13:28:17 +0200 Subject: [PATCH 212/269] Better export for flat torus + debug code --- .../include/CGAL/Tangential_complex.h | 76 ++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 5bae49d9a7f..1c65f03cec1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -69,10 +69,13 @@ //#define CGAL_FIXED_ALPHA_TC const double ALPHA = 0.3; +//static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP + //CJTODO: debug //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE +//#define BETTER_EXPORT_FOR_FLAT_TORUS namespace CGAL { @@ -2353,8 +2356,15 @@ next_face: for (int ii = 0 ; ii < N ; ++ii) { int i = 0; +#if BETTER_EXPORT_FOR_FLAT_TORUS + // For flat torus + os << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 2)) << " " + << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 3)) << " " + << 1 * CGAL::to_double(coord(p, 1)); +#else for ( ; i < num_coords ; ++i) os << CGAL::to_double(coord(p, i)) << " "; +#endif if (i == 2) os << "0"; @@ -2593,11 +2603,51 @@ next_face: } std::cerr << std::endl; }*/ + + // CJTODO TEMP DEBUG + // If co-intrinsic dimension = 1, let's compare normals + /*if (m_ambient_dim - m_intrinsic_dimension == 1) + { + typename Kernel::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename Kernel::Squared_length_d k_sqlen = + m_k.squared_length_d_object(); + Vector pq = k_diff_pts( + compute_perturbed_point(q_idx), compute_perturbed_point(p_idx)); + pq = k_scaled_vec(pq, FT(1)/sqrt(k_sqlen(pq))); + FT dot_product_1 = std::abs( + k_inner_pdct(m_orth_spaces[p_idx][0], pq)); + FT dot_product_2 = std::abs( + k_inner_pdct(m_orth_spaces[q_idx][0], pq)); + csv_stream << inside_pt_indices.size() << " ; "; + csv_stream << dot_product_1 << " ; " << dot_product_2; + csv_stream << std::endl; + }*/ + // CJTODO TEMP DEBUG if (inside_pt_indices.size() > 1) { std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " << inconsistent_simplex.size() - 1 << " simplex\n"; + + // If co-intrinsic dimension = 1, let's compare normals + /*if (m_ambient_dim - m_intrinsic_dimension == 1) + { + std::cerr << "(dot product between normals = "; + std::set::const_iterator it_v = + inconsistent_simplex.begin(); + std::size_t i1 = *it_v; + ++it_v; + for ( ; it_v != inconsistent_simplex.end() ; ++it_v) + { + FT dot_products_between_normals = + k_inner_pdct(m_tangent_spaces[i1][0], m_tangent_spaces[*it_v][0]); + std::cerr << dot_products_between_normals << ", "; + //csv_stream << " ; " <= 3." << std::endl << "==========================================================" << std::endl << std::endl; @@ -3157,7 +3229,7 @@ public: std::cerr << std::endl << "==========================================================" << std::endl - << "check_correlation_between_inconsistencies_and_slivers()\n" + << "check_correlation_between_inconsistencies_and_fatness()\n" << " * Avg. volume/longest_edge^d ratio of consistent simplices: " << avg_vol_edge_ratio_consistent << " (" << num_consistent_simplices << " simplices)" << std::endl From 4e61119d0bd30c0dd6a51fe086a6a92d737a57cf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 13:30:14 +0200 Subject: [PATCH 213/269] Better generate_points_on_plane + generate_points_on_two_orthogonal_spheres_d --- .../Tangential_complex/benchmark_tc.cpp | 7 +- .../test/Tangential_complex/test_utilities.h | 78 +++++++++++++++++-- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index ef920ed2f2f..81082b5cbbc 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -337,6 +337,8 @@ void make_tc(std::vector &points, //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); + //tc.check_correlation_between_inconsistencies_and_fatness(); + //=========================================================================== // Export to OFF //=========================================================================== @@ -371,6 +373,8 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", final_num_inconsistent_local_tr); + //tc.check_correlation_between_inconsistencies_and_fatness(); + //========================================================================= // Export to OFF //========================================================================= @@ -644,7 +648,8 @@ int main() } else if (input == "generate_plane") { - points = generate_points_on_plane(num_points); + points = generate_points_on_plane( + num_points, intrinsic_dim, ambient_dim); } else if (input == "generate_sphere_d") { diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 1b0d0ff4ed1..82a58c776c3 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -237,7 +237,8 @@ bool load_points_from_file( } template -std::vector generate_points_on_plane(std::size_t num_points) +std::vector 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; @@ -250,9 +251,14 @@ std::vector generate_points_on_plane(std::size_t num_p #endif for (std::size_t i = 0 ; i < num_points ; ) { - FT x = rng.get_double(0, 5); - FT y = rng.get_double(0, 5); - Point p = construct_point(k, x, y, FT(0)); + std::vector 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; @@ -424,7 +430,7 @@ std::vector generate_points_on_torus_d( pt.push_back(std::sin(alpha)); } - Point p = k.construct_point_d_object()(pt.size(), pt.begin(), pt.end()); + 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; @@ -536,6 +542,68 @@ std::vector generate_points_on_two_spheres_d( return points; } +template +std::vector +generate_points_on_two_orthogonal_spheres_d( + std::size_t num_points, int intrinsic_dim, int ambient_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 generator(dim, radius); + std::vector points; + points.reserve(num_points); + + typename Kernel::Compute_coordinate_d k_coord = + k.compute_coordinate_d_object(); + + std::vector 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 > 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)); + } + + std::vector pt1(ambient_dim); + for (int i = 0 ; i < intrinsic_dim ; ++i) + pt1[i] = k_coord(p, i); + // TODO : p2 + +#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 std::vector generate_points_on_3sphere_and_circle( From fc891eafb50c785f1d7b6a888f65741afd905945 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 15:39:49 +0200 Subject: [PATCH 214/269] CGAL_ALPHA_TC => CGAL_FIXED_ALPHA_TC --- Tangential_complex/test/Tangential_complex/aniso_TC.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp index 586c63b0bdc..147411ee2e5 100644 --- a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp +++ b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp @@ -201,7 +201,7 @@ void compute_and_set_tangent_planes(TC& tc, } tsc.push_back(CGAL::Tangential_complex_::compute_gram_schmidt_basis(ts, kerd)); -#ifdef CGAL_ALPHA_TC +#ifdef CGAL_FIXED_ALPHA_TC // compute the osc Basis os(origin); @@ -211,7 +211,7 @@ void compute_and_set_tangent_planes(TC& tc, } tc.set_tangent_planes(tsc -#ifdef CGAL_ALPHA_TC +#ifdef CGAL_FIXED_ALPHA_TC , osc #endif ); From 4fb3edce3f3f98c2ddd6c9fc0135c83268a927a9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 15:40:16 +0200 Subject: [PATCH 215/269] Add thickening vectors to Basis and take it into account in the TC Now, the dimension of the local triangulation is not always m_intrinsic_dimension. --- .../include/CGAL/Tangential_complex.h | 135 +++++++++++++----- .../include/CGAL/Tangential_complex/config.h | 6 + .../CGAL/Tangential_complex/utilities.h | 48 ++++++- 3 files changed, 149 insertions(+), 40 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 1c65f03cec1..8b0edab8d9b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -66,8 +66,6 @@ #endif //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) -//#define CGAL_FIXED_ALPHA_TC -const double ALPHA = 0.3; //static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP @@ -102,6 +100,25 @@ template < typename Kernel, // ambiant dimension typename DimensionTag, // intrinsic dimension typename Concurrency_tag = CGAL::Parallel_tag, +#ifdef CGAL_ALPHA_TC + // For the alpha-TC, the dimension of the RT is variable + // => we need to force it to Dynamic_dimension_tag + typename Tr = Regular_triangulation + < + Regular_triangulation_euclidean_traits< + Epick_d >, + + Triangulation_data_structure + < + typename Regular_triangulation_euclidean_traits< + Epick_d >::Dimension, + Triangulation_vertex >, Vertex_data >, + Triangulation_full_cell > > + > + > +#else typename Tr = Regular_triangulation < Regular_triangulation_euclidean_traits< @@ -117,6 +134,7 @@ template < Epick_d > > > > +#endif > class Tangential_complex { @@ -1054,20 +1072,6 @@ private: if (verbose) std::cerr << "** Computing tangent tri #" << i << " **" << std::endl; //std::cerr << "***********************************************" << std::endl; - Triangulation &local_tr = - m_triangulations[i].construct_triangulation(m_intrinsic_dimension); - const Tr_traits &local_tr_traits = local_tr.geom_traits(); - Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); - - // Kernel functor & objects - typename Kernel::Squared_distance_d k_sqdist = - m_k.squared_distance_d_object(); - - // Triangulation's traits functor & objects - typename Tr_traits::Point_weight_d point_weight = - local_tr_traits.point_weight_d_object(); - typename Tr_traits::Power_center_d power_center = - local_tr_traits.power_center_d_object(); // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions @@ -1083,6 +1087,23 @@ private: m_tangent_spaces[i] = compute_tangent_space(center_pt, i); #endif } + + int triangulation_dim = local_triangulation_dim(i); + Triangulation &local_tr = + m_triangulations[i].construct_triangulation(triangulation_dim); + const Tr_traits &local_tr_traits = local_tr.geom_traits(); + Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); + + // Kernel functor & objects + typename Kernel::Squared_distance_d k_sqdist = + m_k.squared_distance_d_object(); + + // Triangulation's traits functor & objects + typename Tr_traits::Point_weight_d point_weight = + local_tr_traits.point_weight_d_object(); + typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object(); + #ifdef CGAL_TC_PERTURB_TANGENT_SPACE else if (m_perturb_tangent_space[i]) { @@ -1113,8 +1134,8 @@ private: if(eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) { proj_wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(m_intrinsic_dimension, ORIGIN), - m_weights[i]); + local_tr_traits.construct_point_d_object()(triangulation_dim, ORIGIN), + m_weights[i]); } else { @@ -1175,7 +1196,7 @@ private: vh->data() = neighbor_point_idx; // Let's recompute squared_star_sphere_radius_plus_margin - if (local_tr.current_dimension() >= m_intrinsic_dimension) + if (local_tr.current_dimension() >= triangulation_dim) { squared_star_sphere_radius_plus_margin = boost::none; // Get the incident cells and look for the biggest circumsphere @@ -1781,6 +1802,13 @@ next_face: */ } + // Returns the dimension of the ith local triangulation + // This is particularly useful for the alpha-TC + int local_triangulation_dim(std::size_t i) const + { + return m_tangent_spaces[i].dimension(); + } + Point compute_perturbed_point(std::size_t pt_idx) const { #ifdef CGAL_TC_PERTURB_POSITION @@ -1834,11 +1862,19 @@ next_face: global_point = k_transl(global_point, k_scaled_vec(tsb[i], coord(p, i))); +#ifdef CGAL_ALPHA_TC + Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); + for (int i = 0 ; i < tv.size() ; ++i) + { + global_point = k_transl( + global_point, + k_scaled_vec(tv[i].vec, coord(p, m_intrinsic_dimension + i))); + } +#endif return global_point; } // Project the point in the tangent space - // The weight will be the squared distance between p and the projection of p Tr_bare_point project_point(const Point &p, const Tangent_space_basis &tsb) const { @@ -1846,19 +1882,28 @@ next_face: m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); + + Vector v = diff_points(p, tsb.origin()); std::vector coords; // Ambiant-space coords of the projected point - coords.reserve(m_intrinsic_dimension); + coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { // Local coords are given by the inner product with the vectors of tsb - Vector v = diff_points(p, tsb.origin()); FT coord = inner_pdct(v, tsb[i]); coords.push_back(coord); } - - return Tr_bare_point(m_intrinsic_dimension, coords.begin(), coords.end()); + +#ifdef CGAL_ALPHA_TC + Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); + for (int i = 0 ; i < tv.size() ; ++i) + { + FT coord = inner_pdct(v, tv[i].vec); + coords.push_back(coord); + } +#endif + return Tr_bare_point(tsb.dimension(), coords.begin(), coords.end()); } // Project the point in the tangent space @@ -1884,6 +1929,8 @@ next_face: m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); @@ -1892,24 +1939,37 @@ next_face: std::vector coords; // Ambiant-space coords of the projected point std::vector p_proj(ccci(tsb.origin()), ccci(tsb.origin(), 0)); - coords.reserve(m_intrinsic_dimension); + coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) { // Local coords are given by the inner product with the vectors of tsb - FT coord = inner_pdct(v, tsb[i]); - coords.push_back(coord); + FT c = inner_pdct(v, tsb[i]); + coords.push_back(c); - // p_proj += coord * v; + // p_proj += c * v; for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += coord * tsb[i][j]; + p_proj[j] += c * coord(tsb[i], j); } + +#ifdef CGAL_ALPHA_TC + Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); + for (int i = 0 ; i < tv.size() ; ++i) + { + FT c = inner_pdct(v, tv[i].vec); + coords.push_back(c); + + // p_proj += c * v; + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += c * coord(tv[i].vec, j); + } +#endif Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); return tr_traits.construct_weighted_point_d_object() ( tr_traits.construct_point_d_object()( - m_intrinsic_dimension, coords.begin(), coords.end()), + tsb.dimension(), coords.begin(), coords.end()), w - m_k.squared_distance_d_object()(p, projected_pt) ); } @@ -1942,10 +2002,11 @@ next_face: m_triangulations[0].tr().geom_traits().difference_of_points_d_object(); std::vector s(simplex.begin(), simplex.end()); + std::size_t simplex_dim = s.size() - 1; // Compute basis Tangent_space_basis basis(m_points[s[0]]); - for (int j = 0 ; j < m_intrinsic_dimension ; ++j) + for (int j = 0 ; j < simplex_dim ; ++j) { Vector e = diff_pts( m_points[s[j+1]], m_points[s[0]]); @@ -1954,21 +2015,21 @@ next_face: basis = compute_gram_schmidt_basis(basis, m_k); // Compute the volume of the simplex: determinant - Eigen::MatrixXd m(m_intrinsic_dimension, m_intrinsic_dimension); - for (int j = 0 ; j < m_intrinsic_dimension ; ++j) + Eigen::MatrixXd m(simplex_dim, simplex_dim); + for (int j = 0 ; j < simplex_dim ; ++j) { Tr_vector v_j = tr_diff_pts( project_point(m_points[s[j+1]], basis), project_point(m_points[s[0]], basis)); - for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + for (int i = 0 ; i < simplex_dim ; ++i) m(j, i) = CGAL::to_double(coord(v_j, i)); } double volume = std::abs(m.determinant()) - / boost::math::factorial(m_intrinsic_dimension); + / boost::math::factorial(simplex_dim); // Compute the longest edge of the simplex - CGAL::Combination_enumerator combi(2, 0, m_intrinsic_dimension+1); + CGAL::Combination_enumerator combi(2, 0, simplex_dim+1); FT max_sq_length = FT(0); for ( ; !combi.finished() ; ++combi) { @@ -1978,7 +2039,7 @@ next_face: max_sq_length = sq_length; } - return volume / std::pow(CGAL::sqrt(max_sq_length), m_intrinsic_dimension); + return volume / std::pow(CGAL::sqrt(max_sq_length), simplex_dim); } // A simplex here is a list of point indices diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 19804ffaa84..150f06066c8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -30,6 +30,12 @@ # define TBB_USE_THREADING_TOOL #endif +//=========================== Alpha-TC or not? ================================ + +//#define CGAL_FIXED_ALPHA_TC +const double ALPHA = 0.3; + +#define CGAL_ALPHA_TC //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index b547125a1ef..e76fd8d3846 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -140,9 +140,10 @@ namespace Tangential_complex_ { template struct Basis { - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Vector_d Vector; - typedef typename std::vector::const_iterator const_iterator; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + typedef typename std::vector::const_iterator const_iterator; Point m_origin; //fixme should probably be (const?) ref ? std::vector m_vectors; @@ -163,6 +164,47 @@ namespace Tangential_complex_ { Basis(const Point& p, const std::vector& vectors) : m_origin(p), m_vectors(vectors) { } + +#ifdef CGAL_ALPHA_TC + // Thickening vectors... + + struct Thickening_vector + { + Thickening_vector() : alpha_minus(FT(0)), alpha_plus(FT(0)) {} + + Vector vec; + FT alpha_minus; + FT alpha_plus; + }; + typedef std::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 alpha_plus) + { + m_thickening_vectors.push_back( + Thickening_vector(vec, alpha_minus, alpha_plus)); + } + + int dimension() const + { + return static_cast(m_vectors.size() + m_thickening_vectors.size()); + } +#else + int dimension() const + { + return static_cast(m_vectors.size()); + } +#endif }; template From 0232ae4ff8ad1d200fcb43f02765896f715e651a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 15:40:39 +0200 Subject: [PATCH 216/269] Fix warning --- Tangential_complex/test/Tangential_complex/test_utilities.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 82a58c776c3..6f90145622e 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -381,7 +381,8 @@ static void generate_uniform_points_on_torus_d( if (current_point.size() == 2*dim) { *out++ = k.construct_point_d_object()( - current_point.size(), current_point.begin(), current_point.end()); + static_cast(current_point.size()), + current_point.begin(), current_point.end()); } else { From b93ecfe222385e03d2ae0414ffd4a4a61f95348c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 16:34:52 +0200 Subject: [PATCH 217/269] Moved and fixed does_voronoi_face_and_alpha_tangent_subspace_intersect It now takes position perturbations into account --- .../include/CGAL/Tangential_complex.h | 153 ++++++++++++++++-- .../CGAL/Tangential_complex/utilities.h | 146 ----------------- 2 files changed, 142 insertions(+), 157 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8b0edab8d9b..b08de382716 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -102,7 +102,7 @@ template < typename Concurrency_tag = CGAL::Parallel_tag, #ifdef CGAL_ALPHA_TC // For the alpha-TC, the dimension of the RT is variable - // => we need to force it to Dynamic_dimension_tag + // => we need to force typename Tr = Regular_triangulation < Regular_triangulation_euclidean_traits< @@ -1349,8 +1349,7 @@ private: Amb_RT local_amb_tr(m_ambient_dim); // Insert p - Weighted_point wp = m_k.construct_weighted_point_d_object()(center_pt, - m_weights[i]); + Weighted_point wp = compute_perturbed_weighted_point(i); Amb_RT_VH center_vertex = local_amb_tr.insert(wp); center_vertex->data() = i; if (verbose) @@ -1378,12 +1377,6 @@ private: // called while other threads are perturbing the positions Weighted_point neighbor_wp = compute_perturbed_weighted_point(neighbor_point_idx); -// fixme ? -// Above seems incorrect since we later pass m_points[] to -// "does_voronoi_face_and_alpha_tangent_subspace_intersect()" and we lose -// the possible position pertubation of wp. -// Either we ignore the translations and it's neighbor_wp = points[idx]+weight -// or need to give m_translations to the voronoi intersections computations // "4*m_sq_half_sparsity" because both points can be perturbed if (squared_star_sphere_radius_plus_margin @@ -1574,8 +1567,7 @@ next_face: #endif bool does_intersect = does_voronoi_face_and_alpha_tangent_subspace_intersect( - m_points, m_weights, i, P, curr_neighbors, - m_orth_spaces[i], alpha, m_k); + i, P, curr_neighbors, m_orth_spaces[i], alpha); if (does_intersect) { star.push_back(current_DT_face); @@ -2878,6 +2870,145 @@ next_face: return inconsistencies_found; } + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_alpha_tangent_subspace_intersect( + std::size_t center_pt_index, + Indexed_point_range const& P, + Indexed_point_range_2 const& Q, + Orthogonal_space_basis const& orthogonal_subspace_basis, + FT alpha) + { + // Notations: + // Fv: Voronoi k-face + // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) + + typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); + typename Kernel::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object(); + typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); + + Point center_pt = compute_perturbed_point(center_pt_index); + int const ambient_dim = m_k.point_dimension_d_object()(center_pt); + + std::size_t card_P = P.size(); + std::size_t card_Q = Q.size(); + std::size_t card_OSB = orthogonal_subspace_basis.size(); + std::size_t num_couples_among_P = card_P*(card_P-1)/2; + std::size_t num_equations = + 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; + + // Linear solver + typedef CGAL::Quadratic_program Linear_program; + typedef CGAL::Quadratic_program_solution LP_solution; + + Linear_program lp(CGAL::SMALLER, false); + int current_row = 0; + + //=========== First set of equations =========== + // For points pi in P + // 2(p0 - pi).x = p0^2 - w0 - pi^2 + wi + Point const& p0 = center_pt; + FT const w0 = m_weights[center_pt_index]; + FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); + + for (typename Indexed_point_range::const_iterator it_p = P.begin(), + it_p_end = P.end() ; + it_p != it_p_end ; ++it_p) + { + Point pi; + FT wi; + compute_perturbed_weighted_point(*it_p, pi, wi); + + for (int k = 0 ; k < ambient_dim ; ++k) + lp.set_a(k, current_row, 2*(coord(p0, k) - coord(pi, k))); + + FT pi_dot_pi = scalar_pdct(pt_to_vec(pi), pt_to_vec(pi)); + lp.set_b(current_row, p0_dot_p0 - pi_dot_pi - w0 + wi); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + // CJTODO: this code might be useful for Option 1 + /*CGAL::Combination_enumerator pi_pj(2, 0, static_cast(card_P)); + for ( ; !pi_pj.finished() ; ++pi_pj) + { + Point const& pi = P[pi_pj[0]]; + FT wi = all_weights[pi_pj[0]]; + Point const& pj = P[pi_pj[1]]; + FT wj = all_weights[pi_pj[1]]; + + for (int k = 0 ; k < ambient_dim ; ++k) + { + FT a = 2*(coord(pi, k) + coord(pj, k)); + lp.set_a(k, current_row , -a); + lp.set_a(k, current_row + 1, a); + } + + FT b = scalar_pdct(pi, pi) - wi - scalar_pdct(pj, pj) + wj; + lp.set_b(current_row , -b); + lp.set_b(current_row + 1, b); + + current_row += 2; + }*/ + + //=========== Second set of equations =========== + // For each point qi in Q + // 2(qi - p0).x <= qi^2 - wi - p0^2 + w0 + for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; + it_q != it_q_end ; ++it_q) + { + Point qi; + FT wi; + compute_perturbed_weighted_point(*it_q, qi, wi); + + for (int k = 0 ; k < ambient_dim ; ++k) + lp.set_a(k, current_row, 2*(coord(qi, k) - coord(p0, k))); + + FT qi_dot_qi = scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)); + lp.set_b(current_row, qi_dot_qi - wi - p0_dot_p0 + w0); + + ++current_row; + } + + //=========== Third set of equations =========== + // For each vector bi of OSB, (x-p).bi <= alpha and >= -alpha + // p is the origin of the basis + // bi.x <= bi.p + alpha + // -bi.x <= -bi.p + alpha + for (typename Orthogonal_space_basis::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; + it_osb != it_osb_end ; ++it_osb) + { + Vector const& bi = *it_osb; + + for (int k = 0 ; k < ambient_dim ; ++k) + { + lp.set_a(k, current_row , bi[k]); + lp.set_a(k, current_row + 1, -bi[k]); + } + + Point const& basis_origin = orthogonal_subspace_basis.origin(); + FT bi_dot_p = scalar_pdct(bi, pt_to_vec(basis_origin)); + lp.set_b(current_row , bi_dot_p + alpha); + lp.set_b(current_row + 1, -bi_dot_p + alpha); + + current_row += 2; + } + + //=========== Other LP parameters =========== + lp.set_c(0, 1); // Minimize x[0] + + //=========== Solve ========================= + LP_solution solution = CGAL::solve_linear_program(lp, ET()); + bool ret = (solution.status() == CGAL::QP_OPTIMAL); + + return ret; + } + std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_OFF_simplices, bool color_inconsistencies = false, diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index e76fd8d3846..3a4b9e42609 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -263,152 +263,6 @@ namespace Tangential_complex_ { } while (std::next_permutation(booleans.begin(), booleans.end())); } - // P: dual face in Delaunay triangulation (p0, p1, ..., pn) - // Q: vertices which are common neighbors of all vertices of P - template - bool does_voronoi_face_and_alpha_tangent_subspace_intersect( - Point_range const& all_points, - Weight_range const& all_weights, - std::size_t center_pt_index, - Indexed_point_range const& P, - Indexed_point_range_2 const& Q, - Basis const& orthogonal_subspace_basis, - typename K::FT alpha, - K const& k) - { - // Notations: - // Fv: Voronoi k-face - // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) - - typedef typename K::FT FT; - typedef typename K::Point_d Point; - typedef typename K::Vector_d Vector; - - typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object(); - typename K::Point_to_vector_d pt_to_vec = k.point_to_vector_d_object(); - typename K::Compute_coordinate_d coord = k.compute_coordinate_d_object(); - - Point const& center_pt = all_points[center_pt_index]; - int const ambient_dim = k.point_dimension_d_object()(center_pt); - - std::size_t card_P = P.size(); - std::size_t card_Q = Q.size(); - std::size_t card_OSB = orthogonal_subspace_basis.size(); - std::size_t num_couples_among_P = card_P*(card_P-1)/2; - std::size_t num_equations = - 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; - - // Linear solver - typedef CGAL::Quadratic_program Linear_program; - typedef CGAL::Quadratic_program_solution LP_solution; - - Linear_program lp(CGAL::SMALLER, false); - int current_row = 0; - - //=========== First set of equations =========== - // For points pi in P - // 2(p0 - pi).x = p0^2 - w0 - pi^2 + wi - Point const& p0 = center_pt; - FT const w0 = all_weights[center_pt_index]; - FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); - - for (typename Indexed_point_range::const_iterator it_p = P.begin(), - it_p_end = P.end() ; - it_p != it_p_end ; ++it_p) - { - Point const& pi = all_points[*it_p]; - FT const wi = all_weights[*it_p]; - - for (int k = 0 ; k < ambient_dim ; ++k) - lp.set_a(k, current_row, 2*(coord(p0, k) - coord(pi, k))); - - FT pi_dot_pi = scalar_pdct(pt_to_vec(pi), pt_to_vec(pi)); - lp.set_b(current_row, p0_dot_p0 - pi_dot_pi - w0 + wi); - lp.set_r(current_row, CGAL::EQUAL); - - ++current_row; - } - - // CJTODO: this code might be useful for Option 1 - /*CGAL::Combination_enumerator pi_pj(2, 0, static_cast(card_P)); - for ( ; !pi_pj.finished() ; ++pi_pj) - { - Point const& pi = P[pi_pj[0]]; - FT wi = all_weights[pi_pj[0]]; - Point const& pj = P[pi_pj[1]]; - FT wj = all_weights[pi_pj[1]]; - - for (int k = 0 ; k < ambient_dim ; ++k) - { - FT a = 2*(coord(pi, k) + coord(pj, k)); - lp.set_a(k, current_row , -a); - lp.set_a(k, current_row + 1, a); - } - - FT b = scalar_pdct(pi, pi) - wi - scalar_pdct(pj, pj) + wj; - lp.set_b(current_row , -b); - lp.set_b(current_row + 1, b); - - current_row += 2; - }*/ - - //=========== Second set of equations =========== - // For each point qi in Q - // 2(qi - p0).x <= qi^2 - wi - p0^2 + w0 - for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), - it_q_end = Q.end() ; - it_q != it_q_end ; ++it_q) - { - Point const& qi = all_points[*it_q]; - FT const wi = all_weights[*it_q]; - - for (int k = 0 ; k < ambient_dim ; ++k) - lp.set_a(k, current_row, 2*(coord(qi, k) - coord(p0, k))); - - FT qi_dot_qi = scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)); - lp.set_b(current_row, qi_dot_qi - wi - p0_dot_p0 + w0); - - ++current_row; - } - - //=========== Third set of equations =========== - // For each vector bi of OSB, (x-p).bi <= alpha and >= -alpha - // p is the origin of the basis - // bi.x <= bi.p + alpha - // -bi.x <= -bi.p + alpha - for (typename Basis::const_iterator it_osb = - orthogonal_subspace_basis.begin(), - it_osb_end = orthogonal_subspace_basis.end() ; - it_osb != it_osb_end ; ++it_osb) - { - Vector const& bi = *it_osb; - - for (int k = 0 ; k < ambient_dim ; ++k) - { - lp.set_a(k, current_row , bi[k]); - lp.set_a(k, current_row + 1, -bi[k]); - } - - Point const& basis_origin = orthogonal_subspace_basis.origin(); - FT bi_dot_p = scalar_pdct(bi, pt_to_vec(basis_origin)); - lp.set_b(current_row , bi_dot_p + alpha); - lp.set_b(current_row + 1, -bi_dot_p + alpha); - - current_row += 2; - } - - //=========== Other LP parameters =========== - lp.set_c(0, 1); // Minimize x[0] - - //=========== Solve ========================= - LP_solution solution = CGAL::solve_linear_program(lp, ET()); - bool ret = (solution.status() == CGAL::QP_OPTIMAL); - - return ret; - } - } // namespace Tangential_complex_ } //namespace CGAL From 723ec9b1a97ea497974d364c6d64713d5eebcbc5 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 16 Jun 2015 19:19:50 +0200 Subject: [PATCH 218/269] Missing constructor + improve code --- Tangential_complex/include/CGAL/Tangential_complex.h | 7 +++---- .../include/CGAL/Tangential_complex/utilities.h | 5 ++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b08de382716..c30802731df 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1097,6 +1097,7 @@ private: // Kernel functor & objects typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); + typename Kernel::Equal_d k_eq = m_k.equal_d_object(); // Triangulation's traits functor & objects typename Tr_traits::Point_weight_d point_weight = @@ -1128,10 +1129,8 @@ private: //*************************************************** // Insert p - typename Kernel::Equal_d eq = m_k.equal_d_object(); - Tr_point proj_wp; - if(eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) + if(k_eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) { proj_wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(triangulation_dim, ORIGIN), @@ -1343,7 +1342,7 @@ private: //*************************************************** #ifdef CGAL_TC_PROFILING - Wall_clock_timer t_star; + Wall_clock_timer t_star; #endif Amb_RT local_amb_tr(m_ambient_dim); diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 3a4b9e42609..f0a8e7b99c4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -170,7 +170,10 @@ namespace Tangential_complex_ { struct Thickening_vector { - Thickening_vector() : alpha_minus(FT(0)), alpha_plus(FT(0)) {} + 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; From 758482934a657b3346e65c8063f3c6709251155f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 17 Jun 2015 19:05:13 +0200 Subject: [PATCH 219/269] Take the "thickening vectors" into account when computing the TC Replacement of the previous fixed-alpha TC code by a version using the "thickening vectors" (for now, the alphas associated to a thickening vector have the same hard-coded values) --- .../include/CGAL/Tangential_complex.h | 508 +++++++++--------- .../include/CGAL/Tangential_complex/config.h | 5 +- 2 files changed, 245 insertions(+), 268 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c30802731df..69b470748f5 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -266,7 +266,7 @@ public: , m_points_ds(m_points) , m_are_tangent_spaces_computed(m_points.size(), false) , m_tangent_spaces(m_points.size(), Tangent_space_basis()) -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) #endif #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM @@ -307,7 +307,7 @@ public: } void set_tangent_planes(const TS_container& tangent_spaces -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS , const OS_container& orthogonal_spaces #endif ) @@ -317,14 +317,14 @@ public: << " tangent spaces manually at the same time" << std::endl; std::exit(EXIT_FAILURE); #endif -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS CGAL_assertion(m_points.size() == tangent_spaces.size() && m_points.size() == orthogonal_spaces.size()); #else CGAL_assertion(m_points.size() == tangent_spaces.size()); #endif m_tangent_spaces = tangent_spaces; -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS m_orth_spaces = orthogonal_spaces; #endif for(std::size_t i=0; i& r ) const { for( size_t i = r.begin() ; i != r.end() ; ++i) - { -#ifdef CGAL_FIXED_ALPHA_TC - m_tc.compute_alpha_tangent_triangulation(i, ALPHA); -#else m_tc.compute_tangent_triangulation(i); -#endif - } } }; #endif // CGAL_LINKED_WITH_TBB @@ -1076,17 +1060,34 @@ private: // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions const Point center_pt = compute_perturbed_point(i); + Tangent_space_basis &tsb = m_tangent_spaces[i]; // Estimate the tangent space if (!m_are_tangent_spaces_computed[i]) { -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = - compute_tangent_space(center_pt, i, true/*normalize*/, &m_orth_spaces[i]); +#ifdef CGAL_TC_EXPORT_NORMALS + tsb = compute_tangent_space(center_pt, i, true/*normalize*/, &m_orth_spaces[i]); #else - m_tangent_spaces[i] = compute_tangent_space(center_pt, i); + tsb = compute_tangent_space(center_pt, i); #endif } +#ifdef CGAL_TC_PERTURB_TANGENT_SPACE + else if (m_perturb_tangent_space[i]) + { +#ifdef CGAL_TC_EXPORT_NORMALS + tsb = compute_tangent_space(center_pt, i, + true /*normalize_basis*/, + &m_orth_spaces[i], + true /*perturb*/); +#else + tsb = compute_tangent_space(center_pt, i, + true /*normalize_basis*/, + NULL /*ortho basis*/, + true /*perturb*/); +#endif + m_perturb_tangent_space[i] = false; + } +#endif int triangulation_dim = local_triangulation_dim(i); Triangulation &local_tr = @@ -1105,23 +1106,6 @@ private: typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object(); -#ifdef CGAL_TC_PERTURB_TANGENT_SPACE - else if (m_perturb_tangent_space[i]) - { -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) - m_tangent_spaces[i] = compute_tangent_space(center_pt, i, - true /*normalize_basis*/, - &m_orth_spaces[i], - true /*perturb*/); -#else - m_tangent_spaces[i] = compute_tangent_space(center_pt, i, - true /*normalize_basis*/, - NULL /*ortho basis*/, - true /*perturb*/); -#endif - m_perturb_tangent_space[i] = false; - } -#endif //*************************************************** // Build a minimal triangulation in the tangent space @@ -1130,7 +1114,7 @@ private: // Insert p Tr_point proj_wp; - if(k_eq(compute_perturbed_point(i), m_tangent_spaces[i].origin())) + if(k_eq(compute_perturbed_point(i), tsb.origin())) { proj_wp = local_tr_traits.construct_weighted_point_d_object()( local_tr_traits.construct_point_d_object()(triangulation_dim, ORIGIN), @@ -1139,8 +1123,7 @@ private: else { const Weighted_point& wp = compute_perturbed_weighted_point(i); - proj_wp = project_point_and_compute_weight(wp, m_tangent_spaces[i], - local_tr_traits); + proj_wp = project_point_and_compute_weight(wp, tsb, local_tr_traits); } center_vertex = local_tr.insert(proj_wp); @@ -1182,7 +1165,7 @@ private: break; Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, neighbor_weight, m_tangent_spaces[i], + neighbor_pt, neighbor_weight, tsb, local_tr_traits); Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); @@ -1251,11 +1234,26 @@ private: } } +#ifdef CGAL_ALPHA_TC + if (tsb.num_thickening_vectors() == 0) + update_star__no_thickening_vectors(i); + else + update_star__with_thickening_vector(i); +#else + update_star__no_thickening_vectors(i); +#endif + } + + // Updates m_stars[i] directly from m_triangulations[i] + void update_star__no_thickening_vectors(std::size_t i) + { //*************************************************** // Update the associated star (in m_stars) //*************************************************** Star &star = m_stars[i]; star.clear(); + Triangulation &local_tr = m_triangulations[i].tr(); + Tr_vertex_handle center_vertex = m_triangulations[i].center_vertex(); int cur_dim_plus_1 = local_tr.current_dimension() + 1; std::vector incident_cells; @@ -1288,214 +1286,64 @@ private: //CGAL::export_triangulation_to_off(off_stream_tr, local_tr); } -#ifdef CGAL_FIXED_ALPHA_TC - void compute_alpha_tangent_triangulation(std::size_t i, FT alpha, - bool verbose = false) +#ifdef CGAL_ALPHA_TC + void update_star__with_thickening_vector(std::size_t i) { - if (verbose) - std::cerr << "** Computing alpha tangent tri #" - << i << " **" << std::endl; - - typedef Regular_triangulation_euclidean_traits Amb_RT_Traits; - typedef Regular_triangulation< - Amb_RT_Traits, - Triangulation_data_structure< - typename Amb_RT_Traits::Dimension, - Triangulation_vertex - > > Amb_RT; - typedef typename Amb_RT::Weighted_point Amb_RT_Point; - typedef typename Amb_RT::Vertex_handle Amb_RT_VH; - typedef typename Amb_RT::Full_cell_handle Amb_RT_FCH; - //typedef typename Amb_RT::Finite_full_cell_const_iterator Amb_FFC_it; - - typename Kernel::Point_drop_weight_d k_drop_w = - m_k.point_drop_weight_d_object(); - typename Kernel::Squared_distance_d k_sqdist = - m_k.squared_distance_d_object(); - typename Kernel::Point_weight_d k_point_weight = - m_k.point_weight_d_object(); - typename Kernel::Power_center_d k_power_center = - m_k.power_center_d_object(); - - // No need to lock the mutex here since this will not be called while - // other threads are perturbing the positions - const Point ¢er_pt = m_points[i]; - - // Estimate the tangent space - if (!m_are_tangent_spaces_computed[i]) - { - m_tangent_spaces[i] = - compute_tangent_space(center_pt, i, true /*normalize*/, &m_orth_spaces[i]); - } -#ifdef CGAL_TC_PERTURB_TANGENT_SPACE - else if (m_perturb_tangent_space[i]) - { - m_tangent_spaces[i] = - compute_tangent_space(center_pt, i, true, &m_orth_spaces[i], true); - m_perturb_tangent_space[i] = false; - } -#endif - - //*************************************************** - // Build a minimal triangulation in the tangent space - // (we only need the star of p in the AMBIENT triangulation) - //*************************************************** - -#ifdef CGAL_TC_PROFILING - Wall_clock_timer t_star; -#endif - - Amb_RT local_amb_tr(m_ambient_dim); - - // Insert p - Weighted_point wp = compute_perturbed_weighted_point(i); - Amb_RT_VH center_vertex = local_amb_tr.insert(wp); - center_vertex->data() = i; - if (verbose) - std::cerr << "* Inserted point #" << i << std::endl; - - INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); - - // While building the local triangulation, we keep the radius - // of the sphere "star sphere" centered at "center_vertex" - // and which contains all the - // circumspheres of the star of "center_vertex" - boost::optional squared_star_sphere_radius_plus_margin; - - // Insert points until we find a point which is outside "star shere" - for (INS_iterator nn_it = ins_range.begin() ; - nn_it != ins_range.end() ; - ++nn_it) - { - std::size_t neighbor_point_idx = nn_it->first; - - // ith point = p, which is already inserted - if (neighbor_point_idx != i) - { - // No need to lock the Mutex_for_perturb here since this will not be - // called while other threads are perturbing the positions - Weighted_point neighbor_wp = - compute_perturbed_weighted_point(neighbor_point_idx); - - // "4*m_sq_half_sparsity" because both points can be perturbed - if (squared_star_sphere_radius_plus_margin - && k_sqdist(center_pt, k_drop_w(neighbor_wp)) - > *squared_star_sphere_radius_plus_margin) - break; - - Amb_RT_VH vh = local_amb_tr.insert_if_in_star(neighbor_wp, center_vertex); - //Amb_RT_VH vh = local_amb_tr.insert(neighbor_wp); - if (vh != Amb_RT_VH()) - { - if (verbose) - std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; - - vh->data() = neighbor_point_idx; - - // Let's recompute squared_star_sphere_radius_plus_margin - if (local_amb_tr.current_dimension() == m_ambient_dim) - { - squared_star_sphere_radius_plus_margin = boost::none; - // Get the incident cells and look for the biggest circumsphere - std::vector incident_cells; - local_amb_tr.incident_full_cells( - center_vertex, - std::back_inserter(incident_cells)); - for (typename std::vector::iterator cit = - incident_cells.begin(); cit != incident_cells.end(); ++cit) - { - Amb_RT_FCH cell = *cit; - if (local_amb_tr.is_infinite(cell)) - { - squared_star_sphere_radius_plus_margin = boost::none; - break; - } - else - { - Amb_RT_Point c = k_power_center( - boost::make_transform_iterator( - cell->vertices_begin(), - vertex_handle_to_point), - boost::make_transform_iterator( - cell->vertices_end(), - vertex_handle_to_point)); - - FT sq_power_sphere_diam = 4*k_point_weight(c); - - if (!squared_star_sphere_radius_plus_margin - || sq_power_sphere_diam > - *squared_star_sphere_radius_plus_margin) - { - squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; - } - } - } - - // Let's add the margin, now - // The value depends on whether we perturb weight or position - if (squared_star_sphere_radius_plus_margin) - { -#ifdef CGAL_TC_PERTURB_WEIGHT - squared_star_sphere_radius_plus_margin = - *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; -#else - squared_star_sphere_radius_plus_margin = CGAL::square( - CGAL::sqrt(*squared_star_sphere_radius_plus_margin) - + 2*m_half_sparsity); -#endif - } - } - } - } - } - //*************************************************** // Parse the faces of the star and add the ones that are in the // restriction to alpha-Tp // Update the associated star (in m_stars) //*************************************************** + + int triangulation_dim = local_triangulation_dim(i); + Triangulation &local_tr = m_triangulations[i].tr(); + Tr_traits const& local_tr_traits = local_tr.geom_traits(); + Tr_vertex_handle center_vertex = m_triangulations[i].center_vertex(); + Tangent_space_basis const& tsb = m_tangent_spaces[i]; + Star &star = m_stars[i]; star.clear(); - int cur_dim_plus_1 = m_ambient_dim + 1; + int cur_dim_plus_1 = triangulation_dim + 1; - std::vector incident_cells; - local_amb_tr.incident_full_cells( + std::vector incident_cells; + local_tr.incident_full_cells( center_vertex, std::back_inserter(incident_cells)); - typedef std::set DT_face; // DT face without center vertex (i) - typedef std::set Neighbor_vertices; + typedef std::set DT_face; // DT face without center vertex (i) + typedef std::set Neighbor_vertices; typedef std::map DT_faces_and_neighbors; - // Maps that associate a k-face and the list of its neighbor points - // (i.e. there are k+1-cofaces that contain these points) - // N.B.: each k-face contains 'i', so 'i' is not stored in the faces - // faces_and_neighbors[0] => dim 1, faces_and_neighbors[1] => dim 2 + // Maps that associate a m-face F and the points of its m+1-cofaces + // (except the points of F). Those points are called its "neighbors". + // N.B.: each m-face contains 'i', so 'i' is not stored in the faces + // N.B.2: faces_and_neighbors[0] => dim 1, faces_and_neighbors[1] => dim 2 std::vector faces_and_neighbors; - faces_and_neighbors.resize(m_ambient_dim); + faces_and_neighbors.resize(triangulation_dim); // Fill faces_and_neighbors - // Let's first take care of the D-faces - typename std::vector::const_iterator it_c = incident_cells.begin(); - typename std::vector::const_iterator it_c_end = incident_cells.end(); + // Let's first take care of the maximal simplices (dim = triangulation_dim) + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end = incident_cells.end(); // For each cell for ( ; it_c != it_c_end ; ++it_c) { DT_face face; - // CJTODO: use (*it_c)->vertices_begin(), etc. for (int j = 0 ; j < cur_dim_plus_1 ; ++j) { - std::size_t index = (*it_c)->vertex(j)->data(); - if (index == std::numeric_limits::max()) + Tr_vertex_handle vh = (*it_c)->vertex(j); + // Skip infinite simplices + if (vh == local_tr.infinite_vertex()) goto next_face; - if (index != i) - face.insert(index); + if (vh->data() != i) + face.insert(vh); } - faces_and_neighbors[m_ambient_dim-1][face] = Neighbor_vertices(); + // No co-faces => no neighbors + faces_and_neighbors[triangulation_dim-1][face] = Neighbor_vertices(); next_face: ; } - // Then the D-k-faces... - int current_dim = m_ambient_dim - 1; + // Then the D-m-faces... + int current_dim = triangulation_dim - 1; while (current_dim > 0) { // Let's fill faces_and_neighbors[current_dim-1] @@ -1504,21 +1352,21 @@ next_face: faces_and_neighbors[current_dim-1]; typedef DT_faces_and_neighbors::const_iterator FaN_it; - // Parse k+1-faces + // Parse m+1-faces for (FaN_it it_k_p1_face = faces_and_neighbors[current_dim].begin(), it_k_p1_face_end = faces_and_neighbors[current_dim].end() ; it_k_p1_face != it_k_p1_face_end ; ++it_k_p1_face) { DT_face const& k_p1_face = it_k_p1_face->first; - // Add each k faces to cur_faces_and_nghb + // Add each m-face to cur_faces_and_nghb std::size_t n = current_dim + 1; // Not +2 since 'i' is not stored std::vector booleans(n, false); std::fill(booleans.begin() + 1, booleans.end(), true); do { DT_face k_face; - std::size_t remaining_vertex; + Tr_vertex_handle remaining_vertex; DT_face::const_iterator it_v = k_p1_face.begin(); for (std::size_t i = 0 ; i < n ; ++i, ++it_v) { @@ -1537,7 +1385,8 @@ next_face: // For each face V of Voronoi_cell(P[i]) - dim 0 to dim D-1 // I.e. For each DT face F of the star - dim D to dim 1 - current_dim = m_ambient_dim; + // Test if V intersects the thickened tangent space + current_dim = triangulation_dim; while (current_dim > 0) { // Remember: faces_and_neighbors[current_dim-1] stores @@ -1557,19 +1406,28 @@ next_face: == current_dim); // P: list of current_DT_face points (including 'i') - std::vector P( + std::vector P( current_DT_face.begin(), current_DT_face.end()); - P.push_back(i); + P.push_back(center_vertex); -#ifdef CGAL_TC_PROFILING - Wall_clock_timer t_inters; -#endif bool does_intersect = - does_voronoi_face_and_alpha_tangent_subspace_intersect( - i, P, curr_neighbors, m_orth_spaces[i], alpha); + does_voronoi_face_and_tangent_subspace_intersect( + triangulation_dim, + center_vertex, + P, + curr_neighbors, + tsb, + local_tr_traits); if (does_intersect) { - star.push_back(current_DT_face); + // Get the indices of the face's points + Incident_simplex face; + DT_face::const_iterator it_vh = current_DT_face.begin(); + DT_face::const_iterator it_vh_end = current_DT_face.end(); + for ( ; it_vh != it_vh_end ; ++it_vh) + face.insert((*it_vh)->data()); + + star.push_back(face); // Clear all subfaces of current_DT_face from the maps for (int dim = current_dim - 1 ; dim > 0 ; --dim) @@ -1596,17 +1454,9 @@ next_face: --current_dim; } - - // CJTODO DEBUG - //std::cerr << "\nChecking topology and geometry..." - // << (local_amb_tr.is_valid(true) ? "OK.\n" : "Error.\n"); - // DEBUG: output the local mesh into an OFF file - //std::stringstream sstr; - //sstr << "data/local_tri_" << i << ".off"; - //std::ofstream off_stream_tr(sstr.str()); - //CGAL::export_triangulation_to_off(off_stream_tr, local_amb_tr); } -#endif // CGAL_FIXED_ALPHA_TC +#endif //CGAL_ALPHA_TC + Tangent_space_basis compute_tangent_space( const Point &p @@ -1765,6 +1615,19 @@ next_face: } } } +#if defined(CGAL_ALPHA_TC) && defined(CGAL_USE_A_FIXED_ALPHA) + // Add the orthogonal vectors as "thickening vectors" + for (int j = m_ambient_dim - m_intrinsic_dimension - 1 ; + j >= 0 ; + --j) + { + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); + tsb.add_thickening_vector( + normalize_vector(v, m_k), -CGAL_TC_ALPHA_VALUE, CGAL_TC_ALPHA_VALUE); + } +#endif m_are_tangent_spaces_computed[i] = true; @@ -2868,16 +2731,135 @@ next_face: return inconsistencies_found; } + + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_tangent_subspace_intersect( + int points_dim, + Tr_vertex_handle center_vh, + VH_range_a const& P, + VH_range_b const& Q, + Tangent_space_basis const& tsb, + const Tr_traits &tr_traits) const + { + // Notations: + // Fv: Voronoi k-face + // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) + + typename Tr_traits::Point_drop_weight_d drop_w = + tr_traits.point_drop_weight_d_object(); + typename Tr_traits::Point_weight_d point_weight = + tr_traits.point_weight_d_object(); + typename Tr_traits::Scalar_product_d scalar_pdct = + tr_traits.scalar_product_d_object(); + typename Tr_traits::Point_to_vector_d pt_to_vec = + tr_traits.point_to_vector_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + tr_traits.compute_coordinate_d_object(); + + typename Kernel::Compute_coordinate_d k_coord = + m_k.compute_coordinate_d_object(); + + std::size_t card_P = P.size(); + std::size_t card_Q = Q.size(); + + // Linear solver + typedef CGAL::Quadratic_program Linear_program; + typedef CGAL::Quadratic_program_solution LP_solution; + + Linear_program lp(CGAL::SMALLER, false); + int current_row = 0; + + //=========== First set of equations =========== + // For points pi in P + // 2(p0 - pi).x = p0^2 - wght(p0) - pi^2 + wght(pi) + Tr_point const& p0 = center_vh->point(); + FT const w0 = point_weight(p0); + FT p0_dot_p0 = scalar_pdct(pt_to_vec(drop_w(p0)), pt_to_vec(drop_w(p0))); + + for (typename VH_range_a::const_iterator it_vh = P.begin(), + it_vh_end = P.end() ; + it_vh != it_vh_end ; ++it_vh) + { + Tr_point const& pi = (*it_vh)->point(); + FT const wi = point_weight(pi); + + for (int k = 0 ; k < points_dim ; ++k) + lp.set_a(k, current_row, 2*(coord(p0, k) - coord(pi, k))); + + FT pi_dot_pi = scalar_pdct(pt_to_vec(drop_w(pi)), pt_to_vec(drop_w(pi))); + lp.set_b(current_row, p0_dot_p0 - pi_dot_pi - w0 + wi); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + //=========== Second set of equations =========== + // For each point qi in Q + // 2(qi - p0).x <= qi^2 - wght(pi) - p0^2 + wght(p0) + for (typename VH_range_b::const_iterator it_vh = Q.begin(), + it_vh_end = Q.end() ; + it_vh != it_vh_end ; ++it_vh) + { + Tr_point const& qi = (*it_vh)->point(); + FT const wi = point_weight(qi); + + for (int k = 0 ; k < points_dim ; ++k) + lp.set_a(k, current_row, 2*(coord(qi, k) - coord(p0, k))); + + FT qi_dot_qi = scalar_pdct(pt_to_vec(drop_w(qi)), pt_to_vec(drop_w(qi))); + lp.set_b(current_row, qi_dot_qi - wi - p0_dot_p0 + w0); + + ++current_row; + } + + //=========== Third set of equations =========== + // For each thickening vector bj of TSB, + // x.bj <= alpha_plus and >= alpha_minus + // where bj is in the TSB => bj = (0..., 1..., 0) (1 is at the ith position) + // x.bj <= alpha_plus + // -x.bj <= -alpha_minus + std::size_t j = points_dim - tsb.num_thickening_vectors(); + for (Tangent_space_basis::Thickening_vectors::const_iterator + it_tv = tsb.thickening_vectors().begin(), + it_tv_end = tsb.thickening_vectors().end() ; + it_tv != it_tv_end ; ++it_tv) + { + Tangent_space_basis::Thickening_vector const& bj = *it_tv; + + for (int k = 0 ; k < points_dim ; ++k) + { + lp.set_a(k, current_row , (j == k ? 1. : 0.)); + lp.set_a(k, current_row + 1, (j == k ? -1. : 0.)); + } + + lp.set_b(current_row , bj.alpha_plus); + lp.set_b(current_row + 1, -bj.alpha_minus); + + current_row += 2; + ++j; + } + + //=========== Other LP parameters =========== + lp.set_c(0, 1); // Minimize x[0] + + //=========== Solve ========================= + LP_solution solution = CGAL::solve_linear_program(lp, ET()); + bool ret = (solution.status() == CGAL::QP_OPTIMAL); + + return ret; + } // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template + template bool does_voronoi_face_and_alpha_tangent_subspace_intersect( std::size_t center_pt_index, - Indexed_point_range const& P, - Indexed_point_range_2 const& Q, + Indexed_point_range_a const& P, + Indexed_point_range_b const& Q, Orthogonal_space_basis const& orthogonal_subspace_basis, - FT alpha) + FT alpha) const { // Notations: // Fv: Voronoi k-face @@ -2892,10 +2874,6 @@ next_face: std::size_t card_P = P.size(); std::size_t card_Q = Q.size(); - std::size_t card_OSB = orthogonal_subspace_basis.size(); - std::size_t num_couples_among_P = card_P*(card_P-1)/2; - std::size_t num_equations = - 2*num_couples_among_P + card_P*card_Q + 2*card_OSB; // Linear solver typedef CGAL::Quadratic_program Linear_program; @@ -2911,8 +2889,8 @@ next_face: FT const w0 = m_weights[center_pt_index]; FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); - for (typename Indexed_point_range::const_iterator it_p = P.begin(), - it_p_end = P.end() ; + for (typename Indexed_point_range_a::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { Point pi; @@ -2955,7 +2933,7 @@ next_face: //=========== Second set of equations =========== // For each point qi in Q // 2(qi - p0).x <= qi^2 - wi - p0^2 + w0 - for (typename Indexed_point_range_2::const_iterator it_q = Q.begin(), + for (typename Indexed_point_range_b::const_iterator it_q = Q.begin(), it_q_end = Q.end() ; it_q != it_q_end ; ++it_q) { @@ -2977,17 +2955,17 @@ next_face: // p is the origin of the basis // bi.x <= bi.p + alpha // -bi.x <= -bi.p + alpha - for (typename Orthogonal_space_basis::const_iterator it_osb = - orthogonal_subspace_basis.begin(), - it_osb_end = orthogonal_subspace_basis.end() ; + for (Orthogonal_space_basis::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; it_osb != it_osb_end ; ++it_osb) { Vector const& bi = *it_osb; for (int k = 0 ; k < ambient_dim ; ++k) { - lp.set_a(k, current_row , bi[k]); - lp.set_a(k, current_row + 1, -bi[k]); + lp.set_a(k, current_row , coord(bi, k)); + lp.set_a(k, current_row + 1, -coord(bi, k)); } Point const& basis_origin = orthogonal_subspace_basis.origin(); @@ -3456,7 +3434,7 @@ private: Points_ds m_points_ds; std::vector m_are_tangent_spaces_computed; TS_container m_tangent_spaces; -#if defined(CGAL_FIXED_ALPHA_TC) || defined(CGAL_TC_EXPORT_NORMALS) +#ifdef CGAL_TC_EXPORT_NORMALS OS_container m_orth_spaces; #endif Tr_container m_triangulations; // Contains the triangulations diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 150f06066c8..5ada1b8bbfa 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -32,10 +32,9 @@ //=========================== Alpha-TC or not? ================================ -//#define CGAL_FIXED_ALPHA_TC -const double ALPHA = 0.3; - #define CGAL_ALPHA_TC + #define CGAL_USE_A_FIXED_ALPHA + const double CGAL_TC_ALPHA_VALUE = 0.3; //========================= Debugging & profiling ============================= #define CGAL_TC_PROFILING From c6b1e4c7cd873de60f41265b1f6be33146914fdf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 19 Jun 2015 17:19:46 +0200 Subject: [PATCH 220/269] Function to compute the intersection between a Voronoi cell and a tangent plane Returns any point of the intersection --- .../include/CGAL/Tangential_complex.h | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 69b470748f5..ed40b96adcb 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -2735,7 +2735,8 @@ next_face: // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P template - bool does_voronoi_face_and_tangent_subspace_intersect( + CGAL::Quadratic_program_solution + compute_voronoi_face_and_tangent_subspace_LP_problem( int points_dim, Tr_vertex_handle center_vh, VH_range_a const& P, @@ -2846,7 +2847,59 @@ next_face: //=========== Solve ========================= LP_solution solution = CGAL::solve_linear_program(lp, ET()); - bool ret = (solution.status() == CGAL::QP_OPTIMAL); + return solution; + } + + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_tangent_subspace_intersect( + int points_dim, + Tr_vertex_handle center_vh, + VH_range_a const& P, + VH_range_b const& Q, + Tangent_space_basis const& tsb, + const Tr_traits &tr_traits) const + { + return compute_voronoi_face_and_tangent_subspace_LP_problem( + points_dim, center_vh, P, Q, tsb, tr_traits).status() == CGAL::QP_OPTIMAL; + } + + // Returns any point of intersection + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + boost::optional compute_voronoi_face_and_tangent_subspace_intersection( + int points_dim, + Tr_vertex_handle center_vh, + VH_range_a const& P, + VH_range_b const& Q, + Tangent_space_basis const& tsb, + const Tr_traits &tr_traits) const + { + typedef CGAL::Quadratic_program_solution LP_solution; + + LP_solution sol = compute_voronoi_face_and_tangent_subspace_LP_problem( + points_dim, center_vh, P, Q, tsb, tr_traits); + + boost::optional ret; + if (sol.status() == CGAL::QP_OPTIMAL) + { + std::vector p; + p.reserve(points_dim); + for (LP_solution::Variable_value_iterator + it_v = sol.variable_values_begin(), + it_v_end = sol.variable_values_end() ; + it_v != it_v_end ; ++it_v) + { + p.push_back(to_double(*it_v)); + } + ret = m_k.construct_point_d_object()(points_dim, p.begin(), p.end()); + } + else + { + ret = boost::none; + } return ret; } From 0332d2c7eea386394f9c12ec3f6226336540e9bb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 10:36:22 +0200 Subject: [PATCH 221/269] Param center_vertex was useless + added function... ... compute_aff_of_voronoi_face_and_tangent_subspace_intersection --- .../include/CGAL/Tangential_complex.h | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ed40b96adcb..b05fba5b9f9 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1412,8 +1412,7 @@ next_face: bool does_intersect = does_voronoi_face_and_tangent_subspace_intersect( - triangulation_dim, - center_vertex, + triangulation_dim, P, curr_neighbors, tsb, @@ -2738,7 +2737,6 @@ next_face: CGAL::Quadratic_program_solution compute_voronoi_face_and_tangent_subspace_LP_problem( int points_dim, - Tr_vertex_handle center_vh, VH_range_a const& P, VH_range_b const& Q, Tangent_space_basis const& tsb, @@ -2775,12 +2773,12 @@ next_face: //=========== First set of equations =========== // For points pi in P // 2(p0 - pi).x = p0^2 - wght(p0) - pi^2 + wght(pi) - Tr_point const& p0 = center_vh->point(); + typename VH_range_a::const_iterator it_vh = P.begin(); + Tr_point const& p0 = (*it_vh)->point(); FT const w0 = point_weight(p0); FT p0_dot_p0 = scalar_pdct(pt_to_vec(drop_w(p0)), pt_to_vec(drop_w(p0))); - - for (typename VH_range_a::const_iterator it_vh = P.begin(), - it_vh_end = P.end() ; + ++it_vh; + for (typename VH_range_a::const_iterator it_vh_end = P.end() ; it_vh != it_vh_end ; ++it_vh) { Tr_point const& pi = (*it_vh)->point(); @@ -2855,23 +2853,38 @@ next_face: template bool does_voronoi_face_and_tangent_subspace_intersect( int points_dim, - Tr_vertex_handle center_vh, VH_range_a const& P, VH_range_b const& Q, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { return compute_voronoi_face_and_tangent_subspace_LP_problem( - points_dim, center_vh, P, Q, tsb, tr_traits).status() == CGAL::QP_OPTIMAL; + points_dim, P, Q, tsb, tr_traits).status() == CGAL::QP_OPTIMAL; } - // Returns any point of intersection + // Returns any point of the intersection between aff(voronoi_cell) and a + // tangent space. + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + template + boost::optional + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + int points_dim, + VH_range_a const& P, + Tangent_space_basis const& tsb, + const Tr_traits &tr_traits) const + { + // As we're only interested by aff(v), Q is empty + return compute_voronoi_face_and_tangent_subspace_intersection( + points_dim, P, std::vector(), tsb, tr_traits); + } + + // Returns any point of the intersection between a Voronoi cell and a + // tangent space. // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P template boost::optional compute_voronoi_face_and_tangent_subspace_intersection( int points_dim, - Tr_vertex_handle center_vh, VH_range_a const& P, VH_range_b const& Q, Tangent_space_basis const& tsb, From 6e44497e856a78f998170aae66dec68c9e516c51 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 11:24:51 +0200 Subject: [PATCH 222/269] Simplified some loops --- .../include/CGAL/Tangential_complex.h | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index b05fba5b9f9..6d8f3369a26 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -618,10 +618,8 @@ public: { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { // For each cell Star::const_iterator it_inc_simplex = m_stars[idx].begin(); @@ -668,10 +666,8 @@ public: { int max_dim = -1; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { // For each cell of the star Star::const_iterator it_inc_simplex = m_stars[idx].begin(); @@ -814,10 +810,8 @@ public: { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { // We build a SC along the way in case it's inconsistent Simplicial_complex sc; @@ -3422,10 +3416,8 @@ public: double sum_vol_edge_ratio_consistent = 0.; std::size_t num_inconsistent_simplices = 0; double sum_vol_edge_ratio_inconsistent = 0.; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); - typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation - for (std::size_t idx = 0 ; it_tr != it_tr_end ; ++it_tr, ++idx) + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { // For each cell Star::const_iterator it_inc_simplex = m_stars[idx].begin(); From 341f17a49cdc6866f250d31760e4e27468977b57 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 18:24:47 +0200 Subject: [PATCH 223/269] First step of solve_inconsistencies_using_adaptive_alpha_TC: priority queue --- .../Tangential_complex/benchmark_tc.cpp | 3 +- .../include/CGAL/Tangential_complex.h | 292 +++++++++++++++--- 2 files changed, 253 insertions(+), 42 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 81082b5cbbc..1545d2e20af 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -405,7 +405,8 @@ void make_tc(std::vector &points, //========================================================================= t.reset(); // Try to solve the remaining inconstencies - tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + //tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); + tc.solve_inconsistencies_using_adaptive_alpha_TC(); fix2_time = t.elapsed(); t.reset(); max_dim = tc.export_TC(complex, false); /*std::set > not_delaunay_simplices; diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6d8f3369a26..6b2a27e3769 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -213,6 +213,34 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; + class Simplex_and_alpha + { + public: + Simplex_and_alpha() {} + Simplex_and_alpha( + std::size_t center_point_index, + std::set const& simplex, // including "center_point_index" + FT squared_alpha, + Vector const& thickening_vector) + : m_center_point_index(center_point_index), + m_simplex(simplex), + m_squared_alpha(squared_alpha), + m_thickening_vector(thickening_vector) + {} + + // For the priority queue + bool operator>(Simplex_and_alpha const& other) const + { + return m_squared_alpha > other.m_squared_alpha; + } + + private: + std::size_t m_center_point_index; // P + std::set m_simplex; // Missing simplex (includes P) + FT m_squared_alpha; + Vector m_thickening_vector; // (P, Cq) + }; + public: typedef typename std::vector TS_container; typedef typename std::vector OS_container; @@ -726,6 +754,92 @@ public: << 100. * stats_after.second / stats_after.first << "%" << std::endl; } + + void solve_inconsistencies_using_adaptive_alpha_TC() + { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif + +#ifdef CGAL_TC_VERBOSE + std::cerr << "Fixing inconsistencies using adaptive alpha TC..." << std::endl; +#endif + + // Kernel/traits functors + typename Kernel::Difference_of_points_d k_diff_points = + m_k.difference_of_points_d_object(); + typename Kernel::Squared_length_d k_sqlen = + m_k.squared_length_d_object(); + typename Tr_traits::Construct_weighted_point_d constr_wp = + m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); + + //------------------------------------------------------------------------- + //1. Fill priority queue + //------------------------------------------------------------------------- + typedef std::priority_queue, + std::greater > AATC_pq; + + AATC_pq pqueue; + + // For each triangulation + for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) + { + // For each cell + Star::const_iterator it_inc_simplex = m_stars[idx].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + Incident_simplex const& s = *it_inc_simplex; + + // Don't check infinite cells + if (*s.rbegin() == std::numeric_limits::max()) + continue; + + // P: points whose star does not contain "s" + std::vector P; + is_simplex_consistent(idx, s, std::back_inserter(P), true); + + if (!P.empty()) + { + Triangulation const& q_tr = m_triangulations[idx].tr(); + std::set full_simplex = s; + full_simplex.insert(idx); + for (std::vector::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) + { + // star(p) does not contain "s" + std::size_t const& p = *it_p; + + Tr_bare_point intersection = + *compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + q_tr.current_dimension(), + project_points_and_compute_weights( + full_simplex, m_tangent_spaces[idx], q_tr.geom_traits()), + m_tangent_spaces[idx], + q_tr.geom_traits()); + + // The following computations are done in the Euclidian space + Point inters_global = unproject_point( + constr_wp(intersection, 0), m_tangent_spaces[idx], + q_tr.geom_traits()); + Vector thickening_v = k_diff_points(inters_global, m_points[p]); + FT squared_alpha = k_sqlen(thickening_v); + + pqueue.push(Simplex_and_alpha( + p, full_simplex, squared_alpha, thickening_v)); + } + } + } + } + + // CJTODO: the rest + +#ifdef CGAL_TC_PROFILING + std::cerr << "Tangential complex fixed in " << t.elapsed() + << " seconds." << std::endl; +#endif + } std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, @@ -1400,15 +1514,29 @@ next_face: == current_dim); // P: list of current_DT_face points (including 'i') - std::vector P( - current_DT_face.begin(), current_DT_face.end()); - P.push_back(center_vertex); + std::vector P; + P.reserve(current_DT_face.size() + 1); + for (DT_face::const_iterator it = current_DT_face.begin(), + it_end = current_DT_face.end() ; it != it_end ; ++it) + { + P.push_back((*it)->point()); + } + P.push_back(center_vertex->point()); + + // Q: vertices which are common neighbors of all vertices of P + std::vector Q; + P.reserve(curr_neighbors.size()); + for (Neighbor_vertices::const_iterator it = curr_neighbors.begin(), + it_end = curr_neighbors.end() ; it != it_end ; ++it) + { + Q.push_back((*it)->point()); + } bool does_intersect = does_voronoi_face_and_tangent_subspace_intersect( triangulation_dim, P, - curr_neighbors, + Q, tsb, local_tr_traits); if (does_intersect) @@ -1820,6 +1948,24 @@ next_face: w - m_k.squared_distance_d_object()(p, projected_pt) ); } + + // Project all the points in the tangent space + template + std::vector project_points_and_compute_weights( + const Indexed_point_range &point_indices, + const Tangent_space_basis &tsb, + const Tr_traits &tr_traits) const + { + std::vector ret; + for (typename Indexed_point_range::const_iterator + it = point_indices.begin(), it_end = point_indices.end(); + it != it_end ; ++it) + { + ret.push_back(project_point_and_compute_weight( + m_points[*it], m_weights[*it], tsb, tr_traits)); + } + return ret; + } // A simplex here is a local tri's full cell handle bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) const @@ -1890,10 +2036,9 @@ next_face: } // A simplex here is a list of point indices + // CJTODO: improve it like the other "is_simplex_consistent" below bool is_simplex_consistent(std::set const& simplex) const { - int cur_dim_plus_1 = static_cast(simplex.size()); - // Check if the simplex is in the stars of all its vertices std::set::const_iterator it_point_idx = simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p @@ -1908,16 +2053,75 @@ next_face: Star const& star = m_stars[point_idx]; // What we're looking for is "simplex" \ point_idx - Incident_simplex ic_to_find = simplex; - ic_to_find.erase(point_idx); + Incident_simplex is_to_find = simplex; + is_to_find.erase(point_idx); // For each cell - if (std::find(star.begin(), star.end(), ic_to_find) == star.end()) + if (std::find(star.begin(), star.end(), is_to_find) == star.end()) return false; } return true; } + + // A simplex here is a list of point indices + // "s" contains all the points of the simplex except "center_point" + // This function returns the points whose star doesn't contain the simplex + // N.B.: the function assumes that the simplex is contained in + // star(center_point) + template // value_type = std::size_t + bool is_simplex_consistent( + std::size_t center_point, + Incident_simplex const& s, // without "center_point" + OutputIterator points_whose_star_does_not_contain_s, + bool check_also_in_non_maximal_faces = false) const + { + std::set full_simplex = s; + full_simplex.insert(center_point); + + // Check if the simplex is in the stars of all its vertices + Incident_simplex::const_iterator it_point_idx = s.begin(); + // For each point p of the simplex, we parse the incidents cells of p + // and we check if "simplex" is among them + for ( ; it_point_idx != s.end() ; ++it_point_idx) + { + std::size_t point_idx = *it_point_idx; + // Don't check infinite simplices + if (point_idx == std::numeric_limits::max()) + continue; + + Star const& star = m_stars[point_idx]; + + // What we're looking for is full_simplex \ point_idx + Incident_simplex is_to_find = full_simplex; + is_to_find.erase(point_idx); + + if (check_also_in_non_maximal_faces) + { + // For each simplex "is" of the star, check if ic_to_simplex is + // included in "is" + bool found = false; + for (Star::const_iterator is = star.begin(), is_end = star.end() ; + !found && is != is_end ; ++is) + { + if (std::includes(is->begin(), is->end(), + is_to_find.begin(), is_to_find.end())) + found = true; + } + + if (!found) + *points_whose_star_does_not_contain_s++ = point_idx; + } + else + { + // Does the star contain is_to_find? + if (std::find(star.begin(), star.end(), is_to_find) == star.end()) + *points_whose_star_does_not_contain_s++ = point_idx; + } + } + + return true; + } #ifdef CGAL_LINKED_WITH_TBB // Functor for try_to_solve_inconsistencies_in_a_local_triangulation function @@ -2688,10 +2892,10 @@ next_face: Star const& star = m_stars[point_idx]; // What we're looking for is "simplex" \ point_idx - Incident_simplex ic_to_find = simplex; - ic_to_find.erase(point_idx); + Incident_simplex is_to_find = simplex; + is_to_find.erase(point_idx); - if (std::find(star.begin(), star.end(), ic_to_find) == star.end()) + if (std::find(star.begin(), star.end(), is_to_find) == star.end()) { solve_inconsistency_by_adding_higher_dimensional_simplices( tr_index, *it_point_idx, simplex); @@ -2724,15 +2928,17 @@ next_face: return inconsistencies_found; } - + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template + // Note the computation is made in local coordinates. "tsb"'s vectors are not + // used because these vectors become (0..., 1..., 0) in local coordinates. + template CGAL::Quadratic_program_solution compute_voronoi_face_and_tangent_subspace_LP_problem( int points_dim, - VH_range_a const& P, - VH_range_b const& Q, + Weighted_point_range_a const& P, + Weighted_point_range_b const& Q, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { @@ -2767,15 +2973,15 @@ next_face: //=========== First set of equations =========== // For points pi in P // 2(p0 - pi).x = p0^2 - wght(p0) - pi^2 + wght(pi) - typename VH_range_a::const_iterator it_vh = P.begin(); - Tr_point const& p0 = (*it_vh)->point(); + typename Weighted_point_range_a::const_iterator it_p = P.begin(); + Tr_point const& p0 = *it_p; FT const w0 = point_weight(p0); FT p0_dot_p0 = scalar_pdct(pt_to_vec(drop_w(p0)), pt_to_vec(drop_w(p0))); - ++it_vh; - for (typename VH_range_a::const_iterator it_vh_end = P.end() ; - it_vh != it_vh_end ; ++it_vh) + ++it_p; + for (typename Weighted_point_range_a::const_iterator it_p_end = P.end() ; + it_p != it_p_end ; ++it_p) { - Tr_point const& pi = (*it_vh)->point(); + Tr_point const& pi = *it_p; FT const wi = point_weight(pi); for (int k = 0 ; k < points_dim ; ++k) @@ -2791,11 +2997,11 @@ next_face: //=========== Second set of equations =========== // For each point qi in Q // 2(qi - p0).x <= qi^2 - wght(pi) - p0^2 + wght(p0) - for (typename VH_range_b::const_iterator it_vh = Q.begin(), - it_vh_end = Q.end() ; - it_vh != it_vh_end ; ++it_vh) + for (typename Weighted_point_range_b::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; + it_q != it_q_end ; ++it_q) { - Tr_point const& qi = (*it_vh)->point(); + Tr_point const& qi = *it_q; FT const wi = point_weight(qi); for (int k = 0 ; k < points_dim ; ++k) @@ -2810,7 +3016,7 @@ next_face: //=========== Third set of equations =========== // For each thickening vector bj of TSB, // x.bj <= alpha_plus and >= alpha_minus - // where bj is in the TSB => bj = (0..., 1..., 0) (1 is at the ith position) + // where bj is in the TSB => bj = (0..., 1..., 0) (1 is at the jth position) // x.bj <= alpha_plus // -x.bj <= -alpha_minus std::size_t j = points_dim - tsb.num_thickening_vectors(); @@ -2844,11 +3050,11 @@ next_face: // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template + template bool does_voronoi_face_and_tangent_subspace_intersect( int points_dim, - VH_range_a const& P, - VH_range_b const& Q, + Weighted_point_range_a const& P, + Weighted_point_range_b const& Q, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { @@ -2859,37 +3065,41 @@ next_face: // Returns any point of the intersection between aff(voronoi_cell) and a // tangent space. // P: dual face in Delaunay triangulation (p0, p1, ..., pn) - template - boost::optional + // Return value: the point coordinates are expressed in the tsb base + template + boost::optional compute_aff_of_voronoi_face_and_tangent_subspace_intersection( int points_dim, - VH_range_a const& P, + Weighted_point_range const& P, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { // As we're only interested by aff(v), Q is empty return compute_voronoi_face_and_tangent_subspace_intersection( - points_dim, P, std::vector(), tsb, tr_traits); + points_dim, P, std::vector(), + tsb, tr_traits); } // Returns any point of the intersection between a Voronoi cell and a // tangent space. // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P - template - boost::optional compute_voronoi_face_and_tangent_subspace_intersection( + // Return value: the point coordinates are expressed in the tsb base + template + boost::optional + compute_voronoi_face_and_tangent_subspace_intersection( int points_dim, - VH_range_a const& P, - VH_range_b const& Q, + Weighted_point_range_a const& P, + Weighted_point_range_b const& Q, Tangent_space_basis const& tsb, const Tr_traits &tr_traits) const { typedef CGAL::Quadratic_program_solution LP_solution; LP_solution sol = compute_voronoi_face_and_tangent_subspace_LP_problem( - points_dim, center_vh, P, Q, tsb, tr_traits); + points_dim, P, Q, tsb, tr_traits); - boost::optional ret; + boost::optional ret; if (sol.status() == CGAL::QP_OPTIMAL) { std::vector p; @@ -2901,7 +3111,7 @@ next_face: { p.push_back(to_double(*it_v)); } - ret = m_k.construct_point_d_object()(points_dim, p.begin(), p.end()); + ret = tr_traits.construct_point_d_object()(points_dim, p.begin(), p.end()); } else { From 0a0714aa44492fd22d195946eeeed10f4b4e5e4f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 18:49:11 +0200 Subject: [PATCH 224/269] One priority queue per dimension --- Tangential_complex/include/CGAL/Tangential_complex.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6b2a27e3769..59ac7edce50 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -780,7 +780,10 @@ public: std::vector, std::greater > AATC_pq; - AATC_pq pqueue; + // One queue per dimension, from intrinsic dim (index = 0) to + // ambiant dim (index = ambiant - intrinsic dim) + std::vector pqueues; + pqueues.resize(m_ambient_dim - m_intrinsic_dimension + 1); // For each triangulation for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) @@ -796,6 +799,8 @@ public: if (*s.rbegin() == std::numeric_limits::max()) continue; + int simplex_dim = s.size(); + // P: points whose star does not contain "s" std::vector P; is_simplex_consistent(idx, s, std::back_inserter(P), true); @@ -826,8 +831,8 @@ public: Vector thickening_v = k_diff_points(inters_global, m_points[p]); FT squared_alpha = k_sqlen(thickening_v); - pqueue.push(Simplex_and_alpha( - p, full_simplex, squared_alpha, thickening_v)); + pqueues[simplex_dim - m_intrinsic_dimension].push( + Simplex_and_alpha(p, full_simplex, squared_alpha, thickening_v)); } } } From a3bd61fa73b2a8321985811b3bc7f6eab5fb9c53 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 18:50:43 +0200 Subject: [PATCH 225/269] m_intrinsic_dimension => m_intrinsic_dim --- .../include/CGAL/Tangential_complex.h | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 59ac7edce50..a33f9bff46f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -278,7 +278,7 @@ public: const Kernel &k = Kernel() ) : m_k(k), - m_intrinsic_dimension(intrinsic_dimension), + m_intrinsic_dim(intrinsic_dimension), m_half_sparsity(0.5*sparsity), m_sq_half_sparsity(m_half_sparsity*m_half_sparsity), m_ambient_dim(k.point_dimension_d_object()(*first)), @@ -314,7 +314,7 @@ public: int intrinsic_dimension() const { - return m_intrinsic_dimension; + return m_intrinsic_dim; } int ambient_dimension() const { @@ -415,7 +415,7 @@ public: std::vector sum_eigen_values(m_ambient_dim, FT(0)); std::size_t num_points_for_pca = - std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dimension); + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim); typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -783,7 +783,7 @@ public: // One queue per dimension, from intrinsic dim (index = 0) to // ambiant dim (index = ambiant - intrinsic dim) std::vector pqueues; - pqueues.resize(m_ambient_dim - m_intrinsic_dimension + 1); + pqueues.resize(m_ambient_dim - m_intrinsic_dim + 1); // For each triangulation for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) @@ -831,7 +831,7 @@ public: Vector thickening_v = k_diff_points(inters_global, m_points[p]); FT squared_alpha = k_sqlen(thickening_v); - pqueues[simplex_dim - m_intrinsic_dimension].push( + pqueues[simplex_dim - m_intrinsic_dim].push( Simplex_and_alpha(p, full_simplex, squared_alpha, thickening_v)); } } @@ -883,7 +883,7 @@ public: << std::endl; } - if (m_intrinsic_dimension < 1 || m_intrinsic_dimension > 3) + if (m_intrinsic_dim < 1 || m_intrinsic_dim > 3) { std::cerr << "Error: export_to_off => intrinsic dimension should be " "between 1 and 3." @@ -1007,9 +1007,9 @@ public: cit != ambient_dt.finite_full_cells_end() ; ++cit ) { int lowest_dim = - (check_for_any_dimension_simplices ? 1 : m_intrinsic_dimension); + (check_for_any_dimension_simplices ? 1 : m_intrinsic_dim); int highest_dim = - (check_for_any_dimension_simplices ? m_ambient_dim : m_intrinsic_dimension); + (check_for_any_dimension_simplices ? m_ambient_dim : m_intrinsic_dim); for (int dim = lowest_dim ; dim <= highest_dim ; ++dim) { @@ -1609,7 +1609,7 @@ next_face: typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); Tangent_space_basis ts; - ts.reserve(m_intrinsic_dimension); + ts.reserve(m_intrinsic_dim); ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); @@ -1621,13 +1621,13 @@ next_face: // CJTODO: this is only for torus_d Tangent_space_basis ts(p); - ts.reserve(m_intrinsic_dimension); - for (int dim = 0 ; dim < m_intrinsic_dimension ; ++dim) + ts.reserve(m_intrinsic_dim); + for (int dim = 0 ; dim < m_intrinsic_dim ; ++dim) { std::vector tt(m_ambient_dim, 0.); tt[2*dim] = -p[2*dim + 1]; tt[2*dim + 1] = p[2*dim]; - Vector t(2*m_intrinsic_dimension, tt.begin(), tt.end()); + Vector t(2*m_intrinsic_dim, tt.begin(), tt.end()); ts.push_back(t); } @@ -1640,7 +1640,7 @@ next_face: #else unsigned int num_points_for_pca = static_cast( - std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dimension)); + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); // Kernel functors typename Kernel::Construct_vector_d constr_vec = @@ -1699,7 +1699,7 @@ next_face: // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues for (int j = m_ambient_dim - 1 ; - j >= m_ambient_dim - m_intrinsic_dimension ; + j >= m_ambient_dim - m_intrinsic_dim ; --j) { if (normalize_basis) @@ -1721,7 +1721,7 @@ next_face: if (p_orth_space_basis) { p_orth_space_basis->origin() = p; - for (int j = m_ambient_dim - m_intrinsic_dimension - 1 ; + for (int j = m_ambient_dim - m_intrinsic_dim - 1 ; j >= 0 ; --j) { @@ -1743,7 +1743,7 @@ next_face: } #if defined(CGAL_ALPHA_TC) && defined(CGAL_USE_A_FIXED_ALPHA) // Add the orthogonal vectors as "thickening vectors" - for (int j = m_ambient_dim - m_intrinsic_dimension - 1 ; + for (int j = m_ambient_dim - m_intrinsic_dim - 1 ; j >= 0 ; --j) { @@ -1774,7 +1774,7 @@ next_face: //Vector t1(12., 15., 65.); //Vector t2(32., 5., 85.); //Tangent_space_basis ts; - //ts.reserve(m_intrinsic_dimension); + //ts.reserve(m_intrinsic_dim); //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); //ts = compute_gram_schmidt_basis(ts, m_k); @@ -1838,7 +1838,7 @@ next_face: tr_traits.compute_coordinate_d_object(); Point global_point = tsb.origin(); - for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + for (int i = 0 ; i < m_intrinsic_dim ; ++i) global_point = k_transl(global_point, k_scaled_vec(tsb[i], coord(p, i))); @@ -1848,7 +1848,7 @@ next_face: { global_point = k_transl( global_point, - k_scaled_vec(tv[i].vec, coord(p, m_intrinsic_dimension + i))); + k_scaled_vec(tv[i].vec, coord(p, m_intrinsic_dim + i))); } #endif return global_point; @@ -1868,7 +1868,7 @@ next_face: std::vector coords; // Ambiant-space coords of the projected point coords.reserve(tsb.dimension()); - for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) + for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { // Local coords are given by the inner product with the vectors of tsb FT coord = inner_pdct(v, tsb[i]); @@ -1920,7 +1920,7 @@ next_face: // Ambiant-space coords of the projected point std::vector p_proj(ccci(tsb.origin()), ccci(tsb.origin(), 0)); coords.reserve(tsb.dimension()); - for (std::size_t i = 0 ; i < m_intrinsic_dimension ; ++i) + for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { // Local coords are given by the inner product with the vectors of tsb FT c = inner_pdct(v, tsb[i]); @@ -2206,7 +2206,7 @@ next_face: CGAL::Random_points_in_ball_d tr_point_in_ball_generator( - m_intrinsic_dimension, + m_intrinsic_dim, m_random_generator.get_double(0., m_half_sparsity)); Tr_point local_random_transl = @@ -2214,7 +2214,7 @@ next_face: *tr_point_in_ball_generator++, 0); Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim); const Tangent_space_basis &tsb = m_tangent_spaces[point_idx]; - for (int i = 0 ; i < m_intrinsic_dimension ; ++i) + for (int i = 0 ; i < m_intrinsic_dim ; ++i) { global_transl = k_transl( global_transl, @@ -2386,7 +2386,7 @@ next_face: KNS_range kns_range = m_points_ds.query_ANN( global_center, - CGAL_TC_NUMBER_OF_PERTURBED_POINTS(m_intrinsic_dimension)); + CGAL_TC_NUMBER_OF_PERTURBED_POINTS(m_intrinsic_dim)); std::vector neighbors; for (KNS_iterator nn_it = kns_range.begin() ; nn_it != kns_range.end() ; @@ -2451,10 +2451,10 @@ next_face: return os; } - // If m_intrinsic_dimension = 1, we output each point two times + // If m_intrinsic_dim = 1, we output each point two times // to be able to export each segment as a flat triangle with 3 different // indices (otherwise, Meshlab detects degenerated simplices) - const int N = (m_intrinsic_dimension == 1 ? 2 : 1); + const int N = (m_intrinsic_dim == 1 ? 2 : 1); // Kernel functors typename Kernel::Compute_coordinate_d coord = @@ -2723,7 +2723,7 @@ next_face: // CJTODO TEMP DEBUG // If co-intrinsic dimension = 1, let's compare normals - /*if (m_ambient_dim - m_intrinsic_dimension == 1) + /*if (m_ambient_dim - m_intrinsic_dim == 1) { typename Kernel::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); @@ -2748,7 +2748,7 @@ next_face: << inconsistent_simplex.size() - 1 << " simplex\n"; // If co-intrinsic dimension = 1, let's compare normals - /*if (m_ambient_dim - m_intrinsic_dimension == 1) + /*if (m_ambient_dim - m_intrinsic_dim == 1) { std::cerr << "(dot product between normals = "; std::set::const_iterator it_v = @@ -2908,7 +2908,7 @@ next_face: break; } // CJTODO TEMP - /*else if (m_ambient_dim - m_intrinsic_dimension == 1) + /*else if (m_ambient_dim - m_intrinsic_dim == 1) { typename Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); @@ -3269,7 +3269,7 @@ next_face: std::set > const *p_simpl_to_color_in_blue = NULL) const { - // If m_intrinsic_dimension = 1, each point is output two times + // If m_intrinsic_dim = 1, each point is output two times // (see export_vertices_to_off) num_OFF_simplices = 0; std::size_t num_maximal_simplices = 0; @@ -3285,7 +3285,7 @@ next_face: Triangulation const& tr = it_tr->tr(); Tr_vertex_handle center_vh = it_tr->center_vertex(); - if (&tr == NULL || tr.current_dimension() < m_intrinsic_dimension) + if (&tr == NULL || tr.current_dimension() < m_intrinsic_dim) continue; // Color for this star @@ -3343,11 +3343,11 @@ next_face: } } - // If m_intrinsic_dimension = 1, each point is output two times, + // If m_intrinsic_dim = 1, each point is output two times, // so we need to multiply each index by 2 // And if only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) - if (m_intrinsic_dimension == 1) + if (m_intrinsic_dim == 1) { std::set tmp_c; std::set::iterator it = c.begin(); @@ -3408,7 +3408,7 @@ next_face: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != (m_intrinsic_dimension == 1 ? 2*idx : idx) + if (*c.begin() != (m_intrinsic_dim == 1 ? 2*idx : idx) && color_simplex == -1) continue; @@ -3474,7 +3474,7 @@ public: typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; - // If m_intrinsic_dimension = 1, each point is output two times + // If m_intrinsic_dim = 1, each point is output two times // (see export_vertices_to_off) num_OFF_simplices = 0; std::size_t num_maximal_simplices = 0; @@ -3521,14 +3521,14 @@ public: std::size_t num_vertices = c.size(); // Do not export smaller dimension simplices - if (num_vertices < m_intrinsic_dimension + 1) + if (num_vertices < m_intrinsic_dim + 1) continue; - // If m_intrinsic_dimension = 1, each point is output two times, + // If m_intrinsic_dim = 1, each point is output two times, // so we need to multiply each index by 2 // And if only 2 vertices, add a third one (each vertex is duplicated in // the file when m_intrinsic dim = 2) - if (m_intrinsic_dimension == 1) + if (m_intrinsic_dim == 1) { std::set tmp_c; std::set::iterator it = c.begin(); @@ -3617,7 +3617,7 @@ public: { std::ofstream csv_consistent("output/correlation_consistent.csv"); // CJTODO TEMP std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO TEMP - if (m_intrinsic_dimension < 3) + if (m_intrinsic_dim < 3) { std::cerr << std::endl << "==========================================================" << std::endl @@ -3684,7 +3684,7 @@ public: private: const Kernel m_k; - const int m_intrinsic_dimension; + const int m_intrinsic_dim; const double m_half_sparsity; const double m_sq_half_sparsity; const int m_ambient_dim; From 95fc8dfdb8021c426606572c4596772ef8b10e36 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 23 Jun 2015 19:38:57 +0200 Subject: [PATCH 226/269] Added/renamed typedefs --- .../include/CGAL/Tangential_complex.h | 151 +++++++++--------- 1 file changed, 79 insertions(+), 72 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index a33f9bff46f..c2e14adaa51 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -213,13 +213,28 @@ class Tangential_complex Tr_vertex_handle m_center_vertex; }; +public: + typedef typename std::vector TS_container; + typedef typename std::vector OS_container; +private: + typedef typename std::vector Tr_container; + typedef typename std::vector Vectors; + + // An Incident_simplex is the list of the vertex indices + // except the center vertex + typedef std::set Incident_simplex; + typedef std::set Indexed_simplex; + typedef std::vector Star; + typedef std::vector Stars_container; + + // For the priority queues of solve_inconsistencies_using_adaptive_alpha_TC class Simplex_and_alpha { public: Simplex_and_alpha() {} Simplex_and_alpha( std::size_t center_point_index, - std::set const& simplex, // including "center_point_index" + Incident_simplex const& simplex, // NOT including "center_point_index" FT squared_alpha, Vector const& thickening_vector) : m_center_point_index(center_point_index), @@ -236,24 +251,11 @@ class Tangential_complex private: std::size_t m_center_point_index; // P - std::set m_simplex; // Missing simplex (includes P) + Incident_simplex m_simplex; // Missing simplex (does NOT includes P) FT m_squared_alpha; Vector m_thickening_vector; // (P, Cq) }; -public: - typedef typename std::vector TS_container; - typedef typename std::vector OS_container; -private: - typedef typename std::vector Tr_container; - typedef typename std::vector Vectors; - - // An Incident_simplex is the list of the vertex indices - // except the center vertex - typedef std::set Incident_simplex; - typedef std::vector Star; - typedef std::vector Stars_container; - // For transform_iterator static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) { @@ -658,7 +660,7 @@ public: if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; c.insert(idx); // Add the missing index if (!is_simplex_consistent(c)) @@ -707,7 +709,7 @@ public: == std::numeric_limits::max()) continue; - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); // Add the missing center vertex @@ -755,6 +757,7 @@ public: << std::endl; } + void solve_inconsistencies_using_adaptive_alpha_TC() { #ifdef CGAL_TC_PROFILING @@ -774,15 +777,16 @@ public: m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); //------------------------------------------------------------------------- - //1. Fill priority queue + // 1. Fill priority queues //------------------------------------------------------------------------- typedef std::priority_queue, std::greater > AATC_pq; + typedef std::vector PQueues; // One queue per dimension, from intrinsic dim (index = 0) to // ambiant dim (index = ambiant - intrinsic dim) - std::vector pqueues; + PQueues pqueues; pqueues.resize(m_ambient_dim - m_intrinsic_dim + 1); // For each triangulation @@ -799,7 +803,7 @@ public: if (*s.rbegin() == std::numeric_limits::max()) continue; - int simplex_dim = s.size(); + int simplex_dim = static_cast(s.size()); // P: points whose star does not contain "s" std::vector P; @@ -808,13 +812,13 @@ public: if (!P.empty()) { Triangulation const& q_tr = m_triangulations[idx].tr(); - std::set full_simplex = s; + Indexed_simplex full_simplex = s; full_simplex.insert(idx); for (std::vector::const_iterator it_p = P.begin(), it_p_end = P.end() ; it_p != it_p_end ; ++it_p) { // star(p) does not contain "s" - std::size_t const& p = *it_p; + std::size_t p = *it_p; Tr_bare_point intersection = *compute_aff_of_voronoi_face_and_tangent_subspace_intersection( @@ -831,8 +835,11 @@ public: Vector thickening_v = k_diff_points(inters_global, m_points[p]); FT squared_alpha = k_sqlen(thickening_v); + // We insert full_simplex \ p + Incident_simplex is = full_simplex; + is.erase(p); pqueues[simplex_dim - m_intrinsic_dim].push( - Simplex_and_alpha(p, full_simplex, squared_alpha, thickening_v)); + Simplex_and_alpha(p, is, squared_alpha, thickening_v)); } } } @@ -848,9 +855,9 @@ public: std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, - std::set > const *p_simpl_to_color_in_red = NULL, - std::set > const *p_simpl_to_color_in_green = NULL, - std::set > const *p_simpl_to_color_in_blue = NULL) + std::set const *p_simpl_to_color_in_red = NULL, + std::set const *p_simpl_to_color_in_green = NULL, + std::set const *p_simpl_to_color_in_blue = NULL) const { return export_to_off( @@ -860,9 +867,9 @@ public: std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, - std::set > const *p_simpl_to_color_in_red = NULL, - std::set > const *p_simpl_to_color_in_green = NULL, - std::set > const *p_simpl_to_color_in_blue = NULL, + std::set const *p_simpl_to_color_in_red = NULL, + std::set const *p_simpl_to_color_in_green = NULL, + std::set const *p_simpl_to_color_in_blue = NULL, const Simplicial_complex *p_complex = NULL) const { if (m_points.empty()) @@ -945,7 +952,7 @@ public: if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; c.insert(idx); // Add the missing index sc.add_simplex(c); @@ -970,7 +977,7 @@ public: bool check_if_all_simplices_are_in_the_ambient_delaunay( const Simplicial_complex *p_complex = NULL, bool check_for_any_dimension_simplices = true, - std::set > * incorrect_simplices = NULL) const + std::set * incorrect_simplices = NULL) const { typedef Simplicial_complex::Simplex Simplex; typedef Simplicial_complex::Simplex_range Simplex_range; @@ -1975,7 +1982,7 @@ next_face: // A simplex here is a local tri's full cell handle bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) const { - std::set c; + Indexed_simplex c; for (int i = 0 ; i < cur_dim + 1 ; ++i) { std::size_t data = fch->vertex(i)->data(); @@ -2042,10 +2049,10 @@ next_face: // A simplex here is a list of point indices // CJTODO: improve it like the other "is_simplex_consistent" below - bool is_simplex_consistent(std::set const& simplex) const + bool is_simplex_consistent(Indexed_simplex const& simplex) const { // Check if the simplex is in the stars of all its vertices - std::set::const_iterator it_point_idx = simplex.begin(); + Indexed_simplex::const_iterator it_point_idx = simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p // and we check if "simplex" is among them for ( ; it_point_idx != simplex.end() ; ++it_point_idx) @@ -2081,7 +2088,7 @@ next_face: OutputIterator points_whose_star_does_not_contain_s, bool check_also_in_non_maximal_faces = false) const { - std::set full_simplex = s; + Indexed_simplex full_simplex = s; full_simplex.insert(center_point); // Check if the simplex is in the stars of all its vertices @@ -2261,7 +2268,7 @@ next_face: if (*incident_simplex.rbegin() == std::numeric_limits::max()) continue; - std::set c = incident_simplex; + Indexed_simplex c = incident_simplex; c.insert(tr_index); // Add the missing index //***************************************************************************** @@ -2273,7 +2280,7 @@ next_face: { is_inconsistent = true; - for (std::set::const_iterator it = c.begin(); + for (Indexed_simplex::const_iterator it = c.begin(); it != c.end() ; ++it) { perturb(*it); @@ -2422,7 +2429,7 @@ next_face: perturb(tr_index); else { - std::set::const_iterator it_idx = c.begin(); + Indexed_simplex::const_iterator it_idx = c.begin(); std::advance(it_idx, rnd - 1); perturb(*it_idx); } @@ -2502,15 +2509,15 @@ next_face: void insert_higher_dim_simplex_into_star( std::size_t index, - const std::set &simplex) + const Indexed_simplex &simplex) { Incident_simplex incident_simplex = simplex; incident_simplex.erase(index); // Remove the center index Star &star = m_stars[index]; - std::set::const_iterator it_point_idx = simplex.begin(); - std::set::const_iterator it_point_idx_end = simplex.end(); + Indexed_simplex::const_iterator it_point_idx = simplex.begin(); + Indexed_simplex::const_iterator it_point_idx_end = simplex.end(); for ( ; it_point_idx != it_point_idx_end ; ++it_point_idx) { // Skip center index @@ -2533,12 +2540,12 @@ next_face: // "inconsistent_simplex" must be in star(p) but not in star(q) void solve_inconsistency_by_adding_higher_dimensional_simplices( std::size_t p_idx, std::size_t q_idx, - const std::set &inconsistent_simplex) + const Indexed_simplex &inconsistent_simplex) { CGAL_assertion_code( - std::set inc_s_minus_p = inconsistent_simplex; + Indexed_simplex inc_s_minus_p = inconsistent_simplex; inc_s_minus_p.erase(p_idx); - std::set inc_s_minus_q = inconsistent_simplex; + Indexed_simplex inc_s_minus_q = inconsistent_simplex; inc_s_minus_q.erase(q_idx); ); CGAL_assertion(std::find(m_stars[p_idx].begin(), m_stars[p_idx].end(), @@ -2582,9 +2589,9 @@ next_face: // other threads are perturbing the positions const Point pt_p = compute_perturbed_point(p_idx); - std::set::const_iterator it_point_idx = + Indexed_simplex::const_iterator it_point_idx = inconsistent_simplex.begin(); - std::set::const_iterator it_point_idx_end = + Indexed_simplex::const_iterator it_point_idx_end = inconsistent_simplex.end(); // For each point of the simplex, we reproject it onto the tangent // space. Could be optimized since it's already been computed before. @@ -2751,7 +2758,7 @@ next_face: /*if (m_ambient_dim - m_intrinsic_dim == 1) { std::cerr << "(dot product between normals = "; - std::set::const_iterator it_v = + Indexed_simplex::const_iterator it_v = inconsistent_simplex.begin(); std::size_t i1 = *it_v; ++it_v; @@ -2855,7 +2862,7 @@ next_face: //------------------------------------------------------------------------- //7. Create a k+1-simplex (inconsistent_simplex, ti) //------------------------------------------------------------------------- - std::set new_simplex = inconsistent_simplex; + Indexed_simplex new_simplex = inconsistent_simplex; new_simplex.insert(inside_point_idx); it_point_idx = new_simplex.begin(); @@ -2874,7 +2881,7 @@ next_face: // Returns true if some inconsistencies were found. // Precondition: incident_simplex is in the star of m_points[tr_index] bool check_and_solve_inconsistencies_by_adding_higher_dim_simplices( - std::size_t tr_index, const std::set &incident_simplex) + std::size_t tr_index, const Incident_simplex &incident_simplex) { bool inconsistencies_found = false; @@ -2883,11 +2890,11 @@ next_face: == std::numeric_limits::max()) return false; - std::set simplex = incident_simplex; + Indexed_simplex simplex = incident_simplex; simplex.insert(tr_index); // Check if the simplex is in the stars of all its vertices - std::set::const_iterator it_point_idx = incident_simplex.begin(); + Incident_simplex::const_iterator it_point_idx = incident_simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p // and we check if "simplex" is among them for ( ; it_point_idx != incident_simplex.end() ; ++it_point_idx) @@ -3264,9 +3271,9 @@ next_face: std::ostream &export_simplices_to_off( std::ostream & os, std::size_t &num_OFF_simplices, bool color_inconsistencies = false, - std::set > const *p_simpl_to_color_in_red = NULL, - std::set > const *p_simpl_to_color_in_green = NULL, - std::set > const *p_simpl_to_color_in_blue = NULL) + std::set const *p_simpl_to_color_in_red = NULL, + std::set const *p_simpl_to_color_in_green = NULL, + std::set const *p_simpl_to_color_in_blue = NULL) const { // If m_intrinsic_dim = 1, each point is output two times @@ -3294,8 +3301,8 @@ next_face: color << 128 << " " << 128 << " " << 128; // Gather the triangles here, with an int telling its color - typedef std::vector, int> > - Star_using_triangles; + typedef std::vector > + Star_using_triangles; Star_using_triangles star_using_triangles; // For each cell of the star @@ -3303,7 +3310,7 @@ next_face: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; c.insert(idx); std::size_t num_vertices = c.size(); ++num_maximal_simplices; @@ -3349,8 +3356,8 @@ next_face: // the file when m_intrinsic dim = 2) if (m_intrinsic_dim == 1) { - std::set tmp_c; - std::set::iterator it = c.begin(); + Indexed_simplex tmp_c; + Indexed_simplex::iterator it = c.begin(); for ( ; it != c.end() ; ++it) tmp_c.insert(*it * 2); if (num_vertices == 2) @@ -3370,8 +3377,8 @@ next_face: std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); do { - std::set triangle; - std::set::iterator it = c.begin(); + Indexed_simplex triangle; + Indexed_simplex::iterator it = c.begin(); for (int i = 0; it != c.end() ; ++i, ++it) { if (booleans[i]) @@ -3395,12 +3402,12 @@ next_face: == std::numeric_limits::max()) continue; - const std::set &c = it_simplex->first; + const Indexed_simplex &c = it_simplex->first; int color_simplex = it_simplex->second; std::stringstream sstr_c; - std::set::const_iterator it_point_idx = c.begin(); + Indexed_simplex::const_iterator it_point_idx = c.begin(); for ( ; it_point_idx != c.end() ; ++it_point_idx) { sstr_c << *it_point_idx << " "; @@ -3466,9 +3473,9 @@ public: std::ostream &export_simplices_to_off( const Simplicial_complex &complex, std::ostream & os, std::size_t &num_OFF_simplices, - std::set > const *p_simpl_to_color_in_red = NULL, - std::set > const *p_simpl_to_color_in_green = NULL, - std::set > const *p_simpl_to_color_in_blue = NULL) + std::set const *p_simpl_to_color_in_red = NULL, + std::set const *p_simpl_to_color_in_green = NULL, + std::set const *p_simpl_to_color_in_blue = NULL) const { typedef Simplicial_complex::Simplex Simplex; @@ -3530,8 +3537,8 @@ public: // the file when m_intrinsic dim = 2) if (m_intrinsic_dim == 1) { - std::set tmp_c; - std::set::iterator it = c.begin(); + Indexed_simplex tmp_c; + Indexed_simplex::iterator it = c.begin(); for ( ; it != c.end() ; ++it) tmp_c.insert(*it * 2); if (num_vertices == 2) @@ -3551,8 +3558,8 @@ public: std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); do { - std::set triangle; - std::set::iterator it = c.begin(); + Indexed_simplex triangle; + Indexed_simplex::iterator it = c.begin(); for (int i = 0; it != c.end() ; ++i, ++it) { if (booleans[i]) @@ -3573,7 +3580,7 @@ public: continue; os << 3 << " "; - std::set::const_iterator it_point_idx = it_tri->begin(); + Indexed_simplex::const_iterator it_point_idx = it_tri->begin(); for ( ; it_point_idx != it_tri->end() ; ++it_point_idx) { os << *it_point_idx << " "; @@ -3643,7 +3650,7 @@ public: if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) continue; - std::set c = *it_inc_simplex; + Indexed_simplex c = *it_inc_simplex; c.insert(idx); // Add the missing index double fatness = compute_simplex_fatness(c); From fa3b2d9bea15726247b3214ef25fa41f00b0fa08 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 25 Jun 2015 11:36:45 +0200 Subject: [PATCH 227/269] Bugfix in RTd: in dimension 2, the points were never hidden --- .../include/CGAL/Regular_triangulation.h | 87 ++++++++++--------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 1e591d6101d..a70cc908131 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -112,7 +112,6 @@ public: using Base::rotate_rotor; using Base::infinite_vertex; using Base::insert_in_hole; - using Base::insert_outside_convex_hull_1; using Base::is_infinite; using Base::locate; using Base::points_begin; @@ -270,7 +269,9 @@ public: CGAL_assertion( Vertex_handle() != hint ); return insert(p, hint->full_cell()); } - + + Vertex_handle insert_outside_convex_hull_1( + const Weighted_point & p, Full_cell_handle s); Vertex_handle insert_outside_affine_hull(const Weighted_point &); Vertex_handle insert_in_conflicting_cell( const Weighted_point &, const Full_cell_handle, @@ -827,7 +828,7 @@ Regular_triangulation typename RTTraits::Point_weight_d pw = geom_traits().point_weight_d_object(); - if (pw(p) == pw(v->point())) + if (pw(p) = pw(v->point())) return v; // If dim == 0 and the new point has a bigger weight, // we replace the point @@ -843,22 +844,49 @@ Regular_triangulation // !NO break here! } default: - if( 1 == current_dimension() ) - { - if( Base::OUTSIDE_CONVEX_HULL == lt ) - { - return insert_outside_convex_hull_1(p, s); - } - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - return v; - } + if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) + return insert_outside_convex_hull_1(p, s); else return insert_in_conflicting_cell(p, s); break; } } +// NOT DOCUMENTED... +template < class RTTraits, class TDS > +typename Regular_triangulation::Vertex_handle +Regular_triangulation +::insert_outside_convex_hull_1(const Weighted_point & p, Full_cell_handle s) +{ + // This is a special case for dimension 1, because in that case, the right + // infinite full_cell is not correctly oriented... (sice its first vertex is the + // infinite one... + + bool in_conflict = is_in_conflict(p, s); + + // If p is not in conflict with s, then p is hidden + // => we don't insert it + if (!in_conflict) + { + m_hidden_points.push_back(p); + return Vertex_handle(); + } + else + { + CGAL_precondition( is_infinite(s) ); + CGAL_precondition( 1 == current_dimension() ); + int inf_v_index = s->index(infinite_vertex()); + bool swap = (0 == s->neighbor(inf_v_index)->index(s)); + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + if( swap ) + { + s->swap_vertices(0, 1); + } + return v; + } +} + template< typename RTTraits, typename TDS > typename Regular_triangulation::Vertex_handle Regular_triangulation @@ -919,21 +947,15 @@ Regular_triangulation } default: { - if( 1 == current_dimension() ) + if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) { if (s->has_vertex(star_center)) - { - if( Base::OUTSIDE_CONVEX_HULL == lt ) - { return insert_outside_convex_hull_1(p, s); - } - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - return v; - } } else + { return insert_in_conflicting_cell(p, s, star_center); + } break; } } @@ -950,22 +972,7 @@ Regular_triangulation { typedef std::vector Full_cell_h_vector; - bool in_conflict; - if( current_dimension() < maximal_dimension() ) - { - Conflict_pred_in_subspace c( - *this, p, - coaffine_orientation_predicate(), - power_test_in_flat_predicate()); - in_conflict = c(s); - } - else - { - Orientation_d ori = geom_traits().orientation_d_object(); - Power_test_d side = geom_traits().power_test_d_object(); - Conflict_pred_in_fullspace c(*this, p, ori, side); - in_conflict = c(s); - } + bool in_conflict = is_in_conflict(p, s); // If p is not in conflict with s, then p is hidden // => we don't insert it @@ -1069,7 +1076,7 @@ bool Regular_triangulation ::is_in_conflict(const Weighted_point & p, Full_cell_const_handle s) const { - CGAL_precondition( 2 <= current_dimension() ); + CGAL_precondition( 1 <= current_dimension() ); if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( @@ -1093,7 +1100,7 @@ typename Regular_triangulation::Facet Regular_triangulation ::compute_conflict_zone(const Weighted_point & p, const Full_cell_handle s, OutputIterator out) const { - CGAL_precondition( 2 <= current_dimension() ); + CGAL_precondition( 1 <= current_dimension() ); if( current_dimension() < maximal_dimension() ) { Conflict_pred_in_subspace c( From aa81039e071bb587593c5f6c7ad3f9c2a096b84e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 25 Jun 2015 20:35:50 +0200 Subject: [PATCH 228/269] Bugfix: == --- Triangulation/include/CGAL/Regular_triangulation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index a70cc908131..02efd84268c 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -828,7 +828,7 @@ Regular_triangulation typename RTTraits::Point_weight_d pw = geom_traits().point_weight_d_object(); - if (pw(p) = pw(v->point())) + if (pw(p) == pw(v->point())) return v; // If dim == 0 and the new point has a bigger weight, // we replace the point From 99ce450f718ddcdd35d42361a438e2d789b9c5fd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 25 Jun 2015 20:37:22 +0200 Subject: [PATCH 229/269] First version of alpha TC Where the tangent spaces are progressively thickened to try to get rid of inconsistencies --- .../Tangential_complex/benchmark_script.txt | 73 ++- .../Tangential_complex/benchmark_tc.cpp | 17 +- .../include/CGAL/Tangential_complex.h | 504 +++++++++++++----- .../include/CGAL/Tangential_complex/config.h | 3 +- .../CGAL/Tangential_complex/utilities.h | 128 ++++- .../test/Tangential_complex/test_utilities.h | 100 +--- 6 files changed, 571 insertions(+), 254 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index fa30a289ffd..26ad4eaead0 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -2,29 +2,62 @@ # Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- +#---------------------------------------------------------------- Adaptive alpha TC tests ------------------------------------------------------------------------ +#generate_sphere_d 1 1 - 50 2 1 0.005 N Y N 3 1 #OK +#generate_torus_d N - - 15 2 1 0.05 N Y N 10 1 +#generate_sphere_d 0.302 3 - 50 3 2 0.005 N Y N 60 1 #OK +#generate_sphere_d 0.302 2 - 300 2 1 0.005 N Y N 60 1 +#generate_torus_3D 2 1 N 200 3 2 0.05 N Y N 600 1 #OK => tetraedra only +#data/fandisk.txt - - - 0 3 2 0.005 Y Y N 5 1 +generate_torus_d N 1 - 50 4 2 0.05 N Y N 3 1 #NOT OK: various errors +#generate_torus_d Y 1 - 2500 4 2 0.05 N Y N 3 1 #NOT OK +#generate_torus_d N - - 30 6 3 0.05 N Y N 300 1 +#generate_moment_curve 0 1 - 10 3 1 0.005 N Y N 60 1 +#generate_two_spheres_d 3 4 - 500 3 2 0.05 N Y N 10 1 #OK +#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N Y N 60 1 + #---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ -#generate_sphere_d 0.302 - - 70 2 1 0.005 N N Y 60 1 -#generate_sphere_d 0.5 - - 70 2 1 0.005 N N Y 60 1 -#generate_sphere_d 3 2 - 1000 3 2 0.05 N N Y 60 1 -#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N Y 60 1 -#generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N Y 60 1 -#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever -#generate_torus_3D 2 1 Y 150 3 2 0.05 Y N N 600 1 -#generate_torus_d N - - 30 2 1 0.01 Y N N 30 1 -#generate_torus_d Y - - 70 4 2 0.05 Y N N 30 1 -#generate_torus_d N - - 200 4 2 0.05 Y N N 30 1 -#generate_torus_d N - - 20000 4 2 0.65 Y N N 30 1 -#generate_torus_d N - - 10000 6 3 0.05 Y N N 300 1 -#generate_torus_d N - - 50000 6 3 0.05 Y N N 7000 1 -#generate_torus_d N - - 100000 6 3 0.05 Y N N 7000 1 -#generate_torus_d N - - 1000000 6 3 0.3 Y N N 3000 1 -#generate_torus_d Y - - 10000 8 4 0.05 Y N N 3600 1 +#generate_sphere_d 0.302 - - 70 2 1 0.005 N N N 60 1 +#generate_sphere_d 0.304 0 - 100 3 2 0.05 N N N 60 1 +#generate_sphere_d 3 0 - 100 4 3 0.05 N N N 60 1 +#generate_sphere_d 3 0 - 1000 5 4 0.05 N N N 60 1 +#generate_two_spheres_d 3 4 - 1000 3 2 0.05 N N N 10 1 +#generate_two_spheres_d 3 10 - 1000 4 3 0.05 N N N 10 1 +#generate_two_spheres_d 3 10 - 2000 5 4 0.05 N N N 10 1 +#generate_3sphere_and_circle_d 3 - - 100000 5 3 0.05 N N N 7000 1 +#generate_plane - - - 100 4 3 0.005 N N N 3000 1 +#generate_plane - - - 10 5 4 0.005 N N N 3000 1 +#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N N 60 1 +#generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N N 60 1 +#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N N N 60 1 #Takes forever +#generate_torus_3D 2 1 Y 150 3 2 0.05 N N N 600 1 +#generate_torus_3D 2 1 N 100000 3 2 0.55 N N N 600 1 +#generate_torus_d N - - 18 2 1 0.01 N N N 30 1 +#generate_torus_d N - - 50000 2 1 0.7 N N N 30 1 +#generate_torus_d Y - - 2 2 1 0 N N N 30 1 +#generate_torus_d Y - - 15 4 2 0.05 N N N 30 1 +#generate_torus_d N 0 - 150 4 2 0.05 N N N 10 1 +#generate_torus_d N - - 20000 4 2 1.0 N N N 30 1 +#generate_torus_d Y 0 - 5000 6 3 0.05 N N N 300 1 +#generate_torus_d N - - 20000 6 3 0.05 N N N 60 1 +#generate_torus_d N - - 100000 6 3 0.05 N N N 3000 1 +#generate_torus_d N - - 1000000 6 3 0.3 N N N 3000 1 +#generate_torus_d Y - - 1000 8 4 0.05 N N N 60 1 +#data/SO3_10000.txt - - - 0 9 3 0.1 N N N 60 1 #---------------------------------------------------------- Spatial search benchmarking -------------------------------------------------------------- -generate_torus_d Y - - 1000000 30 15 0 Y N N 3600 1 -data/SO3_50000.txt - - - 0 9 3 0 Y Y N 60 1 -data/Cy8.txt - - - 0 24 2 0 N Y N 60 1 -data/buddha_100kv.txt - - - 0 3 2 0 N Y N 120 1 +#generate_torus_3D 2 1 Y 10000 3 2 0 Y N N 600 1 +#data/buddha_100kv.txt - - - 0 3 2 0 N Y N 120 1 +#generate_torus_d N - - 10000 30 15 0 Y N N 3600 1 +#generate_torus_d N - - 100000 12 6 0 Y N N 3600 1 +#data/SO3_50000.txt - - - 0 9 3 0 Y N N 60 1 +#data/Cy8.txt - - - 0 24 2 0 N Y N 60 1 +#generate_sphere_d 0.5 - - 10000 2 1 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 3 2 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 4 3 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 5 4 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 6 5 0 N N Y 60 1 +#generate_sphere_d 0.5 - - 10000 7 6 0 N N Y 60 1 #---------------------------------------------------------- Very small cases for Debug mode -------------------------------------------------------------- #generate_sphere_d 4 - - 20 3 2 0.05 N Y N 60 1 diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 1545d2e20af..556208e190e 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -334,8 +334,9 @@ void make_tc(std::vector &points, } return;*/ // CJTODO TEMP =========================== - - //tc.check_if_all_simplices_are_in_the_ambient_delaunay(); + + if (ambient_dim <= 4) + tc.check_if_all_simplices_are_in_the_ambient_delaunay(); //tc.check_correlation_between_inconsistencies_and_fatness(); @@ -405,8 +406,11 @@ void make_tc(std::vector &points, //========================================================================= t.reset(); // Try to solve the remaining inconstencies - //tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); +#ifdef CGAL_ALPHA_TC tc.solve_inconsistencies_using_adaptive_alpha_TC(); +#else + tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); +#endif fix2_time = t.elapsed(); t.reset(); max_dim = tc.export_TC(complex, false); /*std::set > not_delaunay_simplices; @@ -656,8 +660,8 @@ int main() { points = generate_points_on_sphere_d( num_points, ambient_dim, - std::atof(param1.c_str()), - std::atof(param2.c_str())); + std::atof(param1.c_str()), // radius + std::atof(param2.c_str())); // radius_noise_percentage } else if (input == "generate_two_spheres_d") { @@ -688,7 +692,8 @@ int main() points = generate_points_on_torus_d( num_points, intrinsic_dim, - param1 == "Y"); + param1 == "Y", // uniform + std::atof(param2.c_str())); // radius_noise_percentage } else if (input == "generate_klein_bottle_3D") { diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index c2e14adaa51..8eb77e4866d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -70,6 +70,7 @@ //static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP //CJTODO: debug +//#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_2 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE @@ -228,9 +229,8 @@ private: typedef std::vector Stars_container; // For the priority queues of solve_inconsistencies_using_adaptive_alpha_TC - class Simplex_and_alpha + struct Simplex_and_alpha { - public: Simplex_and_alpha() {} Simplex_and_alpha( std::size_t center_point_index, @@ -249,7 +249,6 @@ private: return m_squared_alpha > other.m_squared_alpha; } - private: std::size_t m_center_point_index; // P Incident_simplex m_simplex; // Missing simplex (does NOT includes P) FT m_squared_alpha; @@ -758,6 +757,101 @@ public: } +#ifdef CGAL_ALPHA_TC +private: + + // Look in the star of point "i" for inconsistent simplices, compute + // an approximation of alpha for each one and push it into the priority + // queues. + // Returns the number of inconsistent simplices found + template + std::size_t fill_pqueues_for_alpha_tc(std::size_t i, PQueues &pqueues) + { + // Kernel/traits functors + typename Kernel::Difference_of_points_d k_diff_points = + m_k.difference_of_points_d_object(); + typename Kernel::Squared_length_d k_sqlen = + m_k.squared_length_d_object(); + typename Tr_traits::Construct_weighted_point_d constr_wp = + m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); + + std::size_t num_inconsistent_simplices = 0; + + // For each cell + Star::const_iterator it_inc_simplex = m_stars[i].begin(); + Star::const_iterator it_inc_simplex_end = m_stars[i].end(); + for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + { + Incident_simplex const& s = *it_inc_simplex; + + // Don't check infinite cells + if (*s.rbegin() == std::numeric_limits::max()) + continue; + + int simplex_dim = static_cast(s.size()); + + // P: points whose star does not contain "s" + std::vector P; + is_simplex_consistent(i, s, std::back_inserter(P), true); + + if (!P.empty()) + { + ++num_inconsistent_simplices; + + Triangulation const& q_tr = m_triangulations[i].tr(); + Indexed_simplex full_simplex = s; + full_simplex.insert(i); + for (std::vector::const_iterator it_p = P.begin(), + it_p_end = P.end() ; it_p != it_p_end ; ++it_p) + { + // star(p) does not contain "s" + std::size_t p = *it_p; + + // Compute the intersection between aff(Voronoi_cell(s)) and Tq + boost::optional intersection = + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + q_tr.current_dimension(), + project_points_and_compute_weights( + full_simplex, m_tangent_spaces[i], q_tr.geom_traits()), + m_tangent_spaces[i], + q_tr.geom_traits()); + + // CJTODO: replace with an assertion? + if (!intersection) + { + std::cerr << "ERROR fill_pqueues_for_alpha_tc: " + "aff(Voronoi_cell(s)) and Tq do not intersect.\n"; + continue; + } + + // The following computations are done in the Euclidian space + Point inters_global = unproject_point( + constr_wp(*intersection, 0), m_tangent_spaces[i], + q_tr.geom_traits()); + Vector thickening_v = k_diff_points( + inters_global, compute_perturbed_point(p)); + FT squared_alpha = k_sqlen(thickening_v); + + // We insert full_simplex \ p + Incident_simplex is = full_simplex; + is.erase(p); + pqueues[simplex_dim - m_intrinsic_dim].push( + Simplex_and_alpha(p, is, squared_alpha, thickening_v)); + + // CJTODO TEMP + /*std::cerr + << "Just inserted the simplex "; + std::copy(full_simplex.begin(), full_simplex.end(), + std::ostream_iterator(std::cerr, ", ")); + std::cerr << "into pqueue (i = " << i << ")\n";*/ + } + } + } + + return num_inconsistent_simplices; + } + +public: void solve_inconsistencies_using_adaptive_alpha_TC() { #ifdef CGAL_TC_PROFILING @@ -767,14 +861,6 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Fixing inconsistencies using adaptive alpha TC..." << std::endl; #endif - - // Kernel/traits functors - typename Kernel::Difference_of_points_d k_diff_points = - m_k.difference_of_points_d_object(); - typename Kernel::Squared_length_d k_sqlen = - m_k.squared_length_d_object(); - typename Tr_traits::Construct_weighted_point_d constr_wp = - m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); //------------------------------------------------------------------------- // 1. Fill priority queues @@ -789,69 +875,133 @@ public: PQueues pqueues; pqueues.resize(m_ambient_dim - m_intrinsic_dim + 1); + std::size_t num_inconsistent_simplices = 0; // For each triangulation - for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + num_inconsistent_simplices += fill_pqueues_for_alpha_tc(i, pqueues); + +#ifdef CGAL_TC_VERBOSE + std::cerr + << "Num inconsistent simplices found when filling the priority queues: " + << num_inconsistent_simplices << std::endl; +#endif + + //------------------------------------------------------------------------- + // 2. Thicken tangent spaces to solve inconsistencies + //------------------------------------------------------------------------- + + // While there's elements to treat in the queues + for(;;) { - // For each cell - Star::const_iterator it_inc_simplex = m_stars[idx].begin(); - Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); - for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) + // Pick the simplex with the lowest dimension and the lowest alpha + Simplex_and_alpha saa; + bool found_saa = false; + for (PQueues::iterator it_pq = pqueues.begin(), it_pq_end = pqueues.end(); + !found_saa && it_pq != it_pq_end ; ++it_pq) { - Incident_simplex const& s = *it_inc_simplex; - - // Don't check infinite cells - if (*s.rbegin() == std::numeric_limits::max()) - continue; - - int simplex_dim = static_cast(s.size()); - - // P: points whose star does not contain "s" - std::vector P; - is_simplex_consistent(idx, s, std::back_inserter(P), true); - - if (!P.empty()) + while (!found_saa && !it_pq->empty()) { - Triangulation const& q_tr = m_triangulations[idx].tr(); - Indexed_simplex full_simplex = s; - full_simplex.insert(idx); - for (std::vector::const_iterator it_p = P.begin(), - it_p_end = P.end() ; it_p != it_p_end ; ++it_p) - { - // star(p) does not contain "s" - std::size_t p = *it_p; + saa = it_pq->top(); + it_pq->pop(); - Tr_bare_point intersection = - *compute_aff_of_voronoi_face_and_tangent_subspace_intersection( - q_tr.current_dimension(), - project_points_and_compute_weights( - full_simplex, m_tangent_spaces[idx], q_tr.geom_traits()), - m_tangent_spaces[idx], - q_tr.geom_traits()); - - // The following computations are done in the Euclidian space - Point inters_global = unproject_point( - constr_wp(intersection, 0), m_tangent_spaces[idx], - q_tr.geom_traits()); - Vector thickening_v = k_diff_points(inters_global, m_points[p]); - FT squared_alpha = k_sqlen(thickening_v); - - // We insert full_simplex \ p - Incident_simplex is = full_simplex; - is.erase(p); - pqueues[simplex_dim - m_intrinsic_dim].push( - Simplex_and_alpha(p, is, squared_alpha, thickening_v)); - } + // Check if the simplex is still missing in the star + if (!is_simplex_in_star(saa.m_center_point_index, saa.m_simplex)) + found_saa = true; } } + + // If all the queues are empty, we're done! + if (!found_saa) + break; + + Tangent_space_basis &tangent_basis = + m_tangent_spaces[saa.m_center_point_index]; + + // If we're already in the ambiant dim, we just need to thicken the + // tangent subspace a bit more (see below) + if (tangent_basis.dimension() < m_ambient_dim) + { + // Otherwise, let's thicken the tangent space + bool vec_added = add_vector_to_orthonormal_basis( + tangent_basis, + saa.m_thickening_vector, + m_k, + FT(0), /* sqlen_threshold: default value */ + true /* add_to_thickening_vectors */); + + // CJTODO TEMP + if (!vec_added) + { + std::cerr << "FYI: the thickening vector was not added " + "to the basis since it was linearly dependent to it.\n"; + } + } + + // Update the alpha+/- values + tangent_basis.update_alpha_values_of_thickening_vectors( + saa.m_thickening_vector, m_k); + + // Recompute triangulation & star + compute_tangent_triangulation(saa.m_center_point_index); + +#ifdef CGAL_TC_PERFORM_EXTRA_CHECKS + if (!is_simplex_in_star(saa.m_center_point_index, saa.m_simplex)) + { + std::cerr + << "FAILED in solve_inconsistencies_using_adaptive_alpha_TC(): " + << "the simplex " << saa.m_center_point_index << ", "; + std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), + std::ostream_iterator(std::cerr, ", ")); + std::cerr << "was not added in the star\n"; + + Indexed_simplex full_s = saa.m_simplex; + full_s.insert(saa.m_center_point_index); + + // CJTODO TEMP + bool is_this_simplex_somewhere = false; + for(auto ii : saa.m_simplex) + { + Indexed_simplex z = full_s; + z.erase(ii); + if (is_simplex_in_star(ii, z)) + { + is_this_simplex_somewhere = true; + std::cerr << "The simplex is in star #" << ii << std::endl; + break; + } + } + if (!is_this_simplex_somewhere) + std::cerr << "WOW The simplex is NOWHERE!\n"; + + // CJTODO TEMP + if (is_simplex_in_the_ambient_delaunay(full_s)) + std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + else + std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + + } + // CJTODO TEMP + else + { + std::cerr << "SUCCESS in solve_inconsistencies_using_adaptive_alpha_TC(): " + << "the simplex " << saa.m_center_point_index << ", "; + std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), + std::ostream_iterator(std::cerr, ", ")); + std::cerr << "was successfully added in the star\n"; + } +#endif + + // It's not a problem if entries are duplicated in the pqueues + // since there's a check when we pop elements + fill_pqueues_for_alpha_tc(saa.m_center_point_index, pqueues); } - // CJTODO: the rest - #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex fixed in " << t.elapsed() << " seconds." << std::endl; #endif } +#endif // CGAL_ALPHA_TC std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, @@ -973,6 +1123,47 @@ public: } } + // Expensive! + bool is_simplex_in_the_ambient_delaunay( + Indexed_simplex const& s) const + { + //------------------------------------------------------------------------- + // Build the ambient Delaunay triangulation + // Then save its simplices into "amb_dt_simplices" + //------------------------------------------------------------------------- + + typedef Regular_triangulation_euclidean_traits RT_Traits; + typedef Regular_triangulation< + RT_Traits, + Triangulation_data_structure< + typename RT_Traits::Dimension, + Triangulation_vertex + > > RT; + typedef typename RT::Vertex_handle RT_VH; + typedef typename RT::Finite_full_cell_const_iterator FFC_it; + + RT ambient_dt(m_ambient_dim); + for (std::size_t i=0; idata() = i; + } + + for (FFC_it cit = ambient_dt.finite_full_cells_begin() ; + cit != ambient_dt.finite_full_cells_end() ; ++cit ) + { + Indexed_simplex simplex; + for (int i = 0 ; i < m_ambient_dim + 1 ; ++i) + simplex.insert(cit->vertex(i)->data()); + + if (std::includes(simplex.begin(), simplex.end(), + s.begin(), s.end())) + return true; + } + + return false; + } bool check_if_all_simplices_are_in_the_ambient_delaunay( const Simplicial_complex *p_complex = NULL, @@ -1040,10 +1231,10 @@ public: Simplex_range const *p_simplices; + std::size_t num_infinite_cells = 0; + Simplex_range stars_simplices; if (!p_complex) { - Simplex_range stars_simplices; - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation @@ -1064,7 +1255,7 @@ public: { if (tr.is_infinite(*it_c)) { - std::cerr << "Warning: infinite cell in star" << std::endl; + ++num_infinite_cells; continue; } Simplex simplex; @@ -1094,34 +1285,21 @@ public: std::inserter(*incorrect_simplices, incorrect_simplices->begin()) ); - if (!incorrect_simplices->empty()) - { - std::cerr - << "ERROR check_if_all_simplices_are_in_the_ambient_delaunay:" - << std::endl - << " Number of simplices in ambient RT: " << amb_dt_simplices.size() - << std::endl - << " Number of unique simplices in TC stars: " << p_simplices->size() - << std::endl - << " Number of wrong simplices: " << incorrect_simplices->size() - << std::endl; - return false; - } - else - { #ifdef CGAL_TC_VERBOSE - std::cerr - << "SUCCESS check_if_all_simplices_are_in_the_ambient_delaunay:" - << std::endl - << " Number of simplices in ambient RT: " << amb_dt_simplices.size() - << std::endl - << " Number of unique simplices in TC stars: " << p_simplices->size() - << std::endl - << " Number of wrong simplices: " << incorrect_simplices->size() - << std::endl; + std::cerr + << (incorrect_simplices->empty() ? "OK " : "ERROR ") + << "check_if_all_simplices_are_in_the_ambient_delaunay:" + << std::endl + << " Number of simplices in ambient RT: " << amb_dt_simplices.size() + << std::endl + << " Number of unique simplices in TC stars: " << p_simplices->size() + << std::endl + << " Number of infinite full cells in TC stars: " << num_infinite_cells + << std::endl + << " Number of wrong simplices: " << incorrect_simplices->size() + << std::endl; #endif - return true; - } + return incorrect_simplices->empty(); } private: @@ -1209,16 +1387,15 @@ private: } #endif - int triangulation_dim = local_triangulation_dim(i); + int tangent_space_dim = tangent_basis_dim(i); Triangulation &local_tr = - m_triangulations[i].construct_triangulation(triangulation_dim); + m_triangulations[i].construct_triangulation(tangent_space_dim); const Tr_traits &local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects typename Kernel::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); - typename Kernel::Equal_d k_eq = m_k.equal_d_object(); // Triangulation's traits functor & objects typename Tr_traits::Point_weight_d point_weight = @@ -1234,10 +1411,10 @@ private: // Insert p Tr_point proj_wp; - if(k_eq(compute_perturbed_point(i), tsb.origin())) + if(i == tsb.origin()) { proj_wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(triangulation_dim, ORIGIN), + local_tr_traits.construct_point_d_object()(tangent_space_dim, ORIGIN), m_weights[i]); } else @@ -1278,7 +1455,6 @@ private: compute_perturbed_weighted_point( neighbor_point_idx, neighbor_pt, neighbor_weight); - // "4*m_sq_half_sparsity" because both points can be perturbed if (squared_star_sphere_radius_plus_margin && k_sqdist(center_pt, neighbor_pt) > *squared_star_sphere_radius_plus_margin) @@ -1298,7 +1474,7 @@ private: vh->data() = neighbor_point_idx; // Let's recompute squared_star_sphere_radius_plus_margin - if (local_tr.current_dimension() >= triangulation_dim) + if (local_tr.current_dimension() >= tangent_space_dim) { squared_star_sphere_radius_plus_margin = boost::none; // Get the incident cells and look for the biggest circumsphere @@ -1341,9 +1517,11 @@ private: if (squared_star_sphere_radius_plus_margin) { #ifdef CGAL_TC_PERTURB_WEIGHT + // "4*m_sq_half_sparsity" because both points can be perturbed squared_star_sphere_radius_plus_margin = *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; #else + // "2*m_half_sparsity" because both points can be perturbed squared_star_sphere_radius_plus_margin = CGAL::square( CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2*m_half_sparsity); @@ -1415,12 +1593,19 @@ private: // Update the associated star (in m_stars) //*************************************************** - int triangulation_dim = local_triangulation_dim(i); Triangulation &local_tr = m_triangulations[i].tr(); + int triangulation_dim = local_tr.current_dimension(); Tr_traits const& local_tr_traits = local_tr.geom_traits(); Tr_vertex_handle center_vertex = m_triangulations[i].center_vertex(); Tangent_space_basis const& tsb = m_tangent_spaces[i]; +#ifdef CGAL_TC_PERFORM_EXTRA_CHECKS + if (triangulation_dim != tangent_basis_dim(i)) + std::cerr << "WARNING in update_star__with_thickening_vector: the " + "dimension of the local triangulation is different from " + "the dimension of the tangent space.\n"; +#endif + Star &star = m_stars[i]; star.clear(); int cur_dim_plus_1 = triangulation_dim + 1; @@ -1601,9 +1786,24 @@ next_face: #endif ) { -#ifdef CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 +#ifdef CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_2 + + double tt[2] = {p[1], -p[0]}; + Vector t(2, &tt[0], &tt[2]); + + // Normalize t1 and t2 + typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); + typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + + Tangent_space_basis ts(i); + ts.reserve(m_intrinsic_dim); + ts.push_back(scaled_vec(t, FT(1)/CGAL::sqrt(sqlen(t)))); + m_are_tangent_spaces_computed[i] = true; + + return ts; + +#elif defined(CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3) - // CJTODO: this is only for a sphere in R^3 double tt1[3] = {-p[1] - p[2], p[0], p[0]}; double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], p[2] * tt1[0] - p[0] * tt1[2], @@ -1615,7 +1815,7 @@ next_face: typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - Tangent_space_basis ts; + Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); @@ -1626,8 +1826,7 @@ next_face: #elif defined(CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D) - // CJTODO: this is only for torus_d - Tangent_space_basis ts(p); + Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); for (int dim = 0 ; dim < m_intrinsic_dim ; ++dim) { @@ -1701,7 +1900,7 @@ next_face: Eigen::MatrixXd cov = centered.adjoint() * centered; Eigen::SelfAdjointEigenSolver eig(cov); - Tangent_space_basis tsb(p); // p = compute_perturbed_point(i) here + Tangent_space_basis tsb(i); // p = compute_perturbed_point(i) here // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues @@ -1727,7 +1926,7 @@ next_face: if (p_orth_space_basis) { - p_orth_space_basis->origin() = p; + p_orth_space_basis->set_origin(i); for (int j = m_ambient_dim - m_intrinsic_dim - 1 ; j >= 0 ; --j) @@ -1791,7 +1990,7 @@ next_face: // Returns the dimension of the ith local triangulation // This is particularly useful for the alpha-TC - int local_triangulation_dim(std::size_t i) const + int tangent_basis_dim(std::size_t i) const { return m_tangent_spaces[i].dimension(); } @@ -1844,7 +2043,7 @@ next_face: typename Tr_traits::Compute_coordinate_d coord = tr_traits.compute_coordinate_d_object(); - Point global_point = tsb.origin(); + Point global_point = compute_perturbed_point(tsb.origin()); for (int i = 0 ; i < m_intrinsic_dim ; ++i) global_point = k_transl(global_point, k_scaled_vec(tsb[i], coord(p, i))); @@ -1870,7 +2069,7 @@ next_face: typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); - Vector v = diff_points(p, tsb.origin()); + Vector v = diff_points(p, compute_perturbed_point(tsb.origin())); std::vector coords; // Ambiant-space coords of the projected point @@ -1890,7 +2089,8 @@ next_face: coords.push_back(coord); } #endif - return Tr_bare_point(tsb.dimension(), coords.begin(), coords.end()); + return Tr_bare_point(static_cast( + coords.size()), coords.begin(), coords.end()); } // Project the point in the tangent space @@ -1921,11 +2121,15 @@ next_face: typename Kernel::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); - Vector v = diff_points(p, tsb.origin()); + Point origin = compute_perturbed_point(tsb.origin()); + Vector v = diff_points(p, origin); + + // Same dimension? Then the weight is 0 + bool same_dim = (point_dim == tsb.dimension()); std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(ccci(tsb.origin()), ccci(tsb.origin(), 0)); + std::vector p_proj(ccci(origin), ccci(origin, 0)); coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { @@ -1933,9 +2137,10 @@ next_face: FT c = inner_pdct(v, tsb[i]); coords.push_back(c); - // p_proj += c * v; - for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += c * coord(tsb[i], j); + // p_proj += c * tsb[i] + if (!same_dim) + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += c * coord(tsb[i], j); } #ifdef CGAL_ALPHA_TC @@ -1945,19 +2150,26 @@ next_face: FT c = inner_pdct(v, tv[i].vec); coords.push_back(c); - // p_proj += c * v; - for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += c * coord(tv[i].vec, j); + // p_proj += c * tv[i].vec + if (!same_dim) + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += c * coord(tv[i].vec, j); } #endif - Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); - + // Same dimension? Then the weight is 0 + FT sq_dist_to_proj_pt = 0; + if (!same_dim) + { + Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); + sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt); + } + return tr_traits.construct_weighted_point_d_object() ( tr_traits.construct_point_d_object()( - tsb.dimension(), coords.begin(), coords.end()), - w - m_k.squared_distance_d_object()(p, projected_pt) + static_cast(coords.size()), coords.begin(), coords.end()), + w - sq_dist_to_proj_pt ); } @@ -1974,7 +2186,7 @@ next_face: it != it_end ; ++it) { ret.push_back(project_point_and_compute_weight( - m_points[*it], m_weights[*it], tsb, tr_traits)); + compute_perturbed_weighted_point(*it), tsb, tr_traits)); } return ret; } @@ -2010,11 +2222,11 @@ next_face: std::size_t simplex_dim = s.size() - 1; // Compute basis - Tangent_space_basis basis(m_points[s[0]]); + Tangent_space_basis basis(s[0]); for (int j = 0 ; j < simplex_dim ; ++j) { Vector e = diff_pts( - m_points[s[j+1]], m_points[s[0]]); + compute_perturbed_point(s[j+1]), compute_perturbed_point(s[0])); basis.push_back(e); } basis = compute_gram_schmidt_basis(basis, m_k); @@ -2024,8 +2236,8 @@ next_face: for (int j = 0 ; j < simplex_dim ; ++j) { Tr_vector v_j = tr_diff_pts( - project_point(m_points[s[j+1]], basis), - project_point(m_points[s[0]], basis)); + project_point(compute_perturbed_point(s[j+1]), basis), + project_point(compute_perturbed_point(s[0]), basis)); for (int i = 0 ; i < simplex_dim ; ++i) m(j, i) = CGAL::to_double(coord(v_j, i)); } @@ -2039,7 +2251,8 @@ next_face: for ( ; !combi.finished() ; ++combi) { FT sq_length = sqdist( - m_points[s[combi[0]]], m_points[s[combi[1]]]); + compute_perturbed_point(s[combi[0]]), + compute_perturbed_point(s[combi[1]])); if (sq_length > max_sq_length) max_sq_length = sq_length; } @@ -2135,6 +2348,36 @@ next_face: return true; } + // A simplex here is a list of point indices + // It looks for s in star(p). + // "s" contains all the points of the simplex except p. + bool is_simplex_in_star( + std::size_t p, + Incident_simplex const& s, + bool check_also_in_non_maximal_faces = true) const + { + Star const& star = m_stars[p]; + + if (check_also_in_non_maximal_faces) + { + // For each simplex "is" of the star, check if ic_to_simplex is + // included in "is" + bool found = false; + for (Star::const_iterator is = star.begin(), is_end = star.end() ; + !found && is != is_end ; ++is) + { + if (std::includes(is->begin(), is->end(), s.begin(), s.end())) + found = true; + } + + return found; + } + else + { + return !(std::find(star.begin(), star.end(), s) == star.end()); + } + } + #ifdef CGAL_LINKED_WITH_TBB // Functor for try_to_solve_inconsistencies_in_a_local_triangulation function class Try_to_solve_inconsistencies_in_a_local_triangulation @@ -3250,8 +3493,8 @@ next_face: lp.set_a(k, current_row + 1, -coord(bi, k)); } - Point const& basis_origin = orthogonal_subspace_basis.origin(); - FT bi_dot_p = scalar_pdct(bi, pt_to_vec(basis_origin)); + FT bi_dot_p = scalar_pdct(bi, + pt_to_vec(compute_perturbed_point(orthogonal_subspace_basis.origin()))); lp.set_b(current_row , bi_dot_p + alpha); lp.set_b(current_row + 1, -bi_dot_p + alpha); @@ -3415,9 +3658,10 @@ next_face: // In order to have only one time each simplex, we only keep it // if the lowest index is the index of the center vertex - if (*c.begin() != (m_intrinsic_dim == 1 ? 2*idx : idx) + // CJTODO: uncomment? but it only works if there's no inconsistencies + /*if (*c.begin() != (m_intrinsic_dim == 1 ? 2*idx : idx) && color_simplex == -1) - continue; + continue;*/ os << 3 << " " << sstr_c.str(); if (color_inconsistencies || p_simpl_to_color_in_red diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 5ada1b8bbfa..9c26f718d30 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -33,12 +33,13 @@ //=========================== Alpha-TC or not? ================================ #define CGAL_ALPHA_TC - #define CGAL_USE_A_FIXED_ALPHA + //#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_PERFORM_EXTRA_CHECKS //#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES //#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index f0a8e7b99c4..c58b628fe5d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -145,24 +145,36 @@ namespace Tangential_complex_ { typedef typename Kernel::Vector_d Vector; typedef typename std::vector::const_iterator const_iterator; - Point m_origin; //fixme should probably be (const?) ref ? + std::size_t m_origin; std::vector m_vectors; - Point& origin() { return m_origin; } - const Point& origin() const { return m_origin; } + 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); } + 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(const Point& p) : m_origin(p) { } - Basis(const Point& p, const std::vector& vectors) - : m_origin(p), m_vectors(vectors) + Basis(std::size_t origin) : m_origin(origin) { } + Basis(std::size_t origin, const std::vector& vectors) + : m_origin(origin), m_vectors(vectors) { } #ifdef CGAL_ALPHA_TC @@ -192,12 +204,32 @@ namespace Tangential_complex_ { { return m_thickening_vectors; } - void add_thickening_vector(Vector const& vec, FT alpha_minus, FT alpha_plus) + 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 = 0.001; // CJTODO TEMP + FT alpha_i = k_scalar_pdct(it_v->vec, vec); + if (alpha_i + MARGIN > it_v->alpha_plus) + it_v->alpha_plus = alpha_i + MARGIN; + else if (alpha_i - MARGIN < it_v->alpha_minus) + it_v->alpha_minus = alpha_i - MARGIN; + } + } + int dimension() const { return static_cast(m_vectors.size() + m_thickening_vectors.size()); @@ -209,11 +241,23 @@ namespace Tangential_complex_ { } #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 - Basis compute_gram_schmidt_basis(Basis const& input_basis, K const& k) + bool add_vector_to_orthonormal_basis( + Basis & 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 Basis; + typedef typename K::FT FT; typedef typename K::Vector_d Vector; // Kernel functors @@ -221,23 +265,57 @@ namespace Tangential_complex_ { typename K::Scalar_product_d inner_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, inner_pdct(u, ej) / inner_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, inner_pdct(new_v, ej) / inner_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 + Basis compute_gram_schmidt_basis(Basis const& input_basis, K const& k) + { + typedef Basis 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) - { - Vector u = *inb_it; - - for (int j = 0 ; j < i ; ++j) - { - Vector const& ej = input_basis[j]; - Vector u_proj = scaled_vec(ej, inner_pdct(u, ej) / inner_pdct(ej, ej)); - u = diff_vec(u, u_proj); - } - - output_basis.push_back(normalize_vector(u, k)); - } + add_vector_to_orthonormal_basis(output_basis, *inb_it, k); return output_basis; } diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/test_utilities.h index 6f90145622e..810b5063fcd 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.h +++ b/Tangential_complex/test/Tangential_complex/test_utilities.h @@ -375,9 +375,12 @@ std::vector generate_points_on_torus_3D( template static void generate_uniform_points_on_torus_d( - const Kernel &k, int dim, std::size_t num_slices, OutputIterator out, + const Kernel &k, int dim, std::size_t num_slices, + OutputIterator out, + double radius_noise_percentage = 0., std::vector current_point = std::vector()) { + static CGAL::Random rng; if (current_point.size() == 2*dim) { *out++ = k.construct_point_d_object()( @@ -388,24 +391,32 @@ static void generate_uniform_points_on_torus_d( { 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 cp2 = current_point; FT alpha = 6.2832 * slice_idx / num_slices; - cp2.push_back(std::cos(alpha)); - cp2.push_back(std::sin(alpha)); + 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, cp2); + k, dim, num_slices, out, radius_noise_percentage, cp2); } } } template std::vector generate_points_on_torus_d( - std::size_t num_points, int dim, bool uniform = false) + 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; - CGAL::Random rng; + static CGAL::Random rng; std::vector points; points.reserve(num_points); @@ -413,7 +424,7 @@ std::vector generate_points_on_torus_d( { 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)); + k, dim, num_slices, std::back_inserter(points), radius_noise_percentage); } else { @@ -422,13 +433,20 @@ std::vector generate_points_on_torus_d( #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 pt; pt.reserve(dim*2); for (int curdim = 0 ; curdim < dim ; ++curdim) { FT alpha = rng.get_double(0, 6.2832); - pt.push_back(std::cos(alpha)); - pt.push_back(std::sin(alpha)); + 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()); @@ -462,7 +480,7 @@ std::vector generate_points_on_sphere_d( { 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.); @@ -543,68 +561,6 @@ std::vector generate_points_on_two_spheres_d( return points; } -template -std::vector -generate_points_on_two_orthogonal_spheres_d( - std::size_t num_points, int intrinsic_dim, int ambient_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 generator(dim, radius); - std::vector points; - points.reserve(num_points); - - typename Kernel::Compute_coordinate_d k_coord = - k.compute_coordinate_d_object(); - - std::vector 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 > 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)); - } - - std::vector pt1(ambient_dim); - for (int i = 0 ; i < intrinsic_dim ; ++i) - pt1[i] = k_coord(p, i); - // TODO : p2 - -#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 std::vector generate_points_on_3sphere_and_circle( From 752a5550be16641caabefae8dd560d006f1de818 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 26 Jun 2015 10:10:46 +0200 Subject: [PATCH 230/269] Renamed a few variables/functions --- .../Tangential_complex/benchmark_script.txt | 4 +- .../Tangential_complex/benchmark_tc.cpp | 2 +- .../include/CGAL/Tangential_complex.h | 54 +++++++++---------- .../CGAL/Tangential_complex/utilities.h | 6 +-- .../Tangential_complex/test_utilities.cpp | 8 +-- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 26ad4eaead0..7e243e29c03 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -2,7 +2,7 @@ # Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS #--------------------------------------------------------------------------------------------------------------------------------------------------------- -#---------------------------------------------------------------- Adaptive alpha TC tests ------------------------------------------------------------------------ +#---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ #generate_sphere_d 1 1 - 50 2 1 0.005 N Y N 3 1 #OK #generate_torus_d N - - 15 2 1 0.05 N Y N 10 1 #generate_sphere_d 0.302 3 - 50 3 2 0.005 N Y N 60 1 #OK @@ -16,7 +16,7 @@ generate_torus_d N 1 - 50 4 2 0.05 N Y N 3 1 # #generate_two_spheres_d 3 4 - 500 3 2 0.05 N Y N 10 1 #OK #generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N Y N 60 1 -#---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------ +#---------------------------------------------------------------- Fixed-alpha TC tests ------------------------------------------------------------------------ #generate_sphere_d 0.302 - - 70 2 1 0.005 N N N 60 1 #generate_sphere_d 0.304 0 - 100 3 2 0.05 N N N 60 1 #generate_sphere_d 3 0 - 100 4 3 0.05 N N N 60 1 diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 556208e190e..5751f421a14 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -407,7 +407,7 @@ void make_tc(std::vector &points, t.reset(); // Try to solve the remaining inconstencies #ifdef CGAL_ALPHA_TC - tc.solve_inconsistencies_using_adaptive_alpha_TC(); + tc.solve_inconsistencies_using_alpha_TC(); #else tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); #endif diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8eb77e4866d..7deef326a04 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -228,7 +228,7 @@ private: typedef std::vector Star; typedef std::vector Stars_container; - // For the priority queues of solve_inconsistencies_using_adaptive_alpha_TC + // For the priority queues of solve_inconsistencies_using_alpha_TC struct Simplex_and_alpha { Simplex_and_alpha() {} @@ -852,14 +852,14 @@ private: } public: - void solve_inconsistencies_using_adaptive_alpha_TC() + void solve_inconsistencies_using_alpha_TC() { #ifdef CGAL_TC_PROFILING Wall_clock_timer t; #endif #ifdef CGAL_TC_VERBOSE - std::cerr << "Fixing inconsistencies using adaptive alpha TC..." << std::endl; + std::cerr << "Fixing inconsistencies using alpha TC..." << std::endl; #endif //------------------------------------------------------------------------- @@ -948,7 +948,7 @@ public: if (!is_simplex_in_star(saa.m_center_point_index, saa.m_simplex)) { std::cerr - << "FAILED in solve_inconsistencies_using_adaptive_alpha_TC(): " + << "FAILED in solve_inconsistencies_using_alpha_TC(): " << "the simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); @@ -983,7 +983,7 @@ public: // CJTODO TEMP else { - std::cerr << "SUCCESS in solve_inconsistencies_using_adaptive_alpha_TC(): " + std::cerr << "SUCCESS in solve_inconsistencies_using_alpha_TC(): " << "the simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); @@ -1857,7 +1857,7 @@ next_face: m_k.squared_length_d_object(); typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Scalar_product_d inner_pdct = + typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); typename Kernel::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); @@ -1967,7 +1967,7 @@ next_face: //Vector n = m_k.point_to_vector_d_object()(p); //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); - //std::cerr << "IP = " << inner_pdct(n, ts[0]) << " & " << inner_pdct(n, ts[1]) << std::endl; + //std::cerr << "IP = " << scalar_pdct(n, ts[0]) << " & " << scalar_pdct(n, ts[1]) << std::endl; return tsb; @@ -1981,8 +1981,8 @@ next_face: //Vector t2(32., 5., 85.); //Tangent_space_basis ts; //ts.reserve(m_intrinsic_dim); - //ts.push_back(diff_vec(t1, scaled_vec(n, inner_pdct(t1, n)))); - //ts.push_back(diff_vec(t2, scaled_vec(n, inner_pdct(t2, n)))); + //ts.push_back(diff_vec(t1, scaled_vec(n, scalar_pdct(t1, n)))); + //ts.push_back(diff_vec(t2, scaled_vec(n, scalar_pdct(t2, n)))); //ts = compute_gram_schmidt_basis(ts, m_k); //return ts; */ @@ -2064,7 +2064,7 @@ next_face: Tr_bare_point project_point(const Point &p, const Tangent_space_basis &tsb) const { - typename Kernel::Scalar_product_d inner_pdct = + typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); @@ -2076,8 +2076,8 @@ next_face: coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { - // Local coords are given by the inner product with the vectors of tsb - FT coord = inner_pdct(v, tsb[i]); + // Local coords are given by the scalar product with the vectors of tsb + FT coord = scalar_pdct(v, tsb[i]); coords.push_back(coord); } @@ -2085,7 +2085,7 @@ next_face: Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); for (int i = 0 ; i < tv.size() ; ++i) { - FT coord = inner_pdct(v, tv[i].vec); + FT coord = scalar_pdct(v, tv[i].vec); coords.push_back(coord); } #endif @@ -2112,7 +2112,7 @@ next_face: const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); - typename Kernel::Scalar_product_d inner_pdct = + typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); typename Kernel::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); @@ -2133,8 +2133,8 @@ next_face: coords.reserve(tsb.dimension()); for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) { - // Local coords are given by the inner product with the vectors of tsb - FT c = inner_pdct(v, tsb[i]); + // Local coords are given by the scalar product with the vectors of tsb + FT c = scalar_pdct(v, tsb[i]); coords.push_back(c); // p_proj += c * tsb[i] @@ -2147,7 +2147,7 @@ next_face: Tangent_space_basis::Thickening_vectors const& tv = tsb.thickening_vectors(); for (int i = 0 ; i < tv.size() ; ++i) { - FT c = inner_pdct(v, tv[i].vec); + FT c = scalar_pdct(v, tv[i].vec); coords.push_back(c); // p_proj += c * tv[i].vec @@ -2804,7 +2804,7 @@ next_face: m_k.squared_distance_d_object(); typename Kernel::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - typename Kernel::Scalar_product_d k_inner_pdct = + typename Kernel::Scalar_product_d k_scalar_pdct = m_k.scalar_product_d_object(); typename Kernel::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); @@ -2983,9 +2983,9 @@ next_face: compute_perturbed_point(q_idx), compute_perturbed_point(p_idx)); pq = k_scaled_vec(pq, FT(1)/sqrt(k_sqlen(pq))); FT dot_product_1 = std::abs( - k_inner_pdct(m_orth_spaces[p_idx][0], pq)); + k_scalar_pdct(m_orth_spaces[p_idx][0], pq)); FT dot_product_2 = std::abs( - k_inner_pdct(m_orth_spaces[q_idx][0], pq)); + k_scalar_pdct(m_orth_spaces[q_idx][0], pq)); csv_stream << inside_pt_indices.size() << " ; "; csv_stream << dot_product_1 << " ; " << dot_product_2; csv_stream << std::endl; @@ -3008,7 +3008,7 @@ next_face: for ( ; it_v != inconsistent_simplex.end() ; ++it_v) { FT dot_products_between_normals = - k_inner_pdct(m_tangent_spaces[i1][0], m_tangent_spaces[*it_v][0]); + k_scalar_pdct(m_tangent_spaces[i1][0], m_tangent_spaces[*it_v][0]); std::cerr << dot_products_between_normals << ", "; //csv_stream << " ; " < - bool does_voronoi_face_and_alpha_tangent_subspace_intersect( + bool does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( std::size_t center_pt_index, Indexed_point_range_a const& P, Indexed_point_range_b const& Q, diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index c58b628fe5d..f4b74119850 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -262,14 +262,14 @@ namespace Tangential_complex_ { // Kernel functors typename K::Scaled_vector_d scaled_vec = k.scaled_vector_d_object(); - typename K::Scalar_product_d inner_pdct = k.scalar_product_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, inner_pdct(u, ej) / inner_pdct(ej, ej)); + Vector u_proj = scaled_vec(ej, scalar_pdct(u, ej) / scalar_pdct(ej, ej)); u = diff_vec(u, u_proj); } @@ -287,7 +287,7 @@ namespace Tangential_complex_ { { Vector const& ej = basis[j]; Vector new_v_proj = scaled_vec( - ej, inner_pdct(new_v, ej) / inner_pdct(ej, ej)); + 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); diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.cpp b/Tangential_complex/test/Tangential_complex/test_utilities.cpp index f902cca8f08..85d1646cecf 100644 --- a/Tangential_complex/test/Tangential_complex/test_utilities.cpp +++ b/Tangential_complex/test/Tangential_complex/test_utilities.cpp @@ -37,16 +37,16 @@ void test_does_voronoi_face_and_alpha_tangent_subspace_intersect() osb.push_back(Vec(0.01, 0.995)); - assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( points, 0, P, Q, osb, 0.0, k) == false); - assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( points, 0, P, Q, osb, 0.5, k) == false); - assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( points, 0, P, Q, osb, 1.0, k) == false); - assert(does_voronoi_face_and_alpha_tangent_subspace_intersect( + assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect( points, 0, P, Q, osb, 1.5, k) == true); } From d7be58c3099f121adc791e19471b1f233f4249a2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 30 Jun 2015 17:51:33 +0200 Subject: [PATCH 231/269] Fixed a bug in Gram-Schmidt We were not taking thickening vectors into account --- .../CGAL/Tangential_complex/utilities.h | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index f4b74119850..1c8956382cf 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -224,9 +224,27 @@ namespace Tangential_complex_ { const FT MARGIN = 0.001; // CJTODO TEMP FT alpha_i = k_scalar_pdct(it_v->vec, vec); if (alpha_i + MARGIN > 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; +#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 < 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; +#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 + } } } @@ -272,6 +290,12 @@ namespace Tangential_complex_ { 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); @@ -290,6 +314,13 @@ namespace Tangential_complex_ { 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)); } From fab4c9d5a81bfab393ea3a1d728a50cdb105ae84 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 30 Jun 2015 17:55:29 +0200 Subject: [PATCH 232/269] More debugging code --- .../include/CGAL/Tangential_complex.h | 42 +++++++++++++++++-- .../include/CGAL/Tangential_complex/config.h | 1 + 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 7deef326a04..8de84e1c86b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -952,14 +952,15 @@ public: << "the simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << "was not added in the star\n"; + std::cerr << "was not added in the star #" + << saa.m_center_point_index << "\n"; Indexed_simplex full_s = saa.m_simplex; full_s.insert(saa.m_center_point_index); // CJTODO TEMP bool is_this_simplex_somewhere = false; - for(auto ii : saa.m_simplex) + for(auto ii : saa.m_simplex) // CJTODO C++11 { Indexed_simplex z = full_s; z.erase(ii); @@ -978,7 +979,41 @@ public: std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; else std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; - + + std::cerr << "Checking simplices of the star #" + << saa.m_center_point_index << std::endl; + Star const& star = m_stars[saa.m_center_point_index]; + for (Star::const_iterator is = star.begin(), is_end = star.end() ; + is != is_end ; ++is) + { + if (is_simplex_in_the_ambient_delaunay(*is)) + std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + else + { + std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + for(auto ii : *is) // CJTODO C++11 + perturb(ii); + } + } + + std::cerr << "Perturbing the points..." << std::endl; + perturb(saa.m_center_point_index); + for(auto ii : saa.m_simplex) // CJTODO C++11 + perturb(ii); + refresh_tangential_complex(); + pqueues.clear(); + pqueues.resize(m_ambient_dim - m_intrinsic_dim + 1); + + std::size_t num_inconsistent_simplices = 0; + // For each triangulation + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + num_inconsistent_simplices += fill_pqueues_for_alpha_tc(i, pqueues); + +#ifdef CGAL_TC_VERBOSE + std::cerr + << "Num inconsistent simplices found when filling the priority queues: " + << num_inconsistent_simplices << std::endl; +#endif } // CJTODO TEMP else @@ -988,6 +1023,7 @@ public: std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); std::cerr << "was successfully added in the star\n"; + //check_if_all_simplices_are_in_the_ambient_delaunay(); } #endif diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 9c26f718d30..3f01cde07a4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -39,6 +39,7 @@ //========================= 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 //#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM From e8e5f7e43818ccf84cbdd925c33a8b3d1da3558c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 1 Jul 2015 15:53:19 +0200 Subject: [PATCH 233/269] More detailed trace --- Tangential_complex/include/CGAL/Tangential_complex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 8de84e1c86b..ec3b7926815 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1022,7 +1022,8 @@ public: << "the simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << "was successfully added in the star\n"; + std::cerr << "was successfully added in the star #" + << saa.m_center_point_index << "\n"; //check_if_all_simplices_are_in_the_ambient_delaunay(); } #endif From f015159ff05ceffe12b1aad44056a646e8ae2c18 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 1 Jul 2015 15:53:59 +0200 Subject: [PATCH 234/269] Use a 0.1% margin instead of a fixed offset --- .../include/CGAL/Tangential_complex/utilities.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 1c8956382cf..8dc54e557a1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -221,25 +221,25 @@ namespace Tangential_complex_ { it_v_end = m_thickening_vectors.end() ; it_v != it_v_end ; ++it_v) { - const FT MARGIN = 0.001; // CJTODO TEMP + const FT MARGIN_RATIO = 1.001; // CJTODO TEMP FT alpha_i = k_scalar_pdct(it_v->vec, vec); - if (alpha_i + MARGIN > it_v->alpha_plus) + 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; + 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 < it_v->alpha_minus) + 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; + 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; From 48b8382de3a5ecf066ba0c4de083540314d59c84 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 6 Jul 2015 19:04:29 +0200 Subject: [PATCH 235/269] Definitely removed the "infinite vertex at position 0" constraint... ... and fixed the regular triangulation at the same time. Even though this constraint had been dropped, the code was still expecting the infinite vertex to be at position 0 in the cells. Now, it's not the case anymore, the infinite vertex can be anywhere. This is particularly useful for the 2D case, because the constraint made the orientation of the "rightmost" infinite cell wrong. --- .../include/CGAL/Delaunay_triangulation.h | 61 ++++++---- .../include/CGAL/Regular_triangulation.h | 114 +++++------------- Triangulation/include/CGAL/Triangulation.h | 30 +++-- .../CGAL/Triangulation_data_structure.h | 8 +- .../test/Triangulation/test_delaunay.cpp | 6 +- .../test/Triangulation/test_regular.cpp | 3 +- 6 files changed, 94 insertions(+), 128 deletions(-) diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index a1c8015bb3e..ac27605c6e0 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -365,24 +365,14 @@ Delaunay_triangulation return Full_cell_handle(); } Full_cell_handle left = v->full_cell(); - if( is_infinite(left) && left->neighbor(0)->index(left) == 0 ) // we are on the infinite right. - left = left->neighbor(0); if( 0 == left->index(v) ) left = left->neighbor(1); CGAL_assertion( 1 == left->index(v) ); Full_cell_handle right = left->neighbor(0); - if( ! is_infinite(right) ) - { - tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); - set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); - } - else - { - tds().associate_vertex_with_full_cell(left, 1, left->vertex(0)); - tds().associate_vertex_with_full_cell(left, 0, infinite_vertex()); - set_neighbors(left, 0, left->neighbor(1), left->mirror_index(1)); - set_neighbors(left, 1, right->neighbor(1), right->mirror_index(1)); - } + + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); + tds().delete_vertex(v); tds().delete_full_cell(right); return left; @@ -471,24 +461,16 @@ Delaunay_triangulation { int v_idx = (*it)->index(v); tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); - if( v_idx != 0 ) - { - // we must put the infinite vertex at index 0. - // OK, now with the new convention that the infinite vertex - // does not have to be at index 0, this is not necessary, - // but still, I prefer to keep this piece of code here. [-- Samuel Hornus] - (*it)->swap_vertices(0, v_idx); - // Now, we preserve the positive orientation of the full_cell - (*it)->swap_vertices(current_dimension() - 1, current_dimension()); - } } // Make the handles to infinite full cells searchable infinite_simps.make_searchable(); // Then, modify the neighboring relation for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) { - for( int i = 1; i <= current_dimension(); ++i ) + for( int i = 0; i <= current_dimension(); ++i ) { + if (is_infinite((*it)->vertex(i))) + continue; (*it)->vertex(i)->set_full_cell(*it); Full_cell_handle n = (*it)->neighbor(i); // Was |n| a finite full cell prior to removing |v| ? @@ -732,6 +714,35 @@ Delaunay_triangulation CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) reorient_full_cells(); + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + // Otherwise, let's find the right infinite cell + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + } + } } return v; } diff --git a/Triangulation/include/CGAL/Regular_triangulation.h b/Triangulation/include/CGAL/Regular_triangulation.h index 02efd84268c..7d23dfa0f83 100644 --- a/Triangulation/include/CGAL/Regular_triangulation.h +++ b/Triangulation/include/CGAL/Regular_triangulation.h @@ -242,7 +242,7 @@ public: Facet ft; Full_cell_handle c = locate (*p, lt, f, ft, hint); Vertex_handle v = insert (*p, lt, f, ft, c); - + hint = v == Vertex_handle() ? c : v->full_cell(); } return number_of_vertices() - n; @@ -269,9 +269,7 @@ public: CGAL_assertion( Vertex_handle() != hint ); return insert(p, hint->full_cell()); } - - Vertex_handle insert_outside_convex_hull_1( - const Weighted_point & p, Full_cell_handle s); + Vertex_handle insert_outside_affine_hull(const Weighted_point &); Vertex_handle insert_in_conflicting_cell( const Weighted_point &, const Full_cell_handle, @@ -494,24 +492,12 @@ Regular_triangulation return Full_cell_handle(); } Full_cell_handle left = v->full_cell(); - if( is_infinite(left) && left->neighbor(0)->index(left) == 0 ) // we are on the infinite right. - left = left->neighbor(0); if( 0 == left->index(v) ) left = left->neighbor(1); CGAL_assertion( 1 == left->index(v) ); Full_cell_handle right = left->neighbor(0); - if( ! is_infinite(right) ) - { - tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); - set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); - } - else - { - tds().associate_vertex_with_full_cell(left, 1, left->vertex(0)); - tds().associate_vertex_with_full_cell(left, 0, infinite_vertex()); - set_neighbors(left, 0, left->neighbor(1), left->mirror_index(1)); - set_neighbors(left, 1, right->neighbor(1), right->mirror_index(1)); - } + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); tds().delete_vertex(v); tds().delete_full_cell(right); return left; @@ -604,24 +590,16 @@ Regular_triangulation { int v_idx = (*it)->index(v); tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); - if( v_idx != 0 ) - { - // we must put the infinite vertex at index 0. - // OK, now with the new convention that the infinite vertex - // does not have to be at index 0, this is not necessary, - // but still, I prefer to keep this piece of code here. [-- Samuel Hornus] - (*it)->swap_vertices(0, v_idx); - // Now, we preserve the positive orientation of the full_cell - (*it)->swap_vertices(current_dimension() - 1, current_dimension()); - } } // Make the handles to infinite full cells searchable infinite_simps.make_searchable(); // Then, modify the neighboring relation for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) { - for( int i = 1; i <= current_dimension(); ++i ) + for( int i = 0 ; i <= current_dimension(); ++i ) { + if (is_infinite((*it)->vertex(i))) + continue; (*it)->vertex(i)->set_full_cell(*it); Full_cell_handle n = (*it)->neighbor(i); // Was |n| a finite full cell prior to removing |v| ? @@ -844,46 +822,7 @@ Regular_triangulation // !NO break here! } default: - if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) - return insert_outside_convex_hull_1(p, s); - else - return insert_in_conflicting_cell(p, s); - break; - } -} - -// NOT DOCUMENTED... -template < class RTTraits, class TDS > -typename Regular_triangulation::Vertex_handle -Regular_triangulation -::insert_outside_convex_hull_1(const Weighted_point & p, Full_cell_handle s) -{ - // This is a special case for dimension 1, because in that case, the right - // infinite full_cell is not correctly oriented... (sice its first vertex is the - // infinite one... - - bool in_conflict = is_in_conflict(p, s); - - // If p is not in conflict with s, then p is hidden - // => we don't insert it - if (!in_conflict) - { - m_hidden_points.push_back(p); - return Vertex_handle(); - } - else - { - CGAL_precondition( is_infinite(s) ); - CGAL_precondition( 1 == current_dimension() ); - int inf_v_index = s->index(infinite_vertex()); - bool swap = (0 == s->neighbor(inf_v_index)->index(s)); - Vertex_handle v = tds().insert_in_full_cell(s); - v->set_point(p); - if( swap ) - { - s->swap_vertices(0, 1); - } - return v; + return insert_in_conflicting_cell(p, s); } } @@ -908,6 +847,30 @@ Regular_triangulation CGAL_assertion( ZERO != o ); if( NEGATIVE == o ) reorient_full_cells(); + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); + } + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); + } + } + } } return v; } @@ -946,18 +909,7 @@ Regular_triangulation // !NO break here! } default: - { - if( 1 == current_dimension() && Base::OUTSIDE_CONVEX_HULL == lt) - { - if (s->has_vertex(star_center)) - return insert_outside_convex_hull_1(p, s); - } - else - { - return insert_in_conflicting_cell(p, s, star_center); - } - break; - } + return insert_in_conflicting_cell(p, s, star_center); } return Vertex_handle(); diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index 2dee695b77a..d18df57a282 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -756,6 +756,21 @@ protected: } }; + void display_all_full_cells__debugging() + { + std::cerr << "ALL FULL CELLS:" << std::endl; + for (Full_cell_const_iterator cit = full_cells_begin() ; + cit != full_cells_end() ; ++cit ) + { + std::cerr << std::hex << &*cit << ": "; + for (int jj = 0 ; jj <= current_dimension() ; ++jj) + std::cerr << (is_infinite(cit->vertex(jj)) ? 0xFFFFFFFF : (unsigned int)&*cit->vertex(jj)) << " - "; + std::cerr << std::dec << std::endl; + } + std::cerr << std::endl; + } + + }; // Triangulation<...> // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = @@ -769,17 +784,15 @@ Triangulation { if( current_dimension() < 1 ) return; + Full_cell_iterator sit = full_cells_begin(); Full_cell_iterator send = full_cells_end(); - while( sit != send ) + for ( ; sit != send ; ++sit) { - if( is_infinite(sit) && (1 == current_dimension()) ) + if( ! (is_infinite(sit) && (1 == current_dimension())) ) { - ++sit; - continue; + sit->swap_vertices(current_dimension() - 1, current_dimension()); } - sit->swap_vertices(current_dimension() - 1, current_dimension()); - ++sit; } } @@ -901,13 +914,8 @@ Triangulation CGAL_precondition( is_infinite(s) ); CGAL_precondition( 1 == current_dimension() ); int inf_v_index = s->index(infinite_vertex()); - bool swap = (0 == s->neighbor(inf_v_index)->index(s)); Vertex_handle v = tds().insert_in_full_cell(s); v->set_point(p); - if( swap ) - { - s->swap_vertices(0, 1); - } return v; } diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 895a6f11b51..aab42e68b84 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -894,8 +894,7 @@ Triangulation_data_structure if( v_idx != current_dimension() ) { (*it)->swap_vertices(v_idx, current_dimension()); - if( ( ! (*it)->has_vertex(star) ) || (current_dimension() > 2) ) - (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1); + (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1); } (*it)->set_vertex(current_dimension(), Vertex_handle()); (*it)->set_neighbor(current_dimension(), Full_cell_handle()); @@ -1144,11 +1143,6 @@ void Triangulation_data_structure for( int k = 1; k <= cur_dim; ++k ) associate_vertex_with_full_cell(S_new, k, vertex(S, k - 1)); } - else if( cur_dim == 2 ) - { // if cur. dim. is 2, we must take care of the 'rightmost' infinite vertex. - if( S->mirror_index(S->index(star)) == 0 ) - swap_me = S; - } } // now we setup the neighbors set_visited(start, false); diff --git a/Triangulation/test/Triangulation/test_delaunay.cpp b/Triangulation/test/Triangulation/test_delaunay.cpp index 3b98f66660d..98b75431ca4 100644 --- a/Triangulation/test/Triangulation/test_delaunay.cpp +++ b/Triangulation/test/Triangulation/test_delaunay.cpp @@ -117,10 +117,10 @@ int main(int argc, char **argv) if( argc > 1 ) N = atoi(argv[1]); //go<5>(N); - //go<4>(N); - //go<3>(N); + go<4>(N); + go<3>(N); go<2>(N); - //go<1>(N); + go<1>(N); cerr << endl; return 0; diff --git a/Triangulation/test/Triangulation/test_regular.cpp b/Triangulation/test/Triangulation/test_regular.cpp index d1a6c568777..01aa6d957c5 100644 --- a/Triangulation/test/Triangulation/test_regular.cpp +++ b/Triangulation/test/Triangulation/test_regular.cpp @@ -123,9 +123,10 @@ int main(int argc, char **argv) if( argc > 1 ) N = atoi(argv[1]); //go<5>(N); - //go<4>(N); + go<4>(N); go<3>(N); go<2>(N); + go<1>(N); cerr << endl; return 0; From 35555fd3f99dfca0b344670f7f2645e5ca90130f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 6 Jul 2015 19:45:59 +0200 Subject: [PATCH 236/269] Forgot to fix Triangulation accordingly (see previous commit) --- Triangulation/include/CGAL/Triangulation.h | 32 ++++++++++++++++++- .../test/Triangulation/test_triangulation.cpp | 9 +++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index d18df57a282..dc3df8adc0c 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -756,7 +756,7 @@ protected: } }; - void display_all_full_cells__debugging() + void display_all_full_cells__debugging() const { std::cerr << "ALL FULL CELLS:" << std::endl; for (Full_cell_const_iterator cit = full_cells_begin() ; @@ -971,6 +971,36 @@ Triangulation CGAL_assertion( COPLANAR != o ); if( NEGATIVE == o ) reorient_full_cells(); + + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + // Otherwise, let's find the right infinite cell + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + } + } } return v; } diff --git a/Triangulation/test/Triangulation/test_triangulation.cpp b/Triangulation/test/Triangulation/test_triangulation.cpp index f6230bf4250..f48b261f28e 100644 --- a/Triangulation/test/Triangulation/test_triangulation.cpp +++ b/Triangulation/test/Triangulation/test_triangulation.cpp @@ -114,10 +114,11 @@ int main(int argc, char **argv) int N = 1000; if( argc > 1 ) N = atoi(argv[1]); - //go<5>(N); - //go<3>(N); - go<2>(N); - //go<1>(N); + //go<5>(N); + go<4>(N); + go<3>(N); + go<2>(N); + go<1>(N); cerr << std::endl; return 0; From 3e1a2e86691f487d065723c089356cfd13c600e2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 7 Jul 2015 09:18:16 +0200 Subject: [PATCH 237/269] Call set_error_behaviour to ease debugging --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 5751f421a14..cf67335779e 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -533,6 +533,8 @@ void make_tc(std::vector &points, int main() { + CGAL::set_error_behaviour(CGAL::ABORT); + #ifdef CGAL_LINKED_WITH_TBB # ifdef _DEBUG int num_threads = 1; From b88286122fca9194f8ea6aa6b3f9d0b2dacc7073 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 7 Jul 2015 09:19:12 +0200 Subject: [PATCH 238/269] Don't build ambient Delaunay if dim is too high --- .../test/Tangential_complex/test_tangential_complex.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index 9ac1d555c5c..c632a9e4b11 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -100,7 +100,8 @@ int main() tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - tc.check_if_all_simplices_are_in_the_ambient_delaunay(); + if (ambient_dim <= 4) + tc.check_if_all_simplices_are_in_the_ambient_delaunay(); double export_before_time = -1.; if (INTRINSIC_DIMENSION <= 3) From 8418c6178d9531066d89a62beb1b5066528f8404 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 7 Jul 2015 09:20:36 +0200 Subject: [PATCH 239/269] Verbose output --- .../include/CGAL/Tangential_complex.h | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index ec3b7926815..84a7691e0a0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1396,7 +1396,11 @@ private: // other threads are perturbing the positions const Point center_pt = compute_perturbed_point(i); Tangent_space_basis &tsb = m_tangent_spaces[i]; - + +#if defined(CGAL_TC_VERY_VERBOSE) && defined(CGAL_ALPHA_TC) + std::cerr << "Base dimension, incl. thickening vectors: " + << tsb.dimension() << std::endl; +#endif // Estimate the tangent space if (!m_are_tangent_spaces_computed[i]) { @@ -1465,6 +1469,10 @@ private: if (verbose) std::cerr << "* Inserted point #" << i << std::endl; +#ifdef CGAL_TC_VERY_VERBOSE + std::size_t num_attempts_to_insert_points = 1; + std::size_t num_inserted_points = 1; +#endif //const int NUM_NEIGHBORS = 150; //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); @@ -1500,11 +1508,18 @@ private: Tr_point proj_pt = project_point_and_compute_weight( neighbor_pt, neighbor_weight, tsb, local_tr_traits); + +#ifdef CGAL_TC_VERY_VERBOSE + ++num_attempts_to_insert_points; +#endif Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); //Tr_vertex_handle vh = local_tr.insert(proj_pt); if (vh != Tr_vertex_handle()) { +#ifdef CGAL_TC_VERY_VERBOSE + ++num_inserted_points; +#endif if (verbose) std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; @@ -1568,7 +1583,11 @@ private: } } } - + +#ifdef CGAL_TC_VERY_VERBOSE + std::cerr << "Inserted " << num_inserted_points << " points / " + << num_attempts_to_insert_points << " attemps to compute the star\n"; +#endif #ifdef CGAL_ALPHA_TC if (tsb.num_thickening_vectors() == 0) update_star__no_thickening_vectors(i); From c92ca5ff47ebc5ae87147a7f77295594cce0c571 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 7 Jul 2015 16:03:59 +0200 Subject: [PATCH 240/269] Renamed test_utilities.h to avoid confusion --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 2 +- Tangential_complex/test/Tangential_complex/aniso_TC.cpp | 2 +- .../test/Tangential_complex/test_tangential_complex.cpp | 2 +- .../{test_utilities.h => testing_utilities.h} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename Tangential_complex/test/Tangential_complex/{test_utilities.h => testing_utilities.h} (100%) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index cf67335779e..b90dce674e4 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -12,7 +12,7 @@ #include #include -#include "../../test/Tangential_complex/test_utilities.h" +#include "../../test/Tangential_complex/testing_utilities.h" #include #include diff --git a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp index 147411ee2e5..6983311773a 100644 --- a/Tangential_complex/test/Tangential_complex/aniso_TC.cpp +++ b/Tangential_complex/test/Tangential_complex/aniso_TC.cpp @@ -3,7 +3,7 @@ #include #include -#include "../../test/Tangential_complex/test_utilities.h" +#include "../../test/Tangential_complex/testing_utilities.h" #include // Anisotropic metrics #include diff --git a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp index c632a9e4b11..f94f004a504 100644 --- a/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp +++ b/Tangential_complex/test/Tangential_complex/test_tangential_complex.cpp @@ -12,7 +12,7 @@ #include #include -#include "test_utilities.h" +#include "testing_utilities.h" #include #include diff --git a/Tangential_complex/test/Tangential_complex/test_utilities.h b/Tangential_complex/test/Tangential_complex/testing_utilities.h similarity index 100% rename from Tangential_complex/test/Tangential_complex/test_utilities.h rename to Tangential_complex/test/Tangential_complex/testing_utilities.h From d5ef993d30c2e028e25b9332ee883aa95dc91bbf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 20 Jul 2015 17:08:05 +0200 Subject: [PATCH 241/269] Fix warnings + timers + minor changes --- .../include/CGAL/Tangential_complex.h | 114 ++++++++++++------ .../CGAL/Tangential_complex/utilities.h | 29 +++++ 2 files changed, 106 insertions(+), 37 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 84a7691e0a0..596de6d390f 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -415,8 +415,8 @@ public: m_k.compute_coordinate_d_object(); std::vector sum_eigen_values(m_ambient_dim, FT(0)); - std::size_t num_points_for_pca = - std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim); + std::size_t num_points_for_pca = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); typename Points::const_iterator it_p = m_points.begin(); typename Points::const_iterator it_p_end = m_points.end(); @@ -426,6 +426,7 @@ public: const Point &p = *it_p; KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); + //******************************* PCA ************************************* // One row = one point @@ -656,7 +657,7 @@ public: for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { // Don't export infinite cells - if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + if (is_infinite(*it_inc_simplex)) continue; Indexed_simplex c = *it_inc_simplex; @@ -704,8 +705,7 @@ public: for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { // Don't export infinite cells - if (!export_infinite_simplices && *it_inc_simplex->rbegin() - == std::numeric_limits::max()) + if (!export_infinite_simplices && is_infinite(*it_inc_simplex)) continue; Indexed_simplex c = *it_inc_simplex; @@ -785,7 +785,7 @@ private: Incident_simplex const& s = *it_inc_simplex; // Don't check infinite cells - if (*s.rbegin() == std::numeric_limits::max()) + if (is_infinite(s)) continue; int simplex_dim = static_cast(s.size()); @@ -869,6 +869,10 @@ public: std::vector, std::greater > AATC_pq; typedef std::vector PQueues; + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_pq; +#endif // One queue per dimension, from intrinsic dim (index = 0) to // ambiant dim (index = ambiant - intrinsic dim) @@ -883,7 +887,11 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Num inconsistent simplices found when filling the priority queues: " - << num_inconsistent_simplices << std::endl; + << num_inconsistent_simplices; +# ifdef CGAL_TC_PROFILING + std::cerr << " (" << t_pq.elapsed() << " s)" << std::endl; +# endif + std::cerr << std::endl; #endif //------------------------------------------------------------------------- @@ -893,6 +901,10 @@ public: // While there's elements to treat in the queues for(;;) { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_one_fix; +#endif + // Pick the simplex with the lowest dimension and the lowest alpha Simplex_and_alpha saa; bool found_saa = false; @@ -949,11 +961,16 @@ public: { std::cerr << "FAILED in solve_inconsistencies_using_alpha_TC(): " - << "the simplex " << saa.m_center_point_index << ", "; + << "simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << "was not added in the star #" - << saa.m_center_point_index << "\n"; + std::cerr << " not added in star #" + << saa.m_center_point_index + << " (basis dim = " << tangent_basis.dimension() +# ifdef CGAL_TC_PROFILING + << " - " << t_one_fix.elapsed() << " s" +# endif + << ")\n"; Indexed_simplex full_s = saa.m_simplex; full_s.insert(saa.m_center_point_index); @@ -975,24 +992,27 @@ public: std::cerr << "WOW The simplex is NOWHERE!\n"; // CJTODO TEMP - if (is_simplex_in_the_ambient_delaunay(full_s)) - std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; - else - std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; - - std::cerr << "Checking simplices of the star #" - << saa.m_center_point_index << std::endl; - Star const& star = m_stars[saa.m_center_point_index]; - for (Star::const_iterator is = star.begin(), is_end = star.end() ; - is != is_end ; ++is) - { - if (is_simplex_in_the_ambient_delaunay(*is)) + if (m_ambient_dim <= 3) + { + if (is_simplex_in_the_ambient_delaunay(full_s)) std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; else - { std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; - for(auto ii : *is) // CJTODO C++11 - perturb(ii); + + std::cerr << "Checking simplices of the star #" + << saa.m_center_point_index << std::endl; + Star const& star = m_stars[saa.m_center_point_index]; + for (Star::const_iterator is = star.begin(), is_end = star.end() ; + is != is_end ; ++is) + { + if (is_simplex_in_the_ambient_delaunay(*is)) + std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + else + { + std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + for(auto ii : *is) // CJTODO C++11 + perturb(ii); + } } } @@ -1018,12 +1038,17 @@ public: // CJTODO TEMP else { - std::cerr << "SUCCESS in solve_inconsistencies_using_alpha_TC(): " - << "the simplex " << saa.m_center_point_index << ", "; + std::cerr << "SUCCESS: " + << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << "was successfully added in the star #" - << saa.m_center_point_index << "\n"; + std::cerr << " added in star #" + << saa.m_center_point_index + << " (basis dim = " << tangent_basis.dimension() +# ifdef CGAL_TC_PROFILING + << " - " << t_one_fix.elapsed() << " s" +# endif + << ")\n"; //check_if_all_simplices_are_in_the_ambient_delaunay(); } #endif @@ -1136,7 +1161,7 @@ public: ++it_inc_simplex) { // Skip infinite cells - if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + if (is_infinite(*it_inc_simplex)) continue; Indexed_simplex c = *it_inc_simplex; @@ -1386,6 +1411,11 @@ private: }; #endif // CGAL_LINKED_WITH_TBB + bool is_infinite(Indexed_simplex const& s) const + { + return *s.rbegin() == std::numeric_limits::max(); + } + void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) @@ -1443,6 +1473,8 @@ private: local_tr_traits.point_weight_d_object(); typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object(); + typename Tr_traits::Compute_coordinate_d coord = + local_tr_traits.compute_coordinate_d_object(); //*************************************************** @@ -1488,6 +1520,12 @@ private: nn_it != ins_range.end() ; ++nn_it) { +#ifdef CGAL_ALPHA_TC + ++number_of_attempts_to_insert_points; + if (number_of_attempts_to_insert_points > MAX_NUM_INSERTED_POINTS) + break; +#endif + std::size_t neighbor_point_idx = nn_it->first; // ith point = p, which is already inserted @@ -1512,6 +1550,7 @@ private: #ifdef CGAL_TC_VERY_VERBOSE ++num_attempts_to_insert_points; #endif + Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); //Tr_vertex_handle vh = local_tr.insert(proj_pt); @@ -1592,7 +1631,10 @@ private: if (tsb.num_thickening_vectors() == 0) update_star__no_thickening_vectors(i); else + { update_star__with_thickening_vector(i); + //check_if_all_simplices_are_in_the_ambient_delaunay(); // CJTODO TEMP + } #else update_star__no_thickening_vectors(i); #endif @@ -2564,7 +2606,7 @@ next_face: const Incident_simplex &incident_simplex = *it_inc_simplex; // Don't check infinite cells - if (*incident_simplex.rbegin() == std::numeric_limits::max()) + if (is_infinite(incident_simplex)) continue; Indexed_simplex c = incident_simplex; @@ -3185,8 +3227,7 @@ next_face: bool inconsistencies_found = false; // Don't check infinite simplices - if (*incident_simplex.rbegin() - == std::numeric_limits::max()) + if (is_infinite(incident_simplex)) return false; Indexed_simplex simplex = incident_simplex; @@ -3697,8 +3738,7 @@ next_face: for ( ; it_simplex != it_simplex_end ; ++it_simplex) { // Don't export infinite cells - if (*it_simplex->first.rbegin() - == std::numeric_limits::max()) + if (is_infinite(it_simplex->first)) continue; const Indexed_simplex &c = it_simplex->first; @@ -3876,7 +3916,7 @@ public: for ( ; it_tri != it_tri_end ; ++it_tri) { // Don't export infinite cells - if (*it_tri->rbegin() == std::numeric_limits::max()) + if (is_infinite(*it_tri)) continue; os << 3 << " "; @@ -3947,7 +3987,7 @@ public: for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { // Don't check infinite cells - if (*it_inc_simplex->rbegin() == std::numeric_limits::max()) + if (is_infinite(*it_inc_simplex)) continue; Indexed_simplex c = *it_inc_simplex; diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index 8dc54e557a1..ec95a318317 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -248,6 +248,35 @@ namespace Tangential_complex_ { } } + 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(m_vectors.size() + m_thickening_vectors.size()); From 761d776252338dfdc979c8a959bf79adbf5b2c71 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 20 Jul 2015 17:09:41 +0200 Subject: [PATCH 242/269] Use the stars instead of the local triangulations for the export --- .../include/CGAL/Tangential_complex.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 596de6d390f..d080deef7cc 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1297,7 +1297,19 @@ public: Simplex_range stars_simplices; if (!p_complex) { - typename Tr_container::const_iterator it_tr = m_triangulations.begin(); + Stars_container::const_iterator it_star = m_stars.begin(); + Stars_container::const_iterator it_star_end = m_stars.end(); + // For each star: get the finite simplices + for ( ; it_star != it_star_end ; ++it_star) + { + for (Star::const_iterator it_s = it_star->begin(), + it_s_end = it_star->end() ; it_s != it_s_end ; ++it_s) + { + if (!is_infinite(*it_s)) + stars_simplices.insert(*it_s); + } + } + /*typename Tr_container::const_iterator it_tr = m_triangulations.begin(); typename Tr_container::const_iterator it_tr_end = m_triangulations.end(); // For each triangulation for ( ; it_tr != it_tr_end ; ++it_tr) @@ -1326,7 +1338,7 @@ public: stars_simplices.insert(simplex); } - } + }*/ p_simplices = &stars_simplices; } From 909dd40233dec7357fe879527f46713371d48b79 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 20 Jul 2015 17:13:31 +0200 Subject: [PATCH 243/269] Forgot the commit variable declaration (fix commit d5ef993) --- Tangential_complex/include/CGAL/Tangential_complex.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d080deef7cc..eba7bce121a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1526,6 +1526,18 @@ private: // and which contains all the // circumspheres of the star of "center_vertex" boost::optional squared_star_sphere_radius_plus_margin; + +#ifdef CGAL_ALPHA_TC + /*FT max_absolute_alpha = tsb.max_absolute_alpha(); + // "2*m_half_sparsity" because both points can be perturbed + FT max_sqdist_to_tangent_space = (max_absolute_alpha == FT(0) ? + FT(0) : CGAL::square(2*max_absolute_alpha + 2*m_half_sparsity));*/ + std::size_t number_of_attempts_to_insert_points = 0; + const std::size_t MAX_NUM_INSERTED_POINTS = + tsb.num_thickening_vectors() > 0 ? + static_cast(std::pow(4, /*tsb.dimension()*/m_intrinsic_dim)) + : std::numeric_limits::max(); +#endif // Insert points until we find a point which is outside "star shere" for (INS_iterator nn_it = ins_range.begin() ; From f67e8b63557d88951f6044219cb355232820b729 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 3 Dec 2015 14:47:49 +0100 Subject: [PATCH 244/269] Warning if sparsity = 0 + bugfixes --- Tangential_complex/include/CGAL/Tangential_complex.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index eba7bce121a..d430d3d1c3a 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -302,7 +302,10 @@ public: , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) #endif - { } + { + if (sparsity <= 0.) + std::cerr << "!Warning! Sparsity should be > 0\n"; + } /// Destructor ~Tangential_complex() @@ -517,7 +520,7 @@ public: # ifdef CGAL_TC_VERBOSE std::cerr << "Nothing to fix." << std::endl; # endif - return 0; + return TC_FIXED; } #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES @@ -682,7 +685,7 @@ public: << " * Number of inconsistent simplices in stars (incl. duplicates): " << num_inconsistent_simplices << std::endl << " * Percentage of inconsistencies: " - << 100 * num_inconsistent_simplices / num_simplices << "%" << std::endl + << 100. * num_inconsistent_simplices / num_simplices << "%" << std::endl << "==========================================================" << std::endl; } From e62b5513e1081a0428c5e838a3f8ec7e8dfcc7ea Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 3 Dec 2015 15:40:52 +0100 Subject: [PATCH 245/269] Macros: TC_INPUT_STRIDES + CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY --- .../Tangential_complex/benchmark_tc.cpp | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index b90dce674e4..72e599a42ff 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -40,6 +41,8 @@ typedef CGAL::Tangential_complex< CGAL::Parallel_tag> TC; //#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 #ifdef JUST_BENCHMARK_SPATIAL_SEARCH std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); @@ -186,7 +189,7 @@ bool export_to_off( } else { -#ifdef CGAL_ALPHA_TC +/*#ifdef CGAL_ALPHA_TC TC::Simplicial_complex complex; tc.export_TC(complex, false); tc.export_to_off( @@ -194,13 +197,13 @@ bool export_to_off( p_simpl_to_color_in_red, p_simpl_to_color_in_green, p_simpl_to_color_in_blue); -#else +#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); -#endif +//#endif } return true; } @@ -335,8 +338,10 @@ void make_tc(std::vector &points, return;*/ // CJTODO TEMP =========================== +#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(); @@ -728,7 +733,15 @@ int main() if (!points.empty()) { - make_tc(points, intrinsic_dim, sparsity, +#if defined(TC_INPUT_STRIDES) && TC_INPUT_STRIDES > 1 + auto p = points | boost::adaptors::strided(TC_INPUT_STRIDES); + std::vector points(p.begin(), p.end()); + std::cerr << "****************************************\n" + << "WARNING: taking 1 point every " << TC_INPUT_STRIDES + << " points.\n" + << "****************************************\n"; +#endif + make_tc(points, intrinsic_dim, sparsity, // strided: CJTODO TEMP perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', time_limit_for_perturb, input.c_str()); @@ -757,5 +770,6 @@ int main() std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found." << std::endl; } + system("pause"); return 0; } From 7ea9538a4e1df9844aaed4d59998b04e7ca8429c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 3 Dec 2015 15:44:50 +0100 Subject: [PATCH 246/269] Macro: TC_NO_EXPORT, to disable export into files --- .../benchmark/Tangential_complex/benchmark_tc.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 72e599a42ff..299d1a0458a 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -43,6 +43,7 @@ typedef CGAL::Tangential_complex< //#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 #ifdef JUST_BENCHMARK_SPATIAL_SEARCH std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); @@ -169,6 +170,9 @@ bool export_to_off( std::set > const *p_simpl_to_color_in_green = NULL, std::set > const *p_simpl_to_color_in_blue = NULL) { +#ifdef TC_NO_EXPORT + return true; +#endif if (tc.intrinsic_dimension() <= 3) { std::stringstream output_filename; @@ -181,11 +185,13 @@ bool export_to_off( 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); +#endif } else { @@ -734,7 +740,7 @@ int main() if (!points.empty()) { #if defined(TC_INPUT_STRIDES) && TC_INPUT_STRIDES > 1 - auto p = points | boost::adaptors::strided(TC_INPUT_STRIDES); + auto p = points | boost::adaptors::strided(TC_INPUT_STRIDES); // CJTODO C++11 (auto) std::vector points(p.begin(), p.end()); std::cerr << "****************************************\n" << "WARNING: taking 1 point every " << TC_INPUT_STRIDES From 307e195d3c5832a3d4bdabd2d29370b54db82b21 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 9 Dec 2015 10:26:33 +0100 Subject: [PATCH 247/269] Useless line (cherry picked from commit f07e7181b57723cae26ea1447a0de9ffac408e6e) --- .../include/CGAL/Regular_triangulation_euclidean_traits.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h index e8b6b7796e0..ec701ee2713 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h +++ b/Triangulation/include/CGAL/Regular_triangulation_euclidean_traits.h @@ -209,7 +209,6 @@ public: const Weighted_point & p, const int i) const { Point_drop_weight_d pdw = m_kernel.point_drop_weight_d_object(); - m_kernel.compute_coordinate_d_object()(pdw(p), i); return m_kernel.compute_coordinate_d_object()(pdw(p), i); } }; From 2ea1c1fc5293f86c42a028252b30ee551525676d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 10 Dec 2015 16:44:30 +0100 Subject: [PATCH 248/269] Small bugfixes --- .../include/CGAL/Tangential_complex.h | 198 ++++++++++-------- 1 file changed, 106 insertions(+), 92 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index d430d3d1c3a..6e0a9280507 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -98,7 +98,7 @@ private: /// The class Tangential_complex represents a tangential complex template < - typename Kernel, // ambiant dimension + typename Kernel_, // ambiant dimension typename DimensionTag, // intrinsic dimension typename Concurrency_tag = CGAL::Parallel_tag, #ifdef CGAL_ALPHA_TC @@ -106,9 +106,7 @@ template < // => we need to force typename Tr = Regular_triangulation < - Regular_triangulation_euclidean_traits< - Epick_d >, - + Epick_d, Triangulation_data_structure < typename Regular_triangulation_euclidean_traits< @@ -122,9 +120,7 @@ template < #else typename Tr = Regular_triangulation < - Regular_triangulation_euclidean_traits< - Epick_d >, - + Epick_d, Triangulation_data_structure < typename Regular_triangulation_euclidean_traits< @@ -139,10 +135,11 @@ template < > class Tangential_complex { - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_d Point; - typedef typename Kernel::Weighted_point_d Weighted_point; - typedef typename Kernel::Vector_d Vector; + typedef Kernel_ K; + typedef typename K::FT FT; + typedef typename K::Point_d Point; + typedef typename K::Weighted_point_d Weighted_point; + typedef typename K::Vector_d Vector; typedef Tr Triangulation; typedef typename Triangulation::Geom_traits Tr_traits; @@ -152,8 +149,8 @@ class Tangential_complex typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename Tr_traits::Vector_d Tr_vector; - typedef Basis Tangent_space_basis; - typedef Basis Orthogonal_space_basis; + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; typedef std::vector Points; #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) @@ -172,7 +169,7 @@ class Tangential_complex #endif typedef std::vector Translations_for_perturb; - typedef Point_cloud_data_structure Points_ds; + typedef Point_cloud_data_structure Points_ds; typedef typename Points_ds::KNS_range KNS_range; typedef typename Points_ds::KNS_iterator KNS_iterator; typedef typename Points_ds::INS_range INS_range; @@ -276,7 +273,7 @@ public: #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM InputIterator first_for_tse, InputIterator last_for_tse, #endif - const Kernel &k = Kernel() + const K &k = K() ) : m_k(k), m_intrinsic_dim(intrinsic_dimension), @@ -414,8 +411,7 @@ public: void estimate_intrinsic_dimension() const { // Kernel functors - typename Kernel::Compute_coordinate_d coord = - m_k.compute_coordinate_d_object(); + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); std::vector sum_eigen_values(m_ambient_dim, FT(0)); std::size_t num_points_for_pca = static_cast( @@ -589,14 +585,12 @@ public: << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" << std::endl - << std::endl << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " << stats_after.first << std::endl << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << std::endl - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%" + << stats_after.second + << " (" << 100. * stats_after.second / stats_after.first << "%)" << std::endl << "==========================================================" << std::endl; @@ -771,9 +765,9 @@ private: std::size_t fill_pqueues_for_alpha_tc(std::size_t i, PQueues &pqueues) { // Kernel/traits functors - typename Kernel::Difference_of_points_d k_diff_points = + typename K::Difference_of_points_d k_diff_points = m_k.difference_of_points_d_object(); - typename Kernel::Squared_length_d k_sqlen = + typename K::Squared_length_d k_sqlen = m_k.squared_length_d_object(); typename Tr_traits::Construct_weighted_point_d constr_wp = m_triangulations[0].tr().geom_traits().construct_weighted_point_d_object(); @@ -955,9 +949,16 @@ public: // Update the alpha+/- values tangent_basis.update_alpha_values_of_thickening_vectors( saa.m_thickening_vector, m_k); - + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_recomputation; +#endif // Recompute triangulation & star compute_tangent_triangulation(saa.m_center_point_index); +#ifdef CGAL_TC_PROFILING + double recomp_timing = t_recomputation.elapsed(); +#endif + #ifdef CGAL_TC_PERFORM_EXTRA_CHECKS if (!is_simplex_in_star(saa.m_center_point_index, saa.m_simplex)) @@ -967,11 +968,12 @@ public: << "simplex " << saa.m_center_point_index << ", "; std::copy(saa.m_simplex.begin(), saa.m_simplex.end(), std::ostream_iterator(std::cerr, ", ")); - std::cerr << " not added in star #" + std::cerr << " not added in star #" << saa.m_center_point_index << " (basis dim = " << tangent_basis.dimension() # ifdef CGAL_TC_PROFILING - << " - " << t_one_fix.elapsed() << " s" + << " - " << t_one_fix.elapsed() << " s [recomputation = " + << recomp_timing << " s]" # endif << ")\n"; @@ -1049,7 +1051,8 @@ public: << saa.m_center_point_index << " (basis dim = " << tangent_basis.dimension() # ifdef CGAL_TC_PROFILING - << " - " << t_one_fix.elapsed() << " s" + << " - " << t_one_fix.elapsed() << " s [recomputation = " + << recomp_timing << " s]" # endif << ")\n"; //check_if_all_simplices_are_in_the_ambient_delaunay(); @@ -1197,7 +1200,7 @@ public: // Then save its simplices into "amb_dt_simplices" //------------------------------------------------------------------------- - typedef Regular_triangulation_euclidean_traits RT_Traits; + typedef Regular_triangulation_euclidean_traits RT_Traits; typedef Regular_triangulation< RT_Traits, Triangulation_data_structure< @@ -1241,15 +1244,15 @@ public: if (m_points.empty()) return true; - typedef Regular_triangulation_euclidean_traits RT_Traits; + typedef Regular_triangulation_euclidean_traits RT_Traits; typedef Regular_triangulation< RT_Traits, Triangulation_data_structure< typename RT_Traits::Dimension, Triangulation_vertex - > > RT; - typedef typename RT::Vertex_handle RT_VH; - typedef typename RT::Finite_full_cell_const_iterator FFC_it; + > > RT; + typedef typename RT::Vertex_handle RT_VH; + typedef typename RT::Finite_full_cell_const_iterator FFC_it; //------------------------------------------------------------------------- // Build the ambient Delaunay triangulation @@ -1343,6 +1346,8 @@ public: } }*/ + + p_simplices = &stars_simplices; } else @@ -1384,19 +1389,19 @@ private: class Compare_distance_to_ref_point { public: - Compare_distance_to_ref_point(Point const& ref, Kernel const& k) + Compare_distance_to_ref_point(Point const& ref, K const& k) : m_ref(ref), m_k(k) {} bool operator()(Point const& p1, Point const& p2) { - typename Kernel::Squared_distance_d sqdist = + typename K::Squared_distance_d sqdist = m_k.squared_distance_d_object(); return sqdist(p1, m_ref) < sqdist(p2, m_ref); } private: Point const& m_ref; - Kernel const& m_k; + K const& m_k; }; #ifdef CGAL_LINKED_WITH_TBB @@ -1473,6 +1478,9 @@ private: } #endif +#if defined(CGAL_TC_PROFILING) && defined(CGAL_TC_VERY_VERBOSE) + Wall_clock_timer t; +#endif int tangent_space_dim = tangent_basis_dim(i); Triangulation &local_tr = m_triangulations[i].construct_triangulation(tangent_space_dim); @@ -1480,16 +1488,13 @@ private: Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); // Kernel functor & objects - typename Kernel::Squared_distance_d k_sqdist = - m_k.squared_distance_d_object(); + typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); // Triangulation's traits functor & objects typename Tr_traits::Point_weight_d point_weight = local_tr_traits.point_weight_d_object(); typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object(); - typename Tr_traits::Compute_coordinate_d coord = - local_tr_traits.compute_coordinate_d_object(); //*************************************************** @@ -1649,7 +1654,12 @@ private: } } } - + +#if defined(CGAL_TC_PROFILING) && defined(CGAL_TC_VERY_VERBOSE) + std::cerr << " - triangulation construction: " << t.elapsed() << " s.\n"; + t.reset(); +#endif + #ifdef CGAL_TC_VERY_VERBOSE std::cerr << "Inserted " << num_inserted_points << " points / " << num_attempts_to_insert_points << " attemps to compute the star\n"; @@ -1665,6 +1675,10 @@ private: #else update_star__no_thickening_vectors(i); #endif + +#if defined(CGAL_TC_PROFILING) && defined(CGAL_TC_VERY_VERBOSE) + std::cerr << " - update_star: " << t.elapsed() << " s.\n"; +#endif } // Updates m_stars[i] directly from m_triangulations[i] @@ -1917,8 +1931,8 @@ next_face: Vector t(2, &tt[0], &tt[2]); // Normalize t1 and t2 - typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_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(); Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); @@ -1937,8 +1951,8 @@ next_face: Vector t2(3, &tt2[0], &tt2[3]); // Normalize t1 and t2 - typename Kernel::Squared_length_d sqlen = m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_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(); Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); @@ -1974,19 +1988,19 @@ next_face: std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); // Kernel functors - typename Kernel::Construct_vector_d constr_vec = + typename K::Construct_vector_d constr_vec = m_k.construct_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - typename Kernel::Squared_length_d sqlen = + typename K::Squared_length_d sqlen = m_k.squared_length_d_object(); - typename Kernel::Scaled_vector_d scaled_vec = + typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Scalar_product_d scalar_pdct = + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Difference_of_vectors_d diff_vec = + typename K::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object(); - //typename Kernel::Translated_point_d transl = + //typename K::Translated_point_d transl = // m_k.translated_point_d_object(); #ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM @@ -2008,8 +2022,8 @@ next_face: for (int i = 0 ; i < m_ambient_dim ; ++i) { //const Point p = transl( - // m_points[nn_it->first], m_translations[nn_it->first]); - mat_points(j, i) = CGAL::to_double(coord(m_points[nn_it->first], i)); + // points_for_pca[nn_it->first], m_translations[nn_it->first]); + mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i)); #ifdef CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE mat_points(j, i) += m_random_generator.get_double( -0.5*m_half_sparsity, 0.5*m_half_sparsity); @@ -2143,7 +2157,7 @@ next_face: Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) const { - typename Kernel::Construct_weighted_point_d k_constr_wp = + typename K::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); Weighted_point wp = k_constr_wp( @@ -2161,9 +2175,9 @@ next_face: const Tangent_space_basis &tsb, const Tr_traits &tr_traits) const { - typename Kernel::Translated_point_d k_transl = + typename K::Translated_point_d k_transl = m_k.translated_point_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = + typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); typename Tr_traits::Compute_coordinate_d coord = tr_traits.compute_coordinate_d_object(); @@ -2189,9 +2203,9 @@ next_face: Tr_bare_point project_point(const Point &p, const Tangent_space_basis &tsb) const { - typename Kernel::Scalar_product_d scalar_pdct = + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Difference_of_points_d diff_points = + typename K::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); Vector v = diff_points(p, compute_perturbed_point(tsb.origin())); @@ -2224,9 +2238,9 @@ next_face: const Tangent_space_basis &tsb, const Tr_traits &tr_traits) const { - typename Kernel::Point_drop_weight_d k_drop_w = + typename K::Point_drop_weight_d k_drop_w = m_k.point_drop_weight_d_object(); - typename Kernel::Point_weight_d k_point_weight = + typename K::Point_weight_d k_point_weight = m_k.point_weight_d_object(); return project_point_and_compute_weight( k_drop_w(wp), k_point_weight(wp), tsb, tr_traits); @@ -2237,13 +2251,13 @@ next_face: const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); - typename Kernel::Scalar_product_d scalar_pdct = + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Difference_of_points_d diff_points = + typename K::Difference_of_points_d diff_points = m_k.difference_of_points_d_object(); - typename Kernel::Compute_coordinate_d coord = + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - typename Kernel::Construct_cartesian_const_iterator_d ccci = + typename K::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); Point origin = compute_perturbed_point(tsb.origin()); @@ -2333,11 +2347,11 @@ next_face: double compute_simplex_fatness(IndexRange const& simplex) const { // Kernel functors - typename Kernel::Compute_coordinate_d coord = + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); - typename Kernel::Squared_distance_d sqdist = + typename K::Squared_distance_d sqdist = m_k.squared_distance_d_object(); - typename Kernel::Difference_of_points_d diff_pts = + typename K::Difference_of_points_d diff_pts = m_k.difference_of_points_d_object(); typename Tr_traits::Difference_of_points_d tr_diff_pts = @@ -2551,7 +2565,7 @@ next_face: // Perturb the position? #ifdef CGAL_TC_PERTURB_POSITION # ifdef CGAL_TC_PERTURB_POSITION_GLOBAL - typename Kernel::Point_to_vector_d k_pt_to_vec = + typename K::Point_to_vector_d k_pt_to_vec = m_k.point_to_vector_d_object(); CGAL::Random_points_in_ball_d tr_point_in_ball_generator( @@ -2572,11 +2586,11 @@ next_face: m_triangulations[point_idx].tr().geom_traits(); typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object(); - typename Kernel::Translated_point_d k_transl = + typename K::Translated_point_d k_transl = m_k.translated_point_d_object(); - typename Kernel::Construct_vector_d k_constr_vec = + typename K::Construct_vector_d k_constr_vec = m_k.construct_vector_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = + typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); CGAL::Random_points_in_ball_d @@ -2832,7 +2846,7 @@ next_face: const int N = (m_intrinsic_dim == 1 ? 2 : 1); // Kernel functors - typename Kernel::Compute_coordinate_d coord = + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); int num_coords = min(m_ambient_dim, 3); @@ -2921,19 +2935,19 @@ next_face: CGAL_assertion(std::find(m_stars[q_idx].begin(), m_stars[q_idx].end(), inc_s_minus_q) == m_stars[q_idx].end()); - typename Kernel::Point_drop_weight_d k_drop_w = + typename K::Point_drop_weight_d k_drop_w = m_k.point_drop_weight_d_object(); - typename Kernel::Translated_point_d k_transl = + typename K::Translated_point_d k_transl = m_k.translated_point_d_object(); - typename Kernel::Squared_distance_d k_sqdist = + typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); - typename Kernel::Difference_of_points_d k_diff_pts = + typename K::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - typename Kernel::Scalar_product_d k_scalar_pdct = + typename K::Scalar_product_d k_scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Construct_weighted_point_d k_constr_wp = + typename K::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object(); - typename Kernel::Power_distance_d k_power_dist = + typename K::Power_distance_d k_power_dist = m_k.power_distance_d_object(); const Tr_traits &q_tr_traits = m_triangulations[q_idx].tr().geom_traits(); @@ -3100,9 +3114,9 @@ next_face: // If co-intrinsic dimension = 1, let's compare normals /*if (m_ambient_dim - m_intrinsic_dim == 1) { - typename Kernel::Scaled_vector_d k_scaled_vec = + typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Squared_length_d k_sqlen = + typename K::Squared_length_d k_sqlen = m_k.squared_length_d_object(); Vector pq = k_diff_pts( compute_perturbed_point(q_idx), compute_perturbed_point(p_idx)); @@ -3189,8 +3203,8 @@ next_face: // CJTODO TEMP ==================== /*{ - typename Kernel::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Point_weight_d k_weight = m_k.point_weight_d_object(); + typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); + typename K::Point_weight_d k_weight = m_k.point_weight_d_object(); Weighted_point C = k_constr_wp( k_transl(k_drop_w(global_Cp), scaled_vec(k_diff_pts(k_drop_w(global_Cq), k_drop_w(global_Cp)), min_a)), k_sqdist(k_transl(k_drop_w(global_Cp), scaled_vec(k_diff_pts(k_drop_w(global_Cq), k_drop_w(global_Cp)), min_a)), pt_p)); @@ -3284,13 +3298,13 @@ next_face: // CJTODO TEMP /*else if (m_ambient_dim - m_intrinsic_dim == 1) { - typename Kernel::Difference_of_points_d k_diff_pts = + typename K::Difference_of_points_d k_diff_pts = m_k.difference_of_points_d_object(); - typename Kernel::Scaled_vector_d k_scaled_vec = + typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - typename Kernel::Squared_length_d k_sqlen = + typename K::Squared_length_d k_sqlen = m_k.squared_length_d_object(); - typename Kernel::Scalar_product_d k_scalar_pdct = + typename K::Scalar_product_d k_scalar_pdct = m_k.scalar_product_d_object(); Vector pq = k_diff_pts( compute_perturbed_point(*it_point_idx), compute_perturbed_point(tr_index)); @@ -3336,7 +3350,7 @@ next_face: typename Tr_traits::Compute_coordinate_d coord = tr_traits.compute_coordinate_d_object(); - typename Kernel::Compute_coordinate_d k_coord = + typename K::Compute_coordinate_d k_coord = m_k.compute_coordinate_d_object(); std::size_t card_P = P.size(); @@ -3514,9 +3528,9 @@ next_face: // Fv: Voronoi k-face // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) - typename Kernel::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); - typename Kernel::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); + typename K::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object(); + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); Point center_pt = compute_perturbed_point(center_pt_index); int const ambient_dim = m_k.point_dimension_d_object()(center_pt); @@ -4057,7 +4071,7 @@ public: } private: - const Kernel m_k; + const K m_k; const int m_intrinsic_dim; const double m_half_sparsity; const double m_sq_half_sparsity; From f00c925ccc66e2f6cb19fb692f2d849c4980304f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 19 Jan 2016 15:37:07 +0100 Subject: [PATCH 249/269] Test a kind of "Mesh_d" algorithm - first draft --- .../Tangential_complex/CMakeLists.txt | 4 + .../Tangential_complex/benchmark_mesh_d.cpp | 412 ++++++++++++++++++ .../Tangential_complex/benchmark_script.txt | 207 +++++---- .../Tangential_complex/Simplicial_complex.h | 16 +- .../include/CGAL/Tangential_complex/config.h | 12 +- .../CGAL/Tangential_complex/utilities.h | 9 - .../Tangential_complex/testing_utilities.h | 70 ++- 7 files changed, 615 insertions(+), 115 deletions(-) create mode 100644 Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp diff --git a/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt index 7155f246c2b..56b513551fc 100644 --- a/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt +++ b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt @@ -66,6 +66,10 @@ if ( CGAL_FOUND ) 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.") diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp new file mode 100644 index 00000000000..8ff7c0d0d67 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -0,0 +1,412 @@ +//#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 +#include +#include +#include +#include + +#include "../../test/Tangential_complex/testing_utilities.h" + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif + +using namespace CGAL::Tangential_complex_; + +const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt"; + +typedef CGAL::Epick_d Kernel; +typedef Kernel::FT FT; +typedef Kernel::Point_d Point; +typedef CGAL::Mesh_d< + Kernel, CGAL::Dynamic_dimension_tag, + 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 + + +template +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 &points, + int intrinsic_dim, + bool sparsify = true, + double sparsity = 0.01, + const char *input_name = "mesh") +{ + Kernel k; + + //=========================================================================== + // 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 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() << std::endl; + } + + //=========================================================================== + // 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); +#else + Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim, k); +#endif + + double init_time = t.elapsed(); t.reset(); + + std::vector > 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 > wrong_dim_simplices; + std::set > wrong_number_of_cofaces_simplices; + std::set > unconnected_stars_simplices; + bool is_pure_pseudomanifold = mesh.complex().is_pure_pseudomanifold( + intrinsic_dim, mesh.number_of_vertices(), 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(); + + //=========================================================================== + // Display info + //=========================================================================== + + std::cerr << std::endl + << "================================================" << std::endl + << "Number of vertices: " << mesh.number_of_vertices() << std::endl + //<< "Pure pseudomanifold: " << (is_pure_pseudomanifold ? "YES" : "NO") << std::endl + << "Computation times (seconds): " << std::endl + << " * Mesh: " << init_time + computation_time << std::endl + << " - Init + kd-tree = " << init_time << std::endl + << " - Mesh computation = " << computation_time << std::endl + //<< " * Export to OFF : " << export_before_time << std::endl + << "================================================" << std::endl + << std::endl; +} + +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(time(NULL)); + CGAL::default_random = CGAL::Random(seed); + std::cerr << "Random seed = " << seed << std::endl; + + 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." << std::endl; + 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 << std::endl << std::endl; + std::cerr << "*****************************************" << std::endl; + std::cerr << "******* " << line << std::endl; + std::cerr << "*****************************************" << std::endl; + 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 << std::endl << "Mesh #" << i << "..." << std::endl; + +#ifdef CGAL_MESH_D_PROFILING + Wall_clock_timer t_gen; +#endif + + std::vector points; + + if (input == "generate_moment_curve") + { + points = generate_points_on_moment_curve( + num_points, ambient_dim, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else if (input == "generate_plane") + { + points = generate_points_on_plane( + num_points, intrinsic_dim, ambient_dim); + } + else if (input == "generate_sphere_d") + { + points = generate_points_on_sphere_d( + 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( + 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( + num_points, + std::atof(param1.c_str())); + } + else if (input == "generate_torus_3D") + { + points = generate_points_on_torus_3D( + 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( + 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( + 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( + 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( + num_points, + std::atof(param1.c_str()), std::atof(param2.c_str())); + } + else + { + load_points_from_file( + input, std::back_inserter(points)/*, 600*/); + } + +#ifdef CGAL_MESH_D_PROFILING + std::cerr << "Point set generated/loaded in " << t_gen.elapsed() + << " seconds." << std::endl; +#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 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." << std::endl; + std::cerr << std::endl << "---------------------------------" + << std::endl << std::endl; + } + else + { + std::cerr << "Mesh #" << i++ << ": no points loaded." << std::endl; + } + } + } + } + script_file.seekg(0); + script_file.clear(); + } + + script_file.close(); + } + // Or not script? + else + { + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found." << std::endl; + } + + system("pause"); + return 0; +} diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt index 7e243e29c03..556d18dbb2a 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_script.txt @@ -1,109 +1,136 @@ #--------------------------------------------------------------------------------------------------------------------------------------------------------- -# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS +# 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 1 - 50 2 1 0.005 N Y N 3 1 #OK -#generate_torus_d N - - 15 2 1 0.05 N Y N 10 1 -#generate_sphere_d 0.302 3 - 50 3 2 0.005 N Y N 60 1 #OK -#generate_sphere_d 0.302 2 - 300 2 1 0.005 N Y N 60 1 -#generate_torus_3D 2 1 N 200 3 2 0.05 N Y N 600 1 #OK => tetraedra only -#data/fandisk.txt - - - 0 3 2 0.005 Y Y N 5 1 -generate_torus_d N 1 - 50 4 2 0.05 N Y N 3 1 #NOT OK: various errors -#generate_torus_d Y 1 - 2500 4 2 0.05 N Y N 3 1 #NOT OK -#generate_torus_d N - - 30 6 3 0.05 N Y N 300 1 -#generate_moment_curve 0 1 - 10 3 1 0.005 N Y N 60 1 -#generate_two_spheres_d 3 4 - 500 3 2 0.05 N Y N 10 1 #OK -#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N Y N 60 1 +#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 0.005 N N N 60 1 -#generate_sphere_d 0.304 0 - 100 3 2 0.05 N N N 60 1 -#generate_sphere_d 3 0 - 100 4 3 0.05 N N N 60 1 -#generate_sphere_d 3 0 - 1000 5 4 0.05 N N N 60 1 -#generate_two_spheres_d 3 4 - 1000 3 2 0.05 N N N 10 1 -#generate_two_spheres_d 3 10 - 1000 4 3 0.05 N N N 10 1 -#generate_two_spheres_d 3 10 - 2000 5 4 0.05 N N N 10 1 -#generate_3sphere_and_circle_d 3 - - 100000 5 3 0.05 N N N 7000 1 -#generate_plane - - - 100 4 3 0.005 N N N 3000 1 -#generate_plane - - - 10 5 4 0.005 N N N 3000 1 -#generate_klein_bottle_4D 40 15 - 500 4 2 0.2 N N N 60 1 -#generate_klein_bottle_4D 40 15 - 2000 4 2 0.2 N N N 60 1 -#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N N N 60 1 #Takes forever -#generate_torus_3D 2 1 Y 150 3 2 0.05 N N N 600 1 -#generate_torus_3D 2 1 N 100000 3 2 0.55 N N N 600 1 -#generate_torus_d N - - 18 2 1 0.01 N N N 30 1 -#generate_torus_d N - - 50000 2 1 0.7 N N N 30 1 -#generate_torus_d Y - - 2 2 1 0 N N N 30 1 -#generate_torus_d Y - - 15 4 2 0.05 N N N 30 1 -#generate_torus_d N 0 - 150 4 2 0.05 N N N 10 1 -#generate_torus_d N - - 20000 4 2 1.0 N N N 30 1 -#generate_torus_d Y 0 - 5000 6 3 0.05 N N N 300 1 -#generate_torus_d N - - 20000 6 3 0.05 N N N 60 1 -#generate_torus_d N - - 100000 6 3 0.05 N N N 3000 1 -#generate_torus_d N - - 1000000 6 3 0.3 N N N 3000 1 -#generate_torus_d Y - - 1000 8 4 0.05 N N N 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.1 N N N 60 1 +#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 0 Y N N 600 1 -#data/buddha_100kv.txt - - - 0 3 2 0 N Y N 120 1 -#generate_torus_d N - - 10000 30 15 0 Y N N 3600 1 -#generate_torus_d N - - 100000 12 6 0 Y N N 3600 1 -#data/SO3_50000.txt - - - 0 9 3 0 Y N N 60 1 -#data/Cy8.txt - - - 0 24 2 0 N Y N 60 1 -#generate_sphere_d 0.5 - - 10000 2 1 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 3 2 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 4 3 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 5 4 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 6 5 0 N N Y 60 1 -#generate_sphere_d 0.5 - - 10000 7 6 0 N N Y 60 1 +#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 0.05 N Y N 60 1 -#generate_sphere_d 3 - - 70 3 2 0.05 N Y N 60 1 -#generate_sphere_d 3 - - 1000 3 2 0.05 N Y N 60 1 -#generate_sphere_d 3 - - 70 4 3 0.05 N Y N 60 1 -#generate_sphere_d 3 - - 70 5 4 0.05 N Y N 60 1 -#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 N Y N 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.7 N Y N 60 1 -#generate_moment_curve 0 1 - 30 3 1 0.005 N Y N 60 1 +#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 0.05 Y Y N 60 1 -#data/SO3_10000.txt - - - 0 9 3 0.05 Y N N 60 1 -#data/cube3D_eps_0.1.txt - - - 0 3 2 0.05 N Y N 3000 1 -#data/cube4D_eps_0.1.txt - - - 0 4 3 0.05 N Y N 3000 1 -#data/cube5D_eps_0.1.txt - - - 0 5 4 0.05 N Y N 3000 1 -#data/Cy8.txt - - - 0 24 2 0.1 N Y N 60 1 -#data/Kl.txt - - - 0 5 2 0.05 N Y N 60 1 -#data/S3.txt - - - 0 4 3 0.05 N Y N 60 1 +#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 0.005 N Y N 120 1 -#data/fandisk.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/fertility.txt - - - 0 3 2 0.4 N Y N 60 1 -#data/bunny.txt - - - 0 3 2 0.5 N Y N 60 1 -#data/blob.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/3holes.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/785_hand_2500v.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/785_hand_50kv.txt - - - 0 3 2 0.01 N Y N 60 1 -#data/bumpy_sphere.txt - - - 0 3 2 0.01 N Y N 60 1 +#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 0.05 N Y N 3000 1 -#generate_sphere_d 3 - - 30000 2 1 0.005 N Y N 3000 1 -#generate_sphere_d 3 - - 30000 3 2 0.005 N Y N 3000 1 -#generate_sphere_d 3 - - 30000 4 3 0.05 N Y N 3000 1 -#generate_sphere_d 3 0 - 3000 3 2 0.005 N Y N 60 1 -#generate_sphere_d 3 4 - 3000 3 2 0.005 N Y N 60 1 -#generate_sphere_d 3 7 - 3000 3 2 0.005 N Y N 60 1 -#generate_plane - - - 30000 3 2 0.005 N Y N 3000 1 -#generate_moment_curve 0 1 - 30000 6 1 0.005 N Y N 60 1 -#generate_klein_bottle_4D 4 3 - 1000 4 2 0.1 N Y N 60 1 -#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 N Y N 60 1 -#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 N Y N 60 1 #Takes forever +#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 0.1 N Y N 100 1 \ No newline at end of file +#data/fertility.txt - - - 0 3 2 Y 0.1 N Y N 100 1 \ No newline at end of file diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index ecdea36ce3a..199691c0a64 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -244,7 +244,7 @@ public: 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_wrong_number_of_cofaces = NULL) const { typedef std::set K_1_face; typedef std::map Cofaces_map; @@ -333,7 +333,7 @@ public: std::size_t *p_num_unconnected_stars = NULL, Simplex_range *p_wrong_dim_simplices = NULL, Simplex_range *p_wrong_number_of_cofaces_simplices = NULL, - Simplex_range *p_unconnected_stars_simplices = NULL) + Simplex_range *p_unconnected_stars_simplices = NULL) const { // If simplex_dim == 1, we do not need to check if stars are connected if (simplex_dim == 1) @@ -382,7 +382,7 @@ public: } } - // Now, for each star, with have a vector of its d-simplices + // 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 @@ -450,9 +450,13 @@ public: } // What is left is to check the connexity - std::vector components(boost::num_vertices(adj_graph)); - bool is_connected = - (boost::connected_components(adj_graph, &components[0]) == 1); + bool is_connected = true; + if (boost::num_vertices(adj_graph) > 0) + { + std::vector components(boost::num_vertices(adj_graph)); + is_connected = + (boost::connected_components(adj_graph, &components[0]) == 1); + } if (!is_connected) { diff --git a/Tangential_complex/include/CGAL/Tangential_complex/config.h b/Tangential_complex/include/CGAL/Tangential_complex/config.h index 3f01cde07a4..f9def39e883 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/config.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/config.h @@ -32,17 +32,16 @@ //=========================== Alpha-TC or not? ================================ -#define CGAL_ALPHA_TC +//#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 -//#define USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +//#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 @@ -55,6 +54,8 @@ #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 @@ -76,5 +77,6 @@ // 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 diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index ec95a318317..e1472ae8d95 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -24,8 +24,6 @@ #include #include #include -#include -#include #include #include @@ -35,13 +33,6 @@ #include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) -// choose exact integral type for QP solver -// (Gmpzf is not thread-safe) -#include -typedef CGAL::MP_Float ET; -//#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 - - namespace CGAL { namespace Tangential_complex_ { diff --git a/Tangential_complex/test/Tangential_complex/testing_utilities.h b/Tangential_complex/test/Tangential_complex/testing_utilities.h index 810b5063fcd..1c70713f7d8 100644 --- a/Tangential_complex/test/Tangential_complex/testing_utilities.h +++ b/Tangential_complex/test/Tangential_complex/testing_utilities.h @@ -32,8 +32,12 @@ #include #include #include +#include +#include +#include #include +#include // Actually, this is very slow because the "m_points_ds->insert" // cleans the tree, which is thus built at each query_ANN call @@ -206,11 +210,52 @@ sparsify_point_set( return output; } -template -bool load_points_from_file( - const std::string &filename, OutputIterator points, +template< + typename Kernel, typename OutputIteratorPoints> + bool load_points_from_file( + const std::string &filename, + OutputIteratorPoints points, std::size_t only_first_n_points = std::numeric_limits::max()) { + typedef typename Kernel::Point_d Point; + + std::ifstream in(filename); + if (!in.is_open()) + { + std::cerr << "Could not open '" << filename << "'" << std::endl; + return false; + } + + Point p; + int num_ppints; + in >> num_ppints; + + std::size_t i = 0; + while (i < only_first_n_points && in >> p) + { + *points++ = p; + ++i; + } + +#ifdef CGAL_TC_VERBOSE + std::cerr << "'" << filename << "' loaded." << std::endl; +#endif + + return true; + } + +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::max()) +{ + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + std::ifstream in(filename); if (!in.is_open()) { @@ -218,14 +263,29 @@ bool load_points_from_file( return false; } + bool contains_tangent_spaces = + (filename.substr(filename.size() - 3) == "pwt"); + + Kernel k; Point p; - int dim_from_file; - in >> dim_from_file; + 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; } From 4016d0d247c4018256552ecfa3016a0c0b6b3afa Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 19 Jan 2016 15:38:44 +0100 Subject: [PATCH 250/269] operator>> for Vector_d --- .../CGAL/IO/Triangulation_off_ostream.h | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h index dc795045782..d7c8a6ce38e 100644 --- a/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h +++ b/Triangulation/include/CGAL/IO/Triangulation_off_ostream.h @@ -173,6 +173,32 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d & wp) return is; } +// TODO: test if the stream is binary or text? +template +std::istream & +operator>>(std::istream &is, typename Wrap::Vector_d & v) +{ + typedef typename Wrap::Vector_d V; + typedef typename K::FT FT; + std::vector 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, From 018ee665578814561f28daedac6a59c7e291908a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 19 Jan 2016 15:54:31 +0100 Subject: [PATCH 251/269] Add alpha TC + point set protection + another test to solve inconsistencies Test: see check_and_solve_inconsistencies_by_filtering_simplices_out() --- .../Tangential_complex/benchmark_tc.cpp | 108 ++- .../include/CGAL/Tangential_complex.h | 712 +++++++++++++----- 2 files changed, 599 insertions(+), 221 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 299d1a0458a..5b8f79e1369 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -6,6 +6,9 @@ # define TBB_USE_THREADING_TOOL #endif + +#include // CJTODO TEST + #include #include #include @@ -36,14 +39,17 @@ const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt"; typedef CGAL::Epick_d 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; +//#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 TC_INPUT_STRIDES 10 // only take one point every TC_INPUT_STRIDES points +//#define TC_NO_EXPORT #ifdef JUST_BENCHMARK_SPATIAL_SEARCH std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); @@ -217,8 +223,10 @@ bool export_to_off( } void make_tc(std::vector &points, + TC::TS_container const& tangent_spaces, // can be empty int intrinsic_dim, - double sparsity = 0., + bool sparsify = true, + double sparsity = 0.01, bool perturb = true, bool add_high_dim_simpl = false, bool collapse = false, @@ -226,6 +234,12 @@ void make_tc(std::vector &points, 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; @@ -275,14 +289,14 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size()); -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM std::vector points_not_sparse = points; #endif //=========================================================================== // Sparsify point set if requested //=========================================================================== - if (sparsity != 0.) + if (sparsify) { std::size_t num_points_before = points.size(); points = sparsify_point_set(k, points, sparsity*sparsity); @@ -290,6 +304,27 @@ void make_tc(std::vector &points, << num_points_before << " / " << points.size() << std::endl; } +#ifdef TC_PROTECT_POINT_SET_DELTA + // CJTODO TEST +# ifdef CGAL_TC_PROFILING + Wall_clock_timer t_protection; +# endif + + std::vector points2; + std::vector dummy; + std::vector > 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." << std::endl; +# 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()); @@ -297,13 +332,18 @@ void make_tc(std::vector &points, // Compute Tangential Complex //=========================================================================== -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#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(); @@ -356,7 +396,7 @@ void make_tc(std::vector &points, //=========================================================================== t.reset(); double export_before_time = - (export_to_off(tc, input_name_stripped, "_BEFORE_FIX") ? t.elapsed() : -1); + (export_to_off(tc, input_name_stripped, "_INITIAL_TC") ? t.elapsed() : -1); t.reset(); unsigned int num_perturb_steps = 0; @@ -406,6 +446,9 @@ void make_tc(std::vector &points, CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", "N/A"); } + // CJTODO TEST + //tc.check_and_solve_inconsistencies_by_filtering_simplices_out(); + int max_dim = -1; double fix2_time = -1; double export_after_fix2_time = -1.; @@ -447,14 +490,14 @@ void make_tc(std::vector &points, complex.display_stats(); - // Export to OFF with higher-dim simplices colored - std::set > higher_dim_simplices; + // CJTODO TEMP: Export to OFF with higher-dim simplices colored + /*std::set > 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, - &higher_dim_simplices); + &higher_dim_simplices);*/ //=========================================================================== // Collapse @@ -484,18 +527,23 @@ void make_tc(std::vector &points, //=========================================================================== // Export to OFF //=========================================================================== - 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:" << std::endl - << " * Red: wrong dim simplices" << std::endl - << " * Green: wrong number of cofaces simplices" << std::endl - << " * Blue: not-connected stars" << std::endl; - double export_after_collapse_time = (exported ? t.elapsed() : -1); - t.reset(); + + 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:" << std::endl + << " * Red: wrong dim simplices" << std::endl + << " * Green: wrong number of cofaces simplices" << std::endl + << " * Blue: not-connected stars" << std::endl; + double export_after_collapse_time = (exported ? t.elapsed() : -1.); + t.reset(); + } //=========================================================================== // Display info @@ -550,7 +598,7 @@ int main() # ifdef _DEBUG int num_threads = 1; # else - int num_threads = 10; + int num_threads = 8; # endif #endif @@ -608,6 +656,7 @@ int main() 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; @@ -619,6 +668,7 @@ int main() sstr >> num_points; sstr >> ambient_dim; sstr >> intrinsic_dim; + sstr >> sparsify; sstr >> sparsity; sstr >> perturb; sstr >> add_high_dim_simpl; @@ -657,6 +707,7 @@ int main() #endif std::vector points; + TC::TS_container tangent_spaces; if (input == "generate_moment_curve") { @@ -728,8 +779,9 @@ int main() } else { - load_points_from_file( - input, std::back_inserter(points)/*, 600*/); + load_points_from_file( + input, std::back_inserter(points), + std::back_inserter(tangent_spaces)/*, 600*/); } #ifdef CGAL_TC_PROFILING @@ -747,9 +799,9 @@ int main() << " points.\n" << "****************************************\n"; #endif - make_tc(points, intrinsic_dim, sparsity, // strided: CJTODO TEMP - perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', - time_limit_for_perturb, input.c_str()); + 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." << std::endl; std::cerr << std::endl << "---------------------------------" diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 6e0a9280507..73df4839054 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -37,6 +37,8 @@ #include #include #include +#include +#include # include @@ -47,6 +49,8 @@ #include #include +#include +#include #include #include @@ -65,6 +69,12 @@ # include #endif +// choose exact integral type for QP solver +// (Gmpzf is not thread-safe) +#include +typedef CGAL::MP_Float ET; +//#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 + //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) //static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP @@ -98,7 +108,7 @@ private: /// The class Tangential_complex represents a tangential complex template < - typename Kernel_, // ambiant dimension + typename Kernel_, // ambiant kernel typename DimensionTag, // intrinsic dimension typename Concurrency_tag = CGAL::Parallel_tag, #ifdef CGAL_ALPHA_TC @@ -149,9 +159,6 @@ class Tangential_complex typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename Tr_traits::Vector_d Tr_vector; - typedef Basis Tangent_space_basis; - typedef Basis Orthogonal_space_basis; - typedef std::vector Points; #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_TC_GLOBAL_REFRESH) typedef tbb::mutex Mutex_for_perturb; @@ -212,11 +219,14 @@ class Tangential_complex }; public: - typedef typename std::vector TS_container; - typedef typename std::vector OS_container; + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; + typedef std::vector TS_container; + typedef std::vector OS_container; + private: - typedef typename std::vector Tr_container; - typedef typename std::vector Vectors; + typedef std::vector Tr_container; + typedef std::vector Vectors; // An Incident_simplex is the list of the vertex indices // except the center vertex @@ -262,6 +272,22 @@ private: { return vh->point(); } + struct First_of_pair + { + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type::first_type const& type; + }; + + template + typename Pair::first_type const& operator()(Pair const& pair) const + { + return pair.first; + } + }; public: typedef Tangential_complex_::Simplicial_complex Simplicial_complex; @@ -270,7 +296,7 @@ public: template Tangential_complex(InputIterator first, InputIterator last, double sparsity, int intrinsic_dimension, -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM InputIterator first_for_tse, InputIterator last_for_tse, #endif const K &k = K() @@ -295,7 +321,7 @@ public: #ifdef CGAL_TC_EXPORT_NORMALS , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) #endif -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM , m_points_for_tse(first_for_tse, last_for_tse) , m_points_ds_for_tse(m_points_for_tse) #endif @@ -581,9 +607,10 @@ public: << stats_before.second << " (" << 100. * stats_before.second / stats_before.first << "%)" << std::endl - << " * Num inconsistent stars: " + /*<< " * Num inconsistent stars: " << num_inconsistent_local_tr << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" + << std::endl*/ << std::endl << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl << " - Total number of simplices in stars (incl. duplicates): " @@ -752,7 +779,46 @@ public: << 100. * stats_after.second / stats_after.first << "%" << std::endl; } - + + // Returns true if some inconsistencies were found + bool check_and_solve_inconsistencies_by_filtering_simplices_out() + { + // CJTODO TEMP + std::pair stats_before = + number_of_inconsistent_simplices(false); + std::cerr << "BEFORE check_and_solve_inconsistencies_by_filtering_simplices_out():\n" + << " - Total number of simplices in stars (incl. duplicates): " + << stats_before.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_before.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_before.second / stats_before.first << "%" + << std::endl; + + bool inconsistencies_found = false; + + // CJTODO: parallel_for??? + for (std::size_t idx = 0 ; idx < m_triangulations.size() ; ++idx) + { + if (filter_inconsistent_simplices_in_a_local_triangulation(idx)) + inconsistencies_found = true; + } + + // CJTODO TEMP + std::pair stats_after = + number_of_inconsistent_simplices(false); + std::cerr << "AFTER check_and_solve_inconsistencies_by_filtering_simplices_out():\n" + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_after.second << std::endl + << " - Percentage of inconsistencies: " + << 100. * stats_after.second / stats_after.first << "%" + << std::endl; + + return inconsistencies_found; + } + #ifdef CGAL_ALPHA_TC private: @@ -804,21 +870,71 @@ private: // star(p) does not contain "s" std::size_t p = *it_p; - // Compute the intersection between aff(Voronoi_cell(s)) and Tq - boost::optional intersection = - compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + boost::optional intersection; + + // If we know the intersection between Tq and voronoi(s) is a point + // I.e. dim(Tq) + dim(V(full_simplex)) = D + // <=> dim(Tq) = dim(full_simplex) + if (q_tr.current_dimension() == s.size()) + { + // Compute the intersection between aff(Voronoi_cell(s)) and Tq + // Note that the computation in done in the sub-space defined by Tq + intersection = + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + q_tr.current_dimension(), + project_points_and_compute_weights( + full_simplex, m_tangent_spaces[i], q_tr.geom_traits()), + m_tangent_spaces[i], + q_tr.geom_traits()); + + // CJTODO: replace with an assertion? + if (!intersection) + { + std::cerr << "ERROR fill_pqueues_for_alpha_tc: " + "aff(Voronoi_cell(s)) and Tq do not intersect.\n"; + continue; + } + } + else + { + std::cerr << "***************** Intersection is not a point ********************\n"; // CJTODO TEMP + // Compute the intersection between Voronoi_cell(s) and Tq + // We need Q, i.e. the vertices which are common neighbors of all + // vertices of full_simplex in the Delaunay triangulation, but we + // don't have, so we use the 5^d nearest neighbors instead + int num_neighbors_for_Q_approx = std::pow( + BASE_VALUE_FOR_ALPHA_TC_NEIGHBORHOOD, m_intrinsic_dim); + const Point center_pt = compute_perturbed_point(p); + KNS_range ins_range = m_points_ds.query_ANN( + center_pt, num_neighbors_for_Q_approx); + + // CJTODO: optimize that, use a vector! + std::set Q( + boost::make_counting_iterator(std::size_t(0)), + boost::make_counting_iterator(m_points.size())); + for (auto i : full_simplex) + Q.erase(i); + + intersection = + compute_voronoi_face_and_tangent_subspace_intersection( q_tr.current_dimension(), project_points_and_compute_weights( - full_simplex, m_tangent_spaces[i], q_tr.geom_traits()), + full_simplex, m_tangent_spaces[i], q_tr.geom_traits()), + project_points_and_compute_weights( + Q, + //boost::counting_range(std::size_t(0), m_points.size() - 1), + //boost::adaptors::transform(ins_range, First_of_pair()), + m_tangent_spaces[i], q_tr.geom_traits()), m_tangent_spaces[i], q_tr.geom_traits()); - // CJTODO: replace with an assertion? - if (!intersection) - { - std::cerr << "ERROR fill_pqueues_for_alpha_tc: " - "aff(Voronoi_cell(s)) and Tq do not intersect.\n"; - continue; + // CJTODO: replace with an assertion? + if (!intersection) + { + std::cerr << "ERROR fill_pqueues_for_alpha_tc: " + "Voronoi_cell(s) and Tq do not intersect.\n"; + continue; + } } // The following computations are done in the Euclidian space @@ -1436,6 +1552,205 @@ private: return *s.rbegin() == std::numeric_limits::max(); } + // Output: "triangulation" is a Regular Triangulation containing at least the + // star of "center_pt" + // Returns the handle of the center vertex + Tr_vertex_handle compute_star( + std::size_t i, const Point ¢er_pt, const Tangent_space_basis &tsb, + Triangulation &triangulation, bool verbose = false) + { + int tangent_space_dim = tsb.dimension(); + const Tr_traits &local_tr_traits = triangulation.geom_traits(); + Tr_vertex_handle center_vertex; + + // Kernel functor & objects + typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); + + // Triangulation's traits functor & objects + typename Tr_traits::Point_weight_d point_weight = + local_tr_traits.point_weight_d_object(); + typename Tr_traits::Power_center_d power_center = + local_tr_traits.power_center_d_object(); + + //*************************************************** + // Build a minimal triangulation in the tangent space + // (we only need the star of p) + //*************************************************** + + // Insert p + Tr_point proj_wp; + if (i == tsb.origin()) + { + // Insert {(0, 0, 0...), m_weights[i]} + proj_wp = local_tr_traits.construct_weighted_point_d_object()( + local_tr_traits.construct_point_d_object()(tangent_space_dim, ORIGIN), + m_weights[i]); + } + else + { + const Weighted_point& wp = compute_perturbed_weighted_point(i); + proj_wp = project_point_and_compute_weight(wp, tsb, local_tr_traits); + } + + center_vertex = triangulation.insert(proj_wp); + center_vertex->data() = i; + if (verbose) + std::cerr << "* Inserted point #" << i << std::endl; + +#ifdef CGAL_TC_VERY_VERBOSE + std::size_t num_attempts_to_insert_points = 1; + std::size_t num_inserted_points = 1; +#endif + //const int NUM_NEIGHBORS = 150; + //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); + INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); + + // While building the local triangulation, we keep the radius + // of the sphere "star sphere" centered at "center_vertex" + // and which contains all the + // circumspheres of the star of "center_vertex" + boost::optional squared_star_sphere_radius_plus_margin; + +#ifdef CGAL_ALPHA_TC + /*FT max_absolute_alpha = tsb.max_absolute_alpha(); + // "2*m_half_sparsity" because both points can be perturbed + FT max_sqdist_to_tangent_space = (max_absolute_alpha == FT(0) ? + FT(0) : CGAL::square(2*max_absolute_alpha + 2*m_half_sparsity));*/ + std::size_t number_of_attempts_to_insert_points = 0; + const std::size_t MAX_NUM_INSERTED_POINTS = + tsb.num_thickening_vectors() > 0 ? + static_cast(std::pow(BASE_VALUE_FOR_ALPHA_TC_NEIGHBORHOOD, /*tsb.dimension()*/m_intrinsic_dim)) + : std::numeric_limits::max(); +#endif + + // Insert points until we find a point which is outside "star shere" + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() ; + ++nn_it) + { +#ifdef CGAL_ALPHA_TC + ++number_of_attempts_to_insert_points; + /*if (number_of_attempts_to_insert_points > MAX_NUM_INSERTED_POINTS) + break;*/ +#endif + + std::size_t neighbor_point_idx = nn_it->first; + + // ith point = p, which is already inserted + if (neighbor_point_idx != i) + { + // No need to lock the Mutex_for_perturb here since this will not be + // called while other threads are perturbing the positions + Point neighbor_pt; + FT neighbor_weight; + compute_perturbed_weighted_point( + neighbor_point_idx, neighbor_pt, neighbor_weight); + + if (squared_star_sphere_radius_plus_margin + && k_sqdist(center_pt, neighbor_pt) + > *squared_star_sphere_radius_plus_margin) + break; + + Tr_point proj_pt = project_point_and_compute_weight( + neighbor_pt, neighbor_weight, tsb, + local_tr_traits); + +#ifdef CGAL_ALPHA_TC + /*for (int i = 0 ; i < tsb.num_thickening_vectors() ; ++i) + { + FT c = coord(proj_pt, m_intrinsic_dim + i); + if (c > 2.5*tsb.alpha_plus(i) + 2*m_half_sparsity //CJTODO: il faut 2*tsb.alpha_plus(i) + || c < 2.5*tsb.alpha_minus(i) - 2*m_half_sparsity) //CJTODO: il faut 2*tsb.alpha_minus(i) + { + goto end_of_insert_loop; // "continue" in n-2 for-loop + } + + }*/ + /*if (max_sqdist_to_tangent_space != FT(0) + && center_to_nbor_sqdist > max_sqdist_to_tangent_space) + break;*/ +#endif + + +#ifdef CGAL_TC_VERY_VERBOSE + ++num_attempts_to_insert_points; +#endif + + + Tr_vertex_handle vh = triangulation.insert_if_in_star(proj_pt, center_vertex); + //Tr_vertex_handle vh = triangulation.insert(proj_pt); + if (vh != Tr_vertex_handle()) + { +#ifdef CGAL_TC_VERY_VERBOSE + ++num_inserted_points; +#endif + if (verbose) + std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; + + vh->data() = neighbor_point_idx; + + // Let's recompute squared_star_sphere_radius_plus_margin + if (triangulation.current_dimension() >= tangent_space_dim) + { + squared_star_sphere_radius_plus_margin = boost::none; + // Get the incident cells and look for the biggest circumsphere + std::vector incident_cells; + triangulation.incident_full_cells( + center_vertex, + std::back_inserter(incident_cells)); + for (typename std::vector::iterator cit = + incident_cells.begin(); cit != incident_cells.end(); ++cit) + { + Tr_full_cell_handle cell = *cit; + if (triangulation.is_infinite(cell)) + { + squared_star_sphere_radius_plus_margin = boost::none; + break; + } + else + { + Tr_point c = power_center( + boost::make_transform_iterator( + cell->vertices_begin(), + vertex_handle_to_point), + boost::make_transform_iterator( + cell->vertices_end(), + vertex_handle_to_point)); + + FT sq_power_sphere_diam = 4 * point_weight(c); + + if (!squared_star_sphere_radius_plus_margin + || sq_power_sphere_diam > + *squared_star_sphere_radius_plus_margin) + { + squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; + } + } + } + + // Let's add the margin, now + // The value depends on whether we perturb weight or position + if (squared_star_sphere_radius_plus_margin) + { +#ifdef CGAL_TC_PERTURB_WEIGHT + // "4*m_sq_half_sparsity" because both points can be perturbed + squared_star_sphere_radius_plus_margin = + *squared_star_sphere_radius_plus_margin + 4 * m_sq_half_sparsity; +#else + // "2*m_half_sparsity" because both points can be perturbed + squared_star_sphere_radius_plus_margin = CGAL::square( + CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + + 2 * m_half_sparsity); +#endif + } + } + } + } + } + + return center_vertex; + } + void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) @@ -1484,176 +1799,9 @@ private: int tangent_space_dim = tangent_basis_dim(i); Triangulation &local_tr = m_triangulations[i].construct_triangulation(tangent_space_dim); - const Tr_traits &local_tr_traits = local_tr.geom_traits(); - Tr_vertex_handle ¢er_vertex = m_triangulations[i].center_vertex(); - // Kernel functor & objects - typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object(); - - // Triangulation's traits functor & objects - typename Tr_traits::Point_weight_d point_weight = - local_tr_traits.point_weight_d_object(); - typename Tr_traits::Power_center_d power_center = - local_tr_traits.power_center_d_object(); - - - //*************************************************** - // Build a minimal triangulation in the tangent space - // (we only need the star of p) - //*************************************************** - - // Insert p - Tr_point proj_wp; - if(i == tsb.origin()) - { - proj_wp = local_tr_traits.construct_weighted_point_d_object()( - local_tr_traits.construct_point_d_object()(tangent_space_dim, ORIGIN), - m_weights[i]); - } - else - { - const Weighted_point& wp = compute_perturbed_weighted_point(i); - proj_wp = project_point_and_compute_weight(wp, tsb, local_tr_traits); - } - - center_vertex = local_tr.insert(proj_wp); - center_vertex->data() = i; - if (verbose) - std::cerr << "* Inserted point #" << i << std::endl; - -#ifdef CGAL_TC_VERY_VERBOSE - std::size_t num_attempts_to_insert_points = 1; - std::size_t num_inserted_points = 1; -#endif - //const int NUM_NEIGHBORS = 150; - //KNS_range ins_range = m_points_ds.query_ANN(center_pt, NUM_NEIGHBORS); - INS_range ins_range = m_points_ds.query_incremental_ANN(center_pt); - - // While building the local triangulation, we keep the radius - // of the sphere "star sphere" centered at "center_vertex" - // and which contains all the - // circumspheres of the star of "center_vertex" - boost::optional squared_star_sphere_radius_plus_margin; - -#ifdef CGAL_ALPHA_TC - /*FT max_absolute_alpha = tsb.max_absolute_alpha(); - // "2*m_half_sparsity" because both points can be perturbed - FT max_sqdist_to_tangent_space = (max_absolute_alpha == FT(0) ? - FT(0) : CGAL::square(2*max_absolute_alpha + 2*m_half_sparsity));*/ - std::size_t number_of_attempts_to_insert_points = 0; - const std::size_t MAX_NUM_INSERTED_POINTS = - tsb.num_thickening_vectors() > 0 ? - static_cast(std::pow(4, /*tsb.dimension()*/m_intrinsic_dim)) - : std::numeric_limits::max(); -#endif - - // Insert points until we find a point which is outside "star shere" - for (INS_iterator nn_it = ins_range.begin() ; - nn_it != ins_range.end() ; - ++nn_it) - { -#ifdef CGAL_ALPHA_TC - ++number_of_attempts_to_insert_points; - if (number_of_attempts_to_insert_points > MAX_NUM_INSERTED_POINTS) - break; -#endif - - std::size_t neighbor_point_idx = nn_it->first; - - // ith point = p, which is already inserted - if (neighbor_point_idx != i) - { - // No need to lock the Mutex_for_perturb here since this will not be - // called while other threads are perturbing the positions - Point neighbor_pt; - FT neighbor_weight; - compute_perturbed_weighted_point( - neighbor_point_idx, neighbor_pt, neighbor_weight); - - if (squared_star_sphere_radius_plus_margin - && k_sqdist(center_pt, neighbor_pt) - > *squared_star_sphere_radius_plus_margin) - break; - - Tr_point proj_pt = project_point_and_compute_weight( - neighbor_pt, neighbor_weight, tsb, - local_tr_traits); - -#ifdef CGAL_TC_VERY_VERBOSE - ++num_attempts_to_insert_points; -#endif - - - Tr_vertex_handle vh = local_tr.insert_if_in_star(proj_pt, center_vertex); - //Tr_vertex_handle vh = local_tr.insert(proj_pt); - if (vh != Tr_vertex_handle()) - { -#ifdef CGAL_TC_VERY_VERBOSE - ++num_inserted_points; -#endif - if (verbose) - std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; - - vh->data() = neighbor_point_idx; - - // Let's recompute squared_star_sphere_radius_plus_margin - if (local_tr.current_dimension() >= tangent_space_dim) - { - squared_star_sphere_radius_plus_margin = boost::none; - // Get the incident cells and look for the biggest circumsphere - std::vector incident_cells; - local_tr.incident_full_cells( - center_vertex, - std::back_inserter(incident_cells)); - for (typename std::vector::iterator cit = - incident_cells.begin(); cit != incident_cells.end(); ++cit) - { - Tr_full_cell_handle cell = *cit; - if (local_tr.is_infinite(cell)) - { - squared_star_sphere_radius_plus_margin = boost::none; - break; - } - else - { - Tr_point c = power_center( - boost::make_transform_iterator( - cell->vertices_begin(), - vertex_handle_to_point), - boost::make_transform_iterator( - cell->vertices_end(), - vertex_handle_to_point)); - - FT sq_power_sphere_diam = 4*point_weight(c); - - if (!squared_star_sphere_radius_plus_margin - || sq_power_sphere_diam > - *squared_star_sphere_radius_plus_margin) - { - squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; - } - } - } - - // Let's add the margin, now - // The value depends on whether we perturb weight or position - if (squared_star_sphere_radius_plus_margin) - { -#ifdef CGAL_TC_PERTURB_WEIGHT - // "4*m_sq_half_sparsity" because both points can be perturbed - squared_star_sphere_radius_plus_margin = - *squared_star_sphere_radius_plus_margin + 4*m_sq_half_sparsity; -#else - // "2*m_half_sparsity" because both points can be perturbed - squared_star_sphere_radius_plus_margin = CGAL::square( - CGAL::sqrt(*squared_star_sphere_radius_plus_margin) - + 2*m_half_sparsity); -#endif - } - } - } - } - } + m_triangulations[i].center_vertex() = + compute_star(i, center_pt, tsb, local_tr, verbose); #if defined(CGAL_TC_PROFILING) && defined(CGAL_TC_VERY_VERBOSE) std::cerr << " - triangulation construction: " << t.elapsed() << " s.\n"; @@ -2003,7 +2151,7 @@ next_face: //typename K::Translated_point_d transl = // m_k.translated_point_d_object(); -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM KNS_range kns_range = m_points_ds_for_tse.query_ANN( p, num_points_for_pca, false); const Points &points_for_pca = m_points_for_tse; @@ -2127,6 +2275,95 @@ next_face: */ } + // Compute the space tangent to a simplex (p1, p2, ... pn) + // CJTODO: Improve this? + // Basically, it takes all the neighbor points to p1, p2... pn and runs PCA + // on it. Note that most points are duplicated. + Tangent_space_basis compute_tangent_space( + const Indexed_simplex &s, bool normalize_basis = true) + { + unsigned int num_points_for_pca = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); + + // Kernel functors + typename K::Construct_vector_d constr_vec = + m_k.construct_vector_d_object(); + typename K::Compute_coordinate_d coord = + m_k.compute_coordinate_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(); + typename K::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename K::Difference_of_vectors_d diff_vec = + m_k.difference_of_vectors_d_object(); + //typename K::Translated_point_d transl = + // m_k.translated_point_d_object(); + + // One row = one point + Eigen::MatrixXd mat_points(s.size()*num_points_for_pca, m_ambient_dim); + unsigned int current_row = 0; + + for (Indexed_simplex::const_iterator it_index = s.begin(); + it_index != s.end() ; ++it_index) + { + const Point &p = m_points[*it_index]; + +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + KNS_range kns_range = m_points_ds_for_tse.query_ANN( + p, num_points_for_pca, false); + const Points &points_for_pca = m_points_for_tse; +#else + KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); + const Points &points_for_pca = m_points; +#endif + + KNS_iterator nn_it = kns_range.begin(); + for ( ; + current_row < num_points_for_pca && nn_it != kns_range.end() ; + ++current_row, ++nn_it) + { + for (int i = 0 ; i < m_ambient_dim ; ++i) + { + //const Point p = transl( + // points_for_pca[nn_it->first], m_translations[nn_it->first]); + mat_points(current_row, i) = + CGAL::to_double(coord(points_for_pca[nn_it->first], i)); + } + } + } + Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver eig(cov); + + Tangent_space_basis tsb; + + // The eigenvectors are sorted in increasing order of their corresponding + // eigenvalues + for (int j = m_ambient_dim - 1 ; + j >= m_ambient_dim - m_intrinsic_dim ; + --j) + { + if (normalize_basis) + { + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); + tsb.push_back(normalize_vector(v, m_k)); + } + else + { + tsb.push_back(constr_vec( + m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); + } + } + + return tsb; + } + // Returns the dimension of the ith local triangulation // This is particularly useful for the alpha-TC int tangent_basis_dim(std::size_t i) const @@ -2830,6 +3067,95 @@ next_face: return is_inconsistent; } + + bool filter_inconsistent_simplices_in_a_local_triangulation( + std::size_t tr_index) + { + bool is_inconsistent = false; + + Star &star = m_stars[tr_index]; + Triangulation const& tr = m_triangulations[tr_index].tr(); + Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex(); + const Tr_traits &local_tr_traits = tr.geom_traits(); + int cur_dim = tr.current_dimension(); + + // For each incident simplex + Star::iterator it_inc_simplex = star.begin(); + while (it_inc_simplex != star.end()) + { + const Incident_simplex &incident_simplex = *it_inc_simplex; + + // Don't check infinite cells + if (is_infinite(incident_simplex)) + { + ++it_inc_simplex; + continue; + } + + Indexed_simplex c = incident_simplex; + c.insert(tr_index); // Add the missing index + + // Inconsistent? + if (!is_simplex_consistent(c)) + { + is_inconsistent = true; + + // Compute T, the space tangent to "c" + Tangent_space_basis tsb = compute_tangent_space(c); + + std::size_t center_index = *(c.begin()); + // Compute the star of "center_index" in the RT restricted to T + tsb.set_origin(center_index); + Triangulation tr(m_intrinsic_dim); + Tr_vertex_handle center_vh = compute_star( + center_index, compute_perturbed_point(center_index), tsb, tr); + + // Get incident cells + std::vector incident_cells; + tr.incident_full_cells( + center_vh, std::back_inserter(incident_cells)); + + // Check if "c" is among them + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end = incident_cells.end(); + bool found = false; + // For each cell + for (; !found && it_c != it_c_end ; ++it_c) + { + Incident_simplex incident_simplex; + for (int j = 0 ; j < tr.current_dimension() + 1 ; ++j) + { + std::size_t index = (*it_c)->vertex(j)->data(); + incident_simplex.insert(index); + } + if (incident_simplex == c) + found = true; + } + // If the simplex is not in the new star, we remove it + if (!found) + { + if (it_inc_simplex != star.end() - 1) + { + *it_inc_simplex = star.back(); + star.pop_back(); + } + else + { + star.pop_back(); + it_inc_simplex = star.end(); // end the loop + } + } + else + ++it_inc_simplex; + } + // Consistent + else + ++it_inc_simplex; + } + + return is_inconsistent; + } + std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices, bool use_perturbed_points = false) const @@ -4105,7 +4431,7 @@ private: //std::vector m_tr_mutexes; #endif -#ifdef USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM +#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM Points m_points_for_tse; Points_ds m_points_ds_for_tse; #endif From 1ede44996cff9130435ae6aee7077a5c8b8102cf Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 19 Jan 2016 17:16:56 +0100 Subject: [PATCH 252/269] Add Simplicial_complex::num_K_simplices() --- .../include/CGAL/Tangential_complex.h | 12 +++--- .../Tangential_complex/Simplicial_complex.h | 37 ++++++++++++++++--- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 73df4839054..19c8af98a5d 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -1355,7 +1355,7 @@ public: std::set * incorrect_simplices = NULL) const { typedef Simplicial_complex::Simplex Simplex; - typedef Simplicial_complex::Simplex_range Simplex_range; + typedef Simplicial_complex::Simplex_set Simplex_set; if (m_points.empty()) return true; @@ -1413,10 +1413,10 @@ public: // save its simplices into "stars_simplices" //------------------------------------------------------------------------- - Simplex_range const *p_simplices; + Simplex_set const *p_simplices; std::size_t num_infinite_cells = 0; - Simplex_range stars_simplices; + Simplex_set stars_simplices; if (!p_complex) { Stars_container::const_iterator it_star = m_stars.begin(); @@ -4186,16 +4186,16 @@ public: const { typedef Simplicial_complex::Simplex Simplex; - typedef Simplicial_complex::Simplex_range Simplex_range; + typedef Simplicial_complex::Simplex_set Simplex_set; // If m_intrinsic_dim = 1, each point is output two times // (see export_vertices_to_off) num_OFF_simplices = 0; std::size_t num_maximal_simplices = 0; - typename Simplex_range::const_iterator it_s = + typename Simplex_set::const_iterator it_s = complex.simplex_range().begin(); - typename Simplex_range::const_iterator it_s_end = + typename Simplex_set::const_iterator it_s_end = complex.simplex_range().end(); // For each simplex for ( ; it_s != it_s_end ; ++it_s) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 199691c0a64..c7a9b58c242 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -43,7 +43,7 @@ class Simplicial_complex { public: typedef std::set Simplex; - typedef std::set Simplex_range; + typedef std::set Simplex_set; void add_simplex( const std::set &s, bool perform_checks = true) @@ -86,7 +86,7 @@ public: m_complex.insert(s); } - const Simplex_range &simplex_range() const + const Simplex_set &simplex_range() const { return m_complex; } @@ -322,6 +322,31 @@ public: return ret; } + template + std::size_t num_K_simplices() + { + std::set 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(); + } + // CJTODO: ADD COMMENTS bool is_pure_pseudomanifold( int simplex_dim, @@ -331,9 +356,9 @@ public: 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_range *p_wrong_dim_simplices = NULL, - Simplex_range *p_wrong_number_of_cofaces_simplices = NULL, - Simplex_range *p_unconnected_stars_simplices = NULL) const + 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) @@ -512,7 +537,7 @@ public: } private: - typedef Simplex_range Complex; + typedef Simplex_set Complex; // graph is an adjacency list typedef boost::adjacency_list Adj_graph; From 73435c098714994282b1f319e76feb1214a818f7 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 Jan 2016 12:50:01 +0100 Subject: [PATCH 253/269] Forgot to commit Mesh_d.h + missing const --- .../Tangential_complex/benchmark_mesh_d.cpp | 16 +- Tangential_complex/include/CGAL/Mesh_d.h | 1181 +++++++++++++++++ .../Tangential_complex/Simplicial_complex.h | 2 +- 3 files changed, 1197 insertions(+), 2 deletions(-) create mode 100644 Tangential_complex/include/CGAL/Mesh_d.h diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp index 8ff7c0d0d67..0e5aea227d1 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -14,6 +14,7 @@ #include #include "../../test/Tangential_complex/testing_utilities.h" +#include "console_color.h" #include #include @@ -168,6 +169,18 @@ void make_mesh( // 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 @@ -176,7 +189,8 @@ void make_mesh( std::cerr << std::endl << "================================================" << std::endl << "Number of vertices: " << mesh.number_of_vertices() << std::endl - //<< "Pure pseudomanifold: " << (is_pure_pseudomanifold ? "YES" : "NO") << std::endl + << "Pure pseudomanifold: " << yellow + << (is_pure_pseudomanifold ? "YES" : "NO") << white << std::endl << "Computation times (seconds): " << std::endl << " * Mesh: " << init_time + computation_time << std::endl << " - Init + kd-tree = " << init_time << std::endl diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h new file mode 100644 index 00000000000..7907d2adff9 --- /dev/null +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -0,0 +1,1181 @@ +// 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 MESH_D_H +#define MESH_D_H + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +# include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif + +// choose exact integral type for QP solver +// (Gmpzf is not thread-safe) +#include +typedef CGAL::MP_Float ET; +//#define CGAL_QP_NO_ASSERTIONS // CJTODO: NECESSARY? http://doc.cgal.org/latest/QP_solver/group__PkgQPSolverFunctions.html#ga1fefbd0436aca0e281f88e8e6cd8eb74 + +namespace CGAL { + +using namespace Tangential_complex_; + +class Vertex_data +{ +public: + Vertex_data(std::size_t data = std::numeric_limits::max()) + : m_data(data) + {} + operator std::size_t() { return m_data; } + operator std::size_t() const { return m_data; } + +private: + std::size_t m_data; +}; + +/// The class Mesh_d represents a d-dimensional mesh +template < + typename Kernel_, // ambiant kernel + typename DimensionTag, // intrinsic dimension + typename Concurrency_tag = CGAL::Parallel_tag, + typename Tr = Delaunay_triangulation + < + Kernel_, + Triangulation_data_structure + < + typename Kernel_::Dimension, + Triangulation_vertex, + Triangulation_full_cell + > + > +> +class Mesh_d +{ + typedef Kernel_ K; + typedef typename K::FT FT; + typedef typename K::Point_d Point; + typedef typename K::Vector_d Vector; + + typedef Tr Triangulation; + typedef typename Triangulation::Vertex_handle Tr_vertex_handle; + typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; + typedef typename Triangulation::Finite_full_cell_const_iterator + Tr_finite_full_cell_const_iterator; + + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; + + typedef std::vector Points; + + typedef Point_cloud_data_structure Points_ds; + typedef typename Points_ds::KNS_range KNS_range; + typedef typename Points_ds::KNS_iterator KNS_iterator; + typedef typename Points_ds::INS_range INS_range; + typedef typename Points_ds::INS_iterator INS_iterator; + + typedef std::set Vertex_set; + typedef std::set Indexed_simplex; + +public: + typedef std::vector TS_container; + typedef std::vector OS_container; +private: + + // For transform_iterator + static const Point &vertex_handle_to_point(Tr_vertex_handle vh) + { + return vh->point(); + } + // For transform_iterator + static std::size_t vertex_handle_to_index(Tr_vertex_handle vh) + { + return vh->data(); + } + + struct First_of_pair + { + template struct result; + + template + struct result + { + typedef typename boost::remove_reference::type::first_type const& type; + }; + + template + typename Pair::first_type const& operator()(Pair const& pair) const + { + return pair.first; + } + }; + +public: + typedef Tangential_complex_::Simplicial_complex Simplicial_complex; + + /// Constructor for a range of points + template + Mesh_d(InputIterator first, InputIterator last, + double sparsity, int intrinsic_dimension, +#ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + InputIterator first_for_tse, InputIterator last_for_tse, +#endif + const K &k = K() + ) + : m_k(k) + , m_intrinsic_dim(intrinsic_dimension) + , m_half_sparsity(0.5*sparsity) + , m_sq_half_sparsity(m_half_sparsity*m_half_sparsity) + , m_ambient_dim(k.point_dimension_d_object()(*first)) + , m_points(first, last) + , m_points_ds(m_points) + , m_are_tangent_spaces_computed(m_points.size(), false) + , m_tangent_spaces(m_points.size(), Tangent_space_basis()) + , m_orth_spaces(m_points.size(), Orthogonal_space_basis()) +#ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + , m_points_for_tse(first_for_tse, last_for_tse) + , m_points_ds_for_tse(m_points_for_tse) +#endif + { + if (sparsity <= 0.) + std::cerr << "!Warning! Sparsity should be > 0\n"; + } + + /// Destructor + ~Mesh_d() + { + } + + int intrinsic_dimension() const + { + return m_intrinsic_dim; + } + int ambient_dimension() const + { + return m_ambient_dim; + } + + std::size_t number_of_vertices() const + { + return m_points.size(); + } + + Simplicial_complex const& complex() + { + return m_complex; + } + + void set_tangent_planes( + const TS_container& tangent_spaces, const OS_container& orthogonal_spaces) + { + CGAL_assertion(m_points.size() == tangent_spaces.size() + && m_points.size() == orthogonal_spaces.size()); + m_tangent_spaces = tangent_spaces; + m_orth_spaces = orthogonal_spaces; + for(std::size_t i=0; i *p_uncertain_simplices = NULL) + { +#if defined(CGAL_MESH_D_PROFILING) && defined(CGAL_LINKED_WITH_TBB) + Wall_clock_timer t; +#endif + + // Tangent and orthogonal spaces + for (std::size_t i = 0; i < m_points.size(); ++i) + { + if (!m_are_tangent_spaces_computed[i]) + { + m_tangent_spaces[i] = compute_tangent_space( + m_points[i], i, true/*normalize*/, &m_orth_spaces[i]); + } + } +#if defined(CGAL_MESH_D_PROFILING) && defined(CGAL_LINKED_WITH_TBB) + std::cerr << "Tangent & orthogonal spaces computed in " << t.elapsed() + << " seconds." << std::endl; + t.reset(); +#endif + + // Ambiant DT + Tr tr(m_ambient_dim); + for (std::size_t i = 0; i < m_points.size(); ++i) + { + Tr_vertex_handle vh = tr.insert(m_points[i]); + vh->data() = i; + } +#if defined(CGAL_MESH_D_PROFILING) && defined(CGAL_LINKED_WITH_TBB) + std::cerr << "Ambient DT computed in " << t.elapsed() + << " seconds." << std::endl; + t.reset(); +#endif + + // Extract complex + // CJTODO: avoid duplicates + parallelize + /*m_complex.clear(); + for (Tr_finite_full_cell_const_iterator cit = tr.finite_full_cells_begin() ; + cit != tr.finite_full_cells_end() ; ++cit) + { + // Enumerate k-dim simplices + CGAL::Combination_enumerator combi( + m_intrinsic_dim + 1, 0, m_ambient_dim + 1); + + for (; !combi.finished() ; ++combi) + { + Indexed_simplex simplex; + std::vector vertices; + for (int i = 0 ; i < m_intrinsic_dim + 1 ; ++i) + { + vertices.push_back(cit->vertex(combi[i])); + simplex.insert(cit->vertex(combi[i])->data()); + } + + Vertex_set Q_set = + get_common_neighbor_vertices(tr, vertices); + // Convert it to a vector, because otherwise, the result of + // boost::adaptors::transform does not provide size() + std::vector Q(Q_set.begin(), Q_set.end()); + bool intersect = does_voronoi_face_and_tangent_subspace_intersect( + boost::adaptors::transform(vertices, vertex_handle_to_point), + boost::adaptors::transform(Q, vertex_handle_to_point), + m_orth_spaces[*simplex.begin()]); // CJTODO: remplacer simplex[0] par un truc plus intelligent + if (intersect) + m_complex.add_simplex(simplex, false); + } + }*/ + + Get_functor::type sum_vecs(m_k); + + // Extract complex + // CJTODO: parallelize + m_complex.clear(); + typedef std::map K_faces_and_neighbor_vertices; + K_faces_and_neighbor_vertices k_faces_and_neighbor_vertices = + get_k_faces_and_neighbor_vertices(tr); + m_complex.clear(); + for (K_faces_and_neighbor_vertices::const_iterator k_face_and_nghb_it = + k_faces_and_neighbor_vertices.begin() ; + k_face_and_nghb_it != k_faces_and_neighbor_vertices.end() ; + ++k_face_and_nghb_it) + { + Vertex_set const& k_face = k_face_and_nghb_it->first; + Vertex_set const& neighbor_vertices = k_face_and_nghb_it->second; + // Convert it to a vector, because otherwise, the result of + // boost::adaptors::transform does not provide size() + std::vector kf(k_face.begin(), k_face.end()); + std::vector nghb( + neighbor_vertices.begin(), neighbor_vertices.end()); + + bool keep_it = false; + bool is_uncertain = false; +#ifdef MESH_D_FILTER_BY_TESTING_ALL_VERTICES_TANGENT_PLANES + int num_intersections = 0; + for (auto vh : kf) // CJTODO C++11 + { + bool intersect = does_voronoi_face_and_tangent_subspace_intersect( + boost::adaptors::transform(kf, vertex_handle_to_point), + boost::adaptors::transform(nghb, vertex_handle_to_point), + m_orth_spaces[vh->data()]); + if (intersect) + ++num_intersections; + } + + if (num_intersections >= 1) + { + keep_it = true; + if (num_intersections < m_intrinsic_dim + 1) + is_uncertain = true; + } +#else + // Compute the intersection with all tangent planes of the vertices + // of the k-face + FT sum_weights = 0; + Vector weighted_sum_of_inters = + m_k.construct_vector_d_object()(m_ambient_dim); + for (auto vh : kf) // CJTODO C++11 + { + boost::optional intersection = + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + boost::adaptors::transform(kf, vertex_handle_to_point), + m_orth_spaces[vh->data()]); + + if (intersection) + { + FT weight = + FT(1) / m_k.squared_distance_d_object()(vh->point(), *intersection); + sum_weights += weight; + weighted_sum_of_inters = sum_vecs( + weighted_sum_of_inters, + m_k.scaled_vector_d_object()( + m_k.point_to_vector_d_object()(*intersection), weight)); + } + else + + } + if (sum_weights > 0) + { + // Compute the weighted barycenter + Point avg_inters = m_k.vector_to_point_d_object()( + m_k.scaled_vector_d_object()( + weighted_sum_of_inters, FT(1) / sum_weights)); + + keep_it = true; + // Check if the averaged intersection "i" is inside the Voronoi cell, i.e. + // for each common neighbor qi, (i - p0)˛ <= (i - qi)˛ + Point const& p0 = (*k_face.begin())->point(); + for (auto neighbor_vh : nghb) // CJTODO: C++11 + { + if (m_k.squared_distance_d_object()(p0, avg_inters) > + m_k.squared_distance_d_object()(neighbor_vh->point(), avg_inters)) + { + keep_it = false; + break; + } + } + } +#endif + + if (keep_it) + { + Indexed_simplex s( + boost::make_transform_iterator(kf.begin(), vertex_handle_to_index), + boost::make_transform_iterator(kf.end(), vertex_handle_to_index)); + m_complex.add_simplex(s, false); + + if (is_uncertain && p_uncertain_simplices) + p_uncertain_simplices->push_back(s); + } + } + +#if defined(CGAL_MESH_D_PROFILING) && defined(CGAL_LINKED_WITH_TBB) + std::cerr << "Mesh extracted in computed in " << t.elapsed() + << " seconds." << std::endl; + t.reset(); +#endif + } + + void display_stats() + { + m_complex.display_stats(); + } + +private: + + class Compare_distance_to_ref_point + { + public: + Compare_distance_to_ref_point(Point const& ref, K const& k) + : m_ref(ref), m_k(k) {} + + bool operator()(Point const& p1, Point const& p2) + { + typename K::Squared_distance_d sqdist = + m_k.squared_distance_d_object(); + return sqdist(p1, m_ref) < sqdist(p2, m_ref); + } + + private: + Point const& m_ref; + K const& m_k; + }; + + bool is_infinite(Indexed_simplex const& s) const + { + return *s.rbegin() == std::numeric_limits::max(); + } + + Tangent_space_basis compute_tangent_space( + const Point &p + , const std::size_t i + , bool normalize_basis = true + , Orthogonal_space_basis *p_orth_space_basis = NULL) + { +#ifdef CGAL_MESH_D_COMPUTE_TANGENT_PLANES_FOR_SPHERE_2 + + double tt[2] = {p[1], -p[0]}; + Vector t(2, &tt[0], &tt[2]); + + // Normalize t1 and t2 + 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(); + + Tangent_space_basis ts(i); + ts.reserve(m_intrinsic_dim); + ts.push_back(scaled_vec(t, FT(1)/CGAL::sqrt(sqlen(t)))); + m_are_tangent_spaces_computed[i] = true; + + return ts; + +#elif defined(CGAL_MESH_D_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3) + + double tt1[3] = {-p[1] - p[2], p[0], p[0]}; + double tt2[3] = {p[1] * tt1[2] - p[2] * tt1[1], + p[2] * tt1[0] - p[0] * tt1[2], + p[0] * tt1[1] - p[1] * tt1[0]}; + Vector t1(3, &tt1[0], &tt1[3]); + Vector t2(3, &tt2[0], &tt2[3]); + + // Normalize t1 and t2 + 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(); + + Tangent_space_basis ts(i); + ts.reserve(m_intrinsic_dim); + ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); + ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); + + m_are_tangent_spaces_computed[i] = true; + + return ts; + +#elif defined(CGAL_MESH_D_COMPUTE_TANGENT_PLANES_FOR_TORUS_D) + + Tangent_space_basis ts(i); + ts.reserve(m_intrinsic_dim); + for (int dim = 0 ; dim < m_intrinsic_dim ; ++dim) + { + std::vector tt(m_ambient_dim, 0.); + tt[2*dim] = -p[2*dim + 1]; + tt[2*dim + 1] = p[2*dim]; + Vector t(2*m_intrinsic_dim, tt.begin(), tt.end()); + ts.push_back(t); + } + + m_are_tangent_spaces_computed[i] = true; + + //return compute_gram_schmidt_basis(ts, m_k); + return ts; + //******************************* PCA ************************************* + +#else + + unsigned int num_points_for_pca = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); + + // Kernel functors + typename K::Construct_vector_d constr_vec = + m_k.construct_vector_d_object(); + typename K::Compute_coordinate_d coord = + m_k.compute_coordinate_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(); + typename K::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename K::Difference_of_vectors_d diff_vec = + m_k.difference_of_vectors_d_object(); + //typename K::Translated_point_d transl = + // m_k.translated_point_d_object(); + +#ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + KNS_range kns_range = m_points_ds_for_tse.query_ANN( + p, num_points_for_pca, false); + const Points &points_for_pca = m_points_for_tse; +#else + KNS_range kns_range = m_points_ds.query_ANN(p, num_points_for_pca, false); + const Points &points_for_pca = m_points; +#endif + + // One row = one point + Eigen::MatrixXd mat_points(num_points_for_pca, m_ambient_dim); + KNS_iterator nn_it = kns_range.begin(); + for (unsigned int j = 0 ; + j < num_points_for_pca && nn_it != kns_range.end() ; + ++j, ++nn_it) + { + for (int i = 0 ; i < m_ambient_dim ; ++i) + { + //const Point p = transl( + // points_for_pca[nn_it->first], m_translations[nn_it->first]); + mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i)); +#ifdef CGAL_MESH_D_ADD_NOISE_TO_TANGENT_SPACE + mat_points(j, i) += m_random_generator.get_double( + -0.5*m_half_sparsity, 0.5*m_half_sparsity); +#endif + } + } + Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean(); + Eigen::MatrixXd cov = centered.adjoint() * centered; + Eigen::SelfAdjointEigenSolver eig(cov); + + Tangent_space_basis tsb(i); // p = compute_perturbed_point(i) here + + // The eigenvectors are sorted in increasing order of their corresponding + // eigenvalues + for (int j = m_ambient_dim - 1 ; + j >= m_ambient_dim - m_intrinsic_dim ; + --j) + { + if (normalize_basis) + { + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); + tsb.push_back(normalize_vector(v, m_k)); + } + else + { + tsb.push_back(constr_vec( + m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); + } + } + + if (p_orth_space_basis) + { + p_orth_space_basis->set_origin(i); + for (int j = m_ambient_dim - m_intrinsic_dim - 1 ; + j >= 0 ; + --j) + { + if (normalize_basis) + { + Vector v = constr_vec(m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim); + p_orth_space_basis->push_back(normalize_vector(v, m_k)); + } + else + { + p_orth_space_basis->push_back(constr_vec( + m_ambient_dim, + eig.eigenvectors().col(j).data(), + eig.eigenvectors().col(j).data() + m_ambient_dim)); + } + } + } + + m_are_tangent_spaces_computed[i] = true; + + //************************************************************************* + + //Vector n = m_k.point_to_vector_d_object()(p); + //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); + //std::cerr << "IP = " << scalar_pdct(n, ts[0]) << " & " << scalar_pdct(n, ts[1]) << std::endl; + + return tsb; + +#endif + + /* + // Alternative code (to be used later) + //Vector n = m_k.point_to_vector_d_object()(p); + //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); + //Vector t1(12., 15., 65.); + //Vector t2(32., 5., 85.); + //Tangent_space_basis ts; + //ts.reserve(m_intrinsic_dim); + //ts.push_back(diff_vec(t1, scaled_vec(n, scalar_pdct(t1, n)))); + //ts.push_back(diff_vec(t2, scaled_vec(n, scalar_pdct(t2, n)))); + //ts = compute_gram_schmidt_basis(ts, m_k); + //return ts; + */ + } + + Vertex_set get_neighbor_vertices( + Triangulation const& tr, Tr_vertex_handle vh, + bool keep_infinite_vertex = false) + { + Vertex_set neighbors; + std::vector incident_cells; + tr.incident_full_cells( + vh, std::back_inserter(incident_cells)); + + typename std::vector::const_iterator it_c = incident_cells.begin(); + typename std::vector::const_iterator it_c_end = incident_cells.end(); + // For each cell + for (; it_c != it_c_end ; ++it_c) + { + for (int j = 0 ; j < m_ambient_dim + 1 ; ++j) + { + Tr_vertex_handle v = (*it_c)->vertex(j); + if (keep_infinite_vertex + || v->data() != std::numeric_limits::max()) + { + neighbors.insert(v); + } + } + } + neighbors.erase(vh); + return neighbors; + } + + template + Vertex_set get_common_neighbor_vertices( + Triangulation const& tr, Vertex_range const& vertices) + { + Vertex_range::const_iterator vh_it = vertices.begin(); + Vertex_set common_neighbors = + get_neighbor_vertices(tr, *vh_it); + ++vh_it; + + for (; vh_it != vertices.end() ; ++vh_it) + { + Vertex_set neighbors = get_neighbor_vertices(tr, *vh_it); + Vertex_set former_common_neighbors = common_neighbors; + common_neighbors.clear(); + std::set_intersection( + former_common_neighbors.begin(), former_common_neighbors.end(), + neighbors.begin(), neighbors.end(), + std::inserter(common_neighbors, common_neighbors.begin())); + } + + return common_neighbors; + } + + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + // Note that the computation is made in global coordinates. + template + CGAL::Quadratic_program_solution + compute_voronoi_face_and_tangent_subspace_LP_problem( + Point_range_a const& P, + Point_range_b const& Q, + Orthogonal_space_basis const& orthogonal_subspace_basis) const + { + // Notations: + // Fv: Voronoi k-face + // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) + + typename Kernel::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename Kernel::Point_to_vector_d pt_to_vec = + m_k.point_to_vector_d_object(); + typename Kernel::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + + std::size_t card_P = P.size(); + std::size_t card_Q = Q.size(); + + // Linear solver + typedef CGAL::Quadratic_program Linear_program; + typedef CGAL::Quadratic_program_solution LP_solution; + + Linear_program lp(CGAL::SMALLER, false); + int current_row = 0; + + //=========== First set of equations =========== + // For points pi in P + // 2(p0 - pi).x = p0^2 - pi^2 + typename Point_range_a::const_iterator it_p = P.begin(); + Point const& p0 = *it_p; + FT p0_dot_p0 = scalar_pdct(pt_to_vec(p0), pt_to_vec(p0)); + ++it_p; + for (typename Point_range_a::const_iterator it_p_end = P.end() ; + it_p != it_p_end ; ++it_p) + { + Point const& pi = *it_p; + + for (int k = 0 ; k < m_ambient_dim ; ++k) + lp.set_a(k, current_row, 2 * (coord(p0, k) - coord(pi, k))); + + FT pi_dot_pi = scalar_pdct(pt_to_vec(pi), pt_to_vec(pi)); + lp.set_b(current_row, p0_dot_p0 - pi_dot_pi); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + //=========== Second set of equations =========== + // For each point qi in Q + // 2(qi - p0).x <= qi^2 - p0^2 + for (typename Point_range_b::const_iterator it_q = Q.begin(), + it_q_end = Q.end() ; + it_q != it_q_end ; ++it_q) + { + Point const& qi = *it_q; + + for (int k = 0 ; k < m_ambient_dim ; ++k) + lp.set_a(k, current_row, 2 * (coord(qi, k) - coord(p0, k))); + + FT qi_dot_qi = scalar_pdct(pt_to_vec(qi), pt_to_vec(qi)); + lp.set_b(current_row, qi_dot_qi - p0_dot_p0); + + ++current_row; + } + + //=========== Third set of equations =========== + // For each vector bi of OSB, (x-p).bi = 0 + // <=> bi.x = bi.p + for (Orthogonal_space_basis::const_iterator it_osb = + orthogonal_subspace_basis.begin(), + it_osb_end = orthogonal_subspace_basis.end() ; + it_osb != it_osb_end ; ++it_osb) + { + Vector const& bi = *it_osb; + + for (int k = 0 ; k < m_ambient_dim ; ++k) + { + lp.set_a(k, current_row, coord(bi, k)); + } + + FT bi_dot_p = scalar_pdct(bi, + pt_to_vec(m_points[orthogonal_subspace_basis.origin()])); + lp.set_b(current_row, bi_dot_p); + lp.set_r(current_row, CGAL::EQUAL); + + ++current_row; + } + + //=========== Other LP parameters =========== + lp.set_c(0, 1); // Minimize x[0] + + //=========== Solve ========================= + LP_solution solution = CGAL::solve_linear_program(lp, ET()); + return solution; + } + + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + template + bool does_voronoi_face_and_tangent_subspace_intersect( + Point_range_a const& P, + Point_range_b const& Q, + Orthogonal_space_basis const& orthogonal_subspace_basis) const + { + return compute_voronoi_face_and_tangent_subspace_LP_problem( + P, Q, orthogonal_subspace_basis).status() == CGAL::QP_OPTIMAL; + } + + + // Returns any point of the intersection between a Voronoi cell and a + // tangent space. + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Q: vertices which are common neighbors of all vertices of P + // Return value: the point coordinates are expressed in global coordinates + template + boost::optional + compute_voronoi_face_and_tangent_subspace_intersection( + Point_range_a const& P, + Point_range_b const& Q, + Orthogonal_space_basis const& orthogonal_subspace_basis) const + { + typedef CGAL::Quadratic_program_solution LP_solution; + + LP_solution sol = compute_voronoi_face_and_tangent_subspace_LP_problem( + P, Q, orthogonal_subspace_basis); + + boost::optional ret; + if (sol.status() == CGAL::QP_OPTIMAL) + { + std::vector p; + p.reserve(m_ambient_dim); + for (LP_solution::Variable_value_iterator + it_v = sol.variable_values_begin(), + it_v_end = sol.variable_values_end() ; + it_v != it_v_end ; ++it_v) + { + p.push_back(to_double(*it_v)); + } + CGAL_assertion(p.size() == m_ambient_dim); + ret = m_k.construct_point_d_object()(m_ambient_dim, p.begin(), p.end()); + } + else + { + ret = boost::none; + } + + return ret; + } + + // Returns any point of the intersection between aff(voronoi_cell) and a + // tangent space. + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Return value: the point coordinates are expressed in the tsb base + template + boost::optional + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + Point_range_a const& P, + Orthogonal_space_basis const& orthogonal_subspace_basis) const + { + // As we're only interested by aff(v), Q is empty + return compute_voronoi_face_and_tangent_subspace_intersection( + P, std::vector(), + orthogonal_subspace_basis); + } + + std::map get_k_faces_and_neighbor_vertices(Triangulation const& tr) + { + typedef std::map K_faces_and_neighbor_vertices; + + // Map that associate a k-face F and the points of its k+1-cofaces + // (except the points of F). Those points are called its "neighbors". + K_faces_and_neighbor_vertices faces_and_neighbors; + + // Fill faces_and_neighbors + typedef K_faces_and_neighbor_vertices::const_iterator FaN_it; + // Parse cells + for (Tr_finite_full_cell_const_iterator cit = tr.finite_full_cells_begin() ; + cit != tr.finite_full_cells_end() ; ++cit) + { + // Add each k-face to faces_and_neighbors + std::vector booleans(m_ambient_dim + 1, true); + std::fill( + booleans.begin(), + booleans.begin() + m_ambient_dim - m_intrinsic_dim, + false); + do + { + Vertex_set k_face; + std::vector remaining_vertices; + for (int i = 0 ; i < m_ambient_dim + 1 ; ++i) + { + if (booleans[i]) + k_face.insert(cit->vertex(i)); + else + remaining_vertices.push_back(cit->vertex(i)); + } + + faces_and_neighbors[k_face].insert( + remaining_vertices.begin(), remaining_vertices.end()); + + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + + return faces_and_neighbors; + } + + // Returns the dimension of the ith local triangulation + // This is particularly useful for the alpha-TC + int tangent_basis_dim(std::size_t i) const + { + return m_tangent_spaces[i].dimension(); + } + +private: + std::ostream &export_vertices_to_off( + std::ostream & os, std::size_t &num_vertices) const + { + if (m_points.empty()) + { + num_vertices = 0; + return os; + } + + // If m_intrinsic_dim = 1, we output each point two times + // to be able to export each segment as a flat triangle with 3 different + // indices (otherwise, Meshlab detects degenerated simplices) + const int N = (m_intrinsic_dim == 1 ? 2 : 1); + + // Kernel functors + typename K::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + + int num_coords = min(m_ambient_dim, 3); +#ifdef CGAL_MESH_D_EXPORT_NORMALS + OS_container::const_iterator it_os = m_orth_spaces.begin(); +#endif + typename Points::const_iterator it_p = m_points.begin(); + typename Points::const_iterator it_p_end = m_points.end(); + // For each point p + for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) + { + Point const& p = *it_p; + for (int ii = 0 ; ii < N ; ++ii) + { + int i = 0; +#if BETTER_EXPORT_FOR_FLAT_TORUS + // For flat torus + os << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 2)) << " " + << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 3)) << " " + << 1 * CGAL::to_double(coord(p, 1)); +#else + for ( ; i < num_coords ; ++i) + os << CGAL::to_double(coord(p, i)) << " "; +#endif + if (i == 2) + os << "0"; + +#ifdef CGAL_MESH_D_EXPORT_NORMALS + for (i = 0 ; i < num_coords ; ++i) + os << " " << CGAL::to_double(coord(*it_os->begin(), i)); +#endif + os << std::endl; + } +#ifdef CGAL_MESH_D_EXPORT_NORMALS + ++it_os; +#endif + } + + num_vertices = N*m_points.size(); + return os; + } + + template + std::ostream &export_simplices_to_off( + std::ostream & os, std::size_t &num_OFF_simplices, + 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) + const + { + typedef Simplicial_complex::Simplex Simplex; + typedef Simplicial_complex::Simplex_set Simplex_set; + + // If m_intrinsic_dim = 1, each point is output two times + // (see export_vertices_to_off) + num_OFF_simplices = 0; + std::size_t num_maximal_simplices = 0; + + typename Simplex_set::const_iterator it_s = + m_complex.simplex_range().begin(); + typename Simplex_set::const_iterator it_s_end = + m_complex.simplex_range().end(); + // For each simplex + for (; it_s != it_s_end ; ++it_s) + { + Simplex c = *it_s; + ++num_maximal_simplices; + + int color_simplex = -1;// -1=no color, 0=yellow, 1=red, 2=green, 3=blue + if (p_simpl_to_color_in_red && + std::find( + p_simpl_to_color_in_red->begin(), + p_simpl_to_color_in_red->end(), + c) != p_simpl_to_color_in_red->end()) + { + color_simplex = 1; + } + else if (p_simpl_to_color_in_green && + std::find( + p_simpl_to_color_in_green->begin(), + p_simpl_to_color_in_green->end(), + c) != p_simpl_to_color_in_green->end()) + { + color_simplex = 2; + } + else if (p_simpl_to_color_in_blue && + std::find( + p_simpl_to_color_in_blue->begin(), + p_simpl_to_color_in_blue->end(), + c) != p_simpl_to_color_in_blue->end()) + { + color_simplex = 3; + } + + // Gather the triangles here + typedef std::vector Triangles; + Triangles triangles; + + std::size_t num_vertices = c.size(); + // Do not export smaller dimension simplices + if (num_vertices < m_intrinsic_dim + 1) + continue; + + // If m_intrinsic_dim = 1, each point is output two times, + // so we need to multiply each index by 2 + // And if only 2 vertices, add a third one (each vertex is duplicated in + // the file when m_intrinsic dim = 2) + if (m_intrinsic_dim == 1) + { + Indexed_simplex tmp_c; + Indexed_simplex::iterator it = c.begin(); + for (; it != c.end() ; ++it) + tmp_c.insert(*it * 2); + if (num_vertices == 2) + tmp_c.insert(*tmp_c.rbegin() + 1); + + c = tmp_c; + } + + if (num_vertices <= 3) + { + triangles.push_back(c); + } + else + { + // num_vertices >= 4: decompose the simplex in triangles + std::vector booleans(num_vertices, false); + std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true); + do + { + Indexed_simplex triangle; + Indexed_simplex::iterator it = c.begin(); + for (int i = 0; it != c.end() ; ++i, ++it) + { + if (booleans[i]) + triangle.insert(*it); + } + triangles.push_back(triangle); + } while (std::next_permutation(booleans.begin(), booleans.end())); + } + + // For each cell + Triangles::const_iterator it_tri = triangles.begin(); + Triangles::const_iterator it_tri_end = triangles.end(); + for (; it_tri != it_tri_end ; ++it_tri) + { + // Don't export infinite cells + if (is_infinite(*it_tri)) + continue; + + os << 3 << " "; + Indexed_simplex::const_iterator it_point_idx = it_tri->begin(); + for (; it_point_idx != it_tri->end() ; ++it_point_idx) + { + os << *it_point_idx << " "; + } + + if (p_simpl_to_color_in_red || p_simpl_to_color_in_green + || p_simpl_to_color_in_blue) + { + switch (color_simplex) + { + case 0: os << " 255 255 0"; break; + case 1: os << " 255 0 0"; break; + case 2: os << " 0 255 0"; break; + case 3: os << " 0 0 255"; break; + default: os << " 128 128 128"; break; + } + } + + ++num_OFF_simplices; + os << std::endl; + } + } + +#ifdef CGAL_MESH_D_VERBOSE + std::cerr << std::endl + << "==========================================================" + << std::endl + << "Export from complex to OFF:\n" + << " * Number of vertices: " << m_points.size() << std::endl + << " * Total number of maximal simplices: " << num_maximal_simplices + << std::endl + << "==========================================================" + << std::endl; +#endif + + return os; + } + +public: + template + std::ostream &export_to_off( + std::ostream & os, + 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) const + { + if (m_points.empty()) + return os; + + if (m_ambient_dim < 2) + { + std::cerr << "Error: export_to_off => ambient dimension should be >= 2." + << std::endl; + os << "Error: export_to_off => ambient dimension should be >= 2." + << std::endl; + return os; + } + if (m_ambient_dim > 3) + { + std::cerr << "Warning: export_to_off => ambient dimension should be " + "<= 3. Only the first 3 coordinates will be exported." + << std::endl; + } + + if (m_intrinsic_dim < 1 || m_intrinsic_dim > 3) + { + std::cerr << "Error: export_to_off => intrinsic dimension should be " + "between 1 and 3." + << std::endl; + os << "Error: export_to_off => intrinsic dimension should be " + "between 1 and 3." + << std::endl; + return os; + } + + std::stringstream output; + std::size_t num_simplices, num_vertices; + export_vertices_to_off(output, num_vertices); + export_simplices_to_off( + output, num_simplices, p_simpl_to_color_in_red, + p_simpl_to_color_in_green, p_simpl_to_color_in_blue); + +#ifdef CGAL_MESH_D_EXPORT_NORMALS + os << "N"; +#endif + + os << "OFF \n" + << num_vertices << " " + << num_simplices << " " + << "0 \n" + << output.str(); + + return os; + } + +private: + const K m_k; + const int m_intrinsic_dim; + const double m_half_sparsity; + const double m_sq_half_sparsity; + const int m_ambient_dim; + + Points m_points; + + Points_ds m_points_ds; + std::vector m_are_tangent_spaces_computed; + TS_container m_tangent_spaces; + OS_container m_orth_spaces; + +#ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM + Points m_points_for_tse; + Points_ds m_points_ds_for_tse; +#endif + + mutable CGAL::Random m_random_generator; + + Simplicial_complex m_complex; + +}; // /class Tangential_complex + +} // end namespace CGAL + +#endif // MESH_D_H diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index c7a9b58c242..a0105521ce4 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -323,7 +323,7 @@ public: } template - std::size_t num_K_simplices() + std::size_t num_K_simplices() const { std::set k_simplices; From 3160d4ac93ab5c970031d309dd6cfa46a51e4936 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 27 Jan 2016 12:52:49 +0100 Subject: [PATCH 254/269] Oops --- Tangential_complex/include/CGAL/Mesh_d.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h index 7907d2adff9..94ef8b3a613 100644 --- a/Tangential_complex/include/CGAL/Mesh_d.h +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -352,8 +352,6 @@ public: m_k.scaled_vector_d_object()( m_k.point_to_vector_d_object()(*intersection), weight)); } - else - } if (sum_weights > 0) { From 31ee6ddc181905a25298c5daa136b9cf7fc8c928 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 2 Feb 2016 19:13:24 +0100 Subject: [PATCH 255/269] Faster TC refresh + Improved output + Possibility to specify a custom point projector for exporting + Temporary hack to handle some data with borders + Console colors --- .../Tangential_complex/benchmark_tc.cpp | 61 +++- .../Tangential_complex/console_color.h | 68 ++++ .../include/CGAL/Tangential_complex.h | 303 ++++++++++++++---- .../CGAL/Tangential_complex/Point_cloud.h | 15 + .../CGAL/Tangential_complex/utilities.h | 113 +++++++ 5 files changed, 499 insertions(+), 61 deletions(-) create mode 100644 Tangential_complex/benchmark/Tangential_complex/console_color.h diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 5b8f79e1369..b7dc7484bf5 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -6,9 +6,6 @@ # define TBB_USE_THREADING_TOOL #endif - -#include // CJTODO TEST - #include #include #include @@ -16,6 +13,7 @@ #include #include "../../test/Tangential_complex/testing_utilities.h" +#include "console_color.h" #include #include @@ -48,9 +46,14 @@ typedef CGAL::Tangential_complex< //#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 10 // only take one point every TC_INPUT_STRIDES points +//#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points //#define TC_NO_EXPORT + +#ifdef TC_PROTECT_POINT_SET_DELTA +# include // CJTODO TEST +#endif + #ifdef JUST_BENCHMARK_SPATIAL_SEARCH std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); #endif @@ -179,6 +182,19 @@ bool export_to_off( #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 }; + CGAL::Tangential_complex_::S3_to_R3_stereographic_projection + proj_functor(0.2, + Point(4, ¢er_pt[0], ¢er_pt[4]), + k); +#else + CGAL::Identity proj_functor; +#endif + if (tc.intrinsic_dimension() <= 3) { std::stringstream output_filename; @@ -196,7 +212,8 @@ bool 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); + p_simpl_to_color_in_blue, + proj_functor); #endif } else @@ -214,7 +231,9 @@ bool 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); + p_simpl_to_color_in_blue, + NULL, + proj_functor); //#endif } return true; @@ -427,6 +446,13 @@ void make_tc(std::vector &points, //tc.check_correlation_between_inconsistencies_and_fatness(); + // CJTODO TEMP + std::cerr << red << "FINAL CHECK:\n" << white; + tc.number_of_inconsistent_simplices(true); + tc.refresh_tangential_complex(); + tc.number_of_inconsistent_simplices(true); + // CJTODO + //========================================================================= // Export to OFF //========================================================================= @@ -466,7 +492,9 @@ void make_tc(std::vector &points, tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); #endif fix2_time = t.elapsed(); t.reset(); + std::cerr << "Exporting the TC as a Simplicial_complex... "; max_dim = tc.export_TC(complex, false); + std::cerr << "done.\n"; /*std::set > not_delaunay_simplices; if (ambient_dim <= 4) { @@ -485,11 +513,29 @@ void make_tc(std::vector &points, } else { + std::cerr << "Exporting the TC as a Simplicial_complex... "; max_dim = tc.export_TC(complex, false); + std::cerr << "done.\n"; } + std::cerr << "Computing stats of the complex...\n"; complex.display_stats(); + if (intrinsic_dim == 2) + { + std::cerr << "Computing Euler characteristic of the complex...\n"; + std::size_t num_vertices = complex.num_K_simplices<0>(); + std::size_t num_edges = complex.num_K_simplices<1>(); + std::size_t num_triangles = complex.num_K_simplices<2>(); + std::cerr << "Euler characteristic: V - E + F = " + << num_vertices << " - " << num_edges << " + " << num_triangles << " = " + << yellow + << (std::ptrdiff_t) num_vertices + - (std::ptrdiff_t) num_edges + + (std::ptrdiff_t) num_triangles + << white << "\n"; + } + // CJTODO TEMP: Export to OFF with higher-dim simplices colored /*std::set > higher_dim_simplices; complex.get_simplices_matching_test( @@ -552,7 +598,8 @@ void make_tc(std::vector &points, std::cerr << std::endl << "================================================" << std::endl << "Number of vertices: " << tc.number_of_vertices() << std::endl - << "Pure pseudomanifold: " << (is_pure_pseudomanifold ? "YES" : "NO") << std::endl + << "Pure pseudomanifold: " << yellow + << (is_pure_pseudomanifold ? "YES" : "NO") << white << std::endl << "Computation times (seconds): " << std::endl << " * Tangential complex: " << init_time + computation_time << std::endl << " - Init + kd-tree = " << init_time << std::endl diff --git a/Tangential_complex/benchmark/Tangential_complex/console_color.h b/Tangential_complex/benchmark/Tangential_complex/console_color.h new file mode 100644 index 00000000000..50554178257 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/console_color.h @@ -0,0 +1,68 @@ +#ifndef CONSOLE_COLOR_H_ +#define CONSOLE_COLOR_H_ + +#include + +#if defined(WIN32) +#include +#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; +} + +#endif diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 19c8af98a5d..669ce57f4f8 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -84,7 +85,8 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_3 //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE -//#define BETTER_EXPORT_FOR_FLAT_TORUS +//#define CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS +//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 0.96 namespace CGAL { @@ -397,6 +399,7 @@ public: // invalidate the vertex handles stored beside the triangulations m_triangulations.resize(m_points.size()); m_stars.resize(m_points.size()); + m_squared_star_spheres_radii_incl_margin.resize(m_points.size(), FT(-1)); #ifdef CGAL_LINKED_WITH_TBB //m_tr_mutexes.resize(m_points.size()); #endif @@ -511,6 +514,40 @@ public: #endif } + // If the list of perturbed points is provided, it is much faster + template + void refresh_tangential_complex( + Point_indices_range const& perturbed_points_indices) + { +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif + + // ANN tree containing only the perturbed points + Points_ds updated_pts_ds(m_points, perturbed_points_indices); + +#ifdef CGAL_LINKED_WITH_TBB + // Parallel + if (boost::is_convertible::value) + { + tbb::parallel_for(tbb::blocked_range(0, m_points.size()), + Refresh_tangent_triangulation(*this, updated_pts_ds) + ); + } + // Sequential + else +#endif // CGAL_LINKED_WITH_TBB + { + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + refresh_tangent_triangulation(i, updated_pts_ds); + } + +#ifdef CGAL_TC_PROFILING + std::cerr << "Tangential complex refreshed in " << t.elapsed() + << " seconds." << std::endl; +#endif + } + // time_limit in seconds: 0 = no fix to do, < 0 = no time limit Fix_inconsistencies_status fix_inconsistencies_using_perturbation( unsigned int &num_steps, @@ -552,6 +589,7 @@ public: while (!done) { std::size_t num_inconsistent_local_tr = 0; + std::vector updated_points; #ifdef CGAL_TC_PROFILING Wall_clock_timer t_fix_step; @@ -562,13 +600,22 @@ public: if (boost::is_convertible::value) { tbb::combinable num_inconsistencies; + tbb::combinable > tls_updated_points; tbb::parallel_for( tbb::blocked_range(0, m_triangulations.size()), Try_to_solve_inconsistencies_in_a_local_triangulation( - *this, num_inconsistencies) + *this, num_inconsistencies, tls_updated_points) ); num_inconsistent_local_tr = num_inconsistencies.combine(std::plus()); + updated_points = tls_updated_points.combine( + [](std::vector const& x, std::vector const& y) { // CJTODO: C++11 + std::vector res; + res.reserve(x.size() + y.size()); + res.insert(res.end(), x.begin(), x.end()); + res.insert(res.end(), y.begin(), y.end()); + return res; + }); } // Sequential else @@ -577,7 +624,8 @@ public: for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) { num_inconsistent_local_tr += - (try_to_solve_inconsistencies_in_a_local_triangulation(i) ? 1 : 0); + try_to_solve_inconsistencies_in_a_local_triangulation( + i, std::back_inserter(updated_points)); } } @@ -587,42 +635,46 @@ public: #endif #ifdef CGAL_TC_GLOBAL_REFRESH - refresh_tangential_complex(); + if (num_inconsistent_local_tr > 0) + refresh_tangential_complex(updated_points); #endif #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES - std::pair stats_after = - number_of_inconsistent_simplices(false); + if (num_inconsistent_local_tr > 0) + { + std::pair stats_after = + number_of_inconsistent_simplices(false); - std::cerr << std::endl - << "==========================================================" - << std::endl - << "Inconsistencies (detailed stats):\n" - << " * Number of vertices: " << m_points.size() << std::endl - << std::endl - << " * BEFORE fix_inconsistencies_using_perturbation:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " - << stats_before.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second - << " (" << 100. * stats_before.second / stats_before.first << "%)" - << std::endl - /*<< " * Num inconsistent stars: " - << num_inconsistent_local_tr - << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" - << std::endl*/ - << std::endl - << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second - << " (" << 100. * stats_after.second / stats_after.first << "%)" - << std::endl - << "==========================================================" - << std::endl; + std::cerr << std::endl + << "==========================================================" + << std::endl + << "Inconsistencies (detailed stats):\n" + << " * Number of vertices: " << m_points.size() << std::endl + << std::endl + << " * BEFORE fix_inconsistencies_using_perturbation:" << std::endl + << " - Total number of simplices in stars (incl. duplicates): " + << stats_before.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_before.second + << " (" << 100. * stats_before.second / stats_before.first << "%)" + << std::endl + /*<< " * Num inconsistent stars: " + << num_inconsistent_local_tr + << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" + << std::endl*/ + << std::endl + << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl + << " - Total number of simplices in stars (incl. duplicates): " + << stats_after.first << std::endl + << " - Num inconsistent simplices in stars (incl. duplicates): " + << stats_after.second + << " (" << 100. * stats_after.second / stats_after.first << "%)" + << std::endl + << "==========================================================" + << std::endl; - stats_before = stats_after; + stats_before = stats_after; + } #else // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES # ifdef CGAL_TC_VERBOSE @@ -680,7 +732,7 @@ public: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { - // Don't export infinite cells + // Don't check infinite cells if (is_infinite(*it_inc_simplex)) continue; @@ -1186,25 +1238,29 @@ public: #endif } #endif // CGAL_ALPHA_TC - + + template > std::ostream &export_to_off( const Simplicial_complex &complex, std::ostream & os, std::set const *p_simpl_to_color_in_red = NULL, std::set const *p_simpl_to_color_in_green = NULL, - std::set const *p_simpl_to_color_in_blue = NULL) + std::set const *p_simpl_to_color_in_blue = NULL, + ProjectionFunctor const& point_projection = ProjectionFunctor()) const { return export_to_off( os, false, p_simpl_to_color_in_red, p_simpl_to_color_in_green, - p_simpl_to_color_in_blue, &complex); + p_simpl_to_color_in_blue, &complex, point_projection); } - + + template > std::ostream &export_to_off( std::ostream & os, bool color_inconsistencies = false, std::set const *p_simpl_to_color_in_red = NULL, std::set const *p_simpl_to_color_in_green = NULL, std::set const *p_simpl_to_color_in_blue = NULL, - const Simplicial_complex *p_complex = NULL) const + const Simplicial_complex *p_complex = NULL, + ProjectionFunctor const& point_projection = ProjectionFunctor()) const { if (m_points.empty()) return os; @@ -1237,7 +1293,7 @@ public: std::stringstream output; std::size_t num_simplices, num_vertices; - export_vertices_to_off(output, num_vertices); + export_vertices_to_off(output, num_vertices, false, point_projection); if (p_complex) { export_simplices_to_off( @@ -1545,12 +1601,68 @@ private: m_tc.compute_tangent_triangulation(i); } }; + + // Functor for resfresh_tangential_complex function + class Refresh_tangent_triangulation + { + Tangential_complex & m_tc; + Points_ds const& m_updated_pts_ds; + + public: + // Constructor + Refresh_tangent_triangulation( + Tangential_complex &tc, Points_ds const& updated_pts_ds) + : m_tc(tc), m_updated_pts_ds(updated_pts_ds) + { } + + // Constructor + Refresh_tangent_triangulation(const Refresh_tangent_triangulation &ctt) + : m_tc(ctt.m_tc), m_updated_pts_ds(ctt.m_updated_pts_ds) + { } + + // operator() + void operator()(const tbb::blocked_range& r) const + { + for (size_t i = r.begin() ; i != r.end() ; ++i) + m_tc.refresh_tangent_triangulation(i, m_updated_pts_ds); + } + }; #endif // CGAL_LINKED_WITH_TBB bool is_infinite(Indexed_simplex const& s) const { return *s.rbegin() == std::numeric_limits::max(); } + + bool is_one_of_the_coord_far_from_origin( + Point const& p, FT limit, int only_test_the_first_n_coords = -1) const + { + typename K::Construct_cartesian_const_iterator_d ccci = + m_k.construct_cartesian_const_iterator_d_object(); + int c = 1; + for (auto it = ccci(p) ; it != ccci(p, 0) ; ++it, ++c) // CJTODO: C++11 + { + if (*it > limit || *it < -limit) + return true; + + if (only_test_the_first_n_coords > 0 && c == only_test_the_first_n_coords) + break; + } + return false; + } + + bool is_one_of_the_coord_far_from_origin( + Indexed_simplex const& s, FT limit, int only_test_the_first_n_coords = -1) const + { + for (Indexed_simplex::const_iterator it_index = s.begin(); + it_index != s.end() ; ++it_index) + { + if (is_one_of_the_coord_far_from_origin( + compute_perturbed_point(*it_index), limit, only_test_the_first_n_coords)) + return true; + } + return false; + } // Output: "triangulation" is a Regular Triangulation containing at least the // star of "center_pt" @@ -1623,7 +1735,7 @@ private: : std::numeric_limits::max(); #endif - // Insert points until we find a point which is outside "star shere" + // Insert points until we find a point which is outside "star sphere" for (INS_iterator nn_it = ins_range.begin() ; nn_it != ins_range.end() ; ++nn_it) @@ -1709,6 +1821,8 @@ private: } else { + // Note that this uses the perturbed point since it uses + // the points of the local triangulation Tr_point c = power_center( boost::make_transform_iterator( cell->vertices_begin(), @@ -1742,6 +1856,13 @@ private: CGAL::sqrt(*squared_star_sphere_radius_plus_margin) + 2 * m_half_sparsity); #endif + // Save it in `m_squared_star_spheres_radii_incl_margin` + m_squared_star_spheres_radii_incl_margin[i] = + *squared_star_sphere_radius_plus_margin; + } + else + { + m_squared_star_spheres_radii_incl_margin[i] = FT(-1); } } } @@ -1751,6 +1872,36 @@ private: return center_vertex; } + void refresh_tangent_triangulation( + std::size_t i, Points_ds const& updated_pts_ds, bool verbose = false) + { + if (verbose) + std::cerr << "** Refreshing tangent tri #" << i << " **" << std::endl; + + if (m_squared_star_spheres_radii_incl_margin[i] == FT(-1)) + return compute_tangent_triangulation(i, verbose); + + Point center_point = compute_perturbed_point(i); + // Among updated point, what is the closer from our center point? + std::size_t closest_pt_index = + updated_pts_ds.query_ANN(center_point, 1, false).begin()->first; + + typename K::Construct_weighted_point_d k_constr_wp = + m_k.construct_weighted_point_d_object(); + typename K::Power_distance_d k_power_dist = m_k.power_distance_d_object(); + + // Construct a weighted point equivalent to the star sphere + Weighted_point star_sphere = k_constr_wp( + compute_perturbed_point(i), + m_squared_star_spheres_radii_incl_margin[i]); + Weighted_point closest_updated_point = + compute_perturbed_weighted_point(closest_pt_index); + + // Is the "closest point" inside our star sphere? + if (k_power_dist(star_sphere, closest_updated_point) <= FT(0)) + compute_tangent_triangulation(i, verbose); + } + void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) @@ -2640,6 +2791,11 @@ next_face: // CJTODO: improve it like the other "is_simplex_consistent" below bool is_simplex_consistent(Indexed_simplex const& simplex) const { +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(simplex, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + return true; +#endif + // Check if the simplex is in the stars of all its vertices Indexed_simplex::const_iterator it_point_idx = simplex.begin(); // For each point p of the simplex, we parse the incidents cells of p @@ -2680,6 +2836,11 @@ next_face: Indexed_simplex full_simplex = s; full_simplex.insert(center_point); +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(full_simplex, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + return true; +#endif + // Check if the simplex is in the stars of all its vertices Incident_simplex::const_iterator it_point_idx = s.begin(); // For each point p of the simplex, we parse the incidents cells of p @@ -2760,18 +2921,25 @@ next_face: { Tangential_complex & m_tc; tbb::combinable &m_num_inconsistencies; + tbb::combinable > &m_updated_points; public: // Constructor Try_to_solve_inconsistencies_in_a_local_triangulation( - Tangential_complex &tc, tbb::combinable &num_inconsistencies) - : m_tc(tc), m_num_inconsistencies(num_inconsistencies) + Tangential_complex &tc, + tbb::combinable &num_inconsistencies, + tbb::combinable > &updated_points) + : m_tc(tc), + m_num_inconsistencies(num_inconsistencies), + m_updated_points(updated_points) {} // Constructor Try_to_solve_inconsistencies_in_a_local_triangulation( const Compute_tangent_triangulation &ctt) - : m_tc(ctt.m_tc), m_num_inconsistencies(ctt.m_num_inc) + : m_tc(ctt.m_tc), + m_num_inconsistencies(ctt.m_num_inconsistencies), + m_updated_points(ctt.m_updated_points) {} // operator() @@ -2780,7 +2948,8 @@ next_face: for( size_t i = r.begin() ; i != r.end() ; ++i) { m_num_inconsistencies.local() += - m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(i); + m_tc.try_to_solve_inconsistencies_in_a_local_triangulation( + i, std::back_inserter(m_updated_points.local())); } } }; @@ -2861,8 +3030,11 @@ next_face: #endif // CGAL_TC_PERTURB_POSITION } + // Return true if inconsistencies were found + template bool try_to_solve_inconsistencies_in_a_local_triangulation( - std::size_t tr_index) + std::size_t tr_index, + OutputIt perturbed_pts_indices = CGAL::Emptyset_iterator()) { bool is_inconsistent = false; @@ -2903,6 +3075,7 @@ next_face: it != c.end() ; ++it) { perturb(*it); + *perturbed_pts_indices++ = *it; } # if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -2930,6 +3103,7 @@ next_face: std::size_t idx = (*it_c)->vertex(k)->data();*/ perturb(idx); + *perturbed_pts_indices++ = idx; # if !defined(CGAL_TC_GLOBAL_REFRESH) refresh_tangential_complex(); @@ -2962,6 +3136,7 @@ next_face: it != the_1_star.end() ; ++it) { perturb(*it); + *perturbed_pts_indices++ = *it; } # if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -3026,6 +3201,7 @@ next_face: ++it) { perturb(*it); + *perturbed_pts_indices++ = *it; } # if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -3045,12 +3221,16 @@ next_face: is_inconsistent = true; int rnd = m_random_generator.get_int(0, static_cast(c.size())); if (rnd == 0) + { perturb(tr_index); + *perturbed_pts_indices++ = tr_index; + } else { Indexed_simplex::const_iterator it_idx = c.begin(); std::advance(it_idx, rnd - 1); perturb(*it_idx); + *perturbed_pts_indices++ = *it_idx; } # if !defined(CGAL_TC_GLOBAL_REFRESH) @@ -3156,9 +3336,11 @@ next_face: return is_inconsistent; } + template > std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices, - bool use_perturbed_points = false) const + bool use_perturbed_points = false, + ProjectionFunctor const& point_projection = ProjectionFunctor()) const { if (m_points.empty()) { @@ -3184,11 +3366,12 @@ next_face: // For each point p for (std::size_t i = 0 ; it_p != it_p_end ; ++it_p, ++i) { - Point p = (use_perturbed_points ? compute_perturbed_point(i) : *it_p); + Point p = point_projection( + use_perturbed_points ? compute_perturbed_point(i) : *it_p); for (int ii = 0 ; ii < N ; ++ii) { int i = 0; -#if BETTER_EXPORT_FOR_FLAT_TORUS +#if CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS // For flat torus os << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 2)) << " " << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 3)) << " " @@ -4104,11 +4287,17 @@ next_face: star_using_triangles.end(); for ( ; it_simplex != it_simplex_end ; ++it_simplex) { - // Don't export infinite cells - if (is_infinite(it_simplex->first)) - continue; - const Indexed_simplex &c = it_simplex->first; + + // Don't export infinite cells + if (is_infinite(c)) + continue; + +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(c, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + continue; +#endif + int color_simplex = it_simplex->second; std::stringstream sstr_c; @@ -4285,6 +4474,11 @@ public: // Don't export infinite cells if (is_infinite(*it_tri)) continue; + +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(*it_tri, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + continue; +#endif os << 3 << " "; Indexed_simplex::const_iterator it_point_idx = it_tri->begin(); @@ -4427,6 +4621,7 @@ private: Tr_container m_triangulations; // Contains the triangulations // and their center vertex Stars_container m_stars; + std::vector m_squared_star_spheres_radii_incl_margin; #ifdef CGAL_LINKED_WITH_TBB //std::vector m_tr_mutexes; #endif diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 6a273ce28fe..293b61fa520 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -88,6 +88,21 @@ public: m_tree.build(); } + /// Constructor + template + 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, diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index e1472ae8d95..ecaf69a734b 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -371,6 +371,119 @@ namespace Tangential_complex_ { return output_basis; } + // 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 + 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 + 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 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 + 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 m_R4toS3; + S3_to_R3_stereographic_projection m_S3toR3; + K const& m_k; + }; + // CJTODO: use CGAL::Combination_enumerator (cf. Tangential_complex.h) // Compute all the k-combinations of elements // Output_iterator::value_type must be std::set > From bbfcb5baa290191f0cb1342d6294c7246a74cd37 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 3 Feb 2016 18:19:12 +0100 Subject: [PATCH 256/269] Improve console output & checks + missing include --- .../Tangential_complex/benchmark_tc.cpp | 99 ++- .../include/CGAL/Tangential_complex.h | 382 ++++++------ .../Tangential_complex/Simplicial_complex.h | 55 +- .../CGAL}/Tangential_complex/console_color.h | 13 + .../CGAL/Tangential_complex/protected_sets.h | 564 ++++++++++++++++++ 5 files changed, 855 insertions(+), 258 deletions(-) rename Tangential_complex/{benchmark => include/CGAL}/Tangential_complex/console_color.h (83%) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/protected_sets.h diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index b7dc7484bf5..f9462605ce5 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -13,7 +13,6 @@ #include #include "../../test/Tangential_complex/testing_utilities.h" -#include "console_color.h" #include #include @@ -320,7 +319,7 @@ void make_tc(std::vector &points, 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() << std::endl; + << num_points_before << " / " << points.size() << "\n"; } #ifdef TC_PROTECT_POINT_SET_DELTA @@ -338,7 +337,7 @@ void make_tc(std::vector &points, # ifdef CGAL_TC_PROFILING std::cerr << "Point set protected in " << t_protection.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; # endif std::cerr << "Number of points after PROTECTION: " << points.size() << "\n"; @@ -446,12 +445,15 @@ void make_tc(std::vector &points, //tc.check_correlation_between_inconsistencies_and_fatness(); - // CJTODO TEMP - std::cerr << red << "FINAL CHECK:\n" << white; - tc.number_of_inconsistent_simplices(true); - tc.refresh_tangential_complex(); - tc.number_of_inconsistent_simplices(true); - // CJTODO + // 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 (tc.number_of_inconsistent_simplices(true).second != num_inc) + // std::cerr << red << "FINAL CHECK: FAILED.\n" << white; + //else + // std::cerr << green << "FINAL CHECK: PASSED.\n" << white; + //========================================================================= // Export to OFF @@ -492,9 +494,7 @@ void make_tc(std::vector &points, tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); #endif fix2_time = t.elapsed(); t.reset(); - std::cerr << "Exporting the TC as a Simplicial_complex... "; max_dim = tc.export_TC(complex, false); - std::cerr << "done.\n"; /*std::set > not_delaunay_simplices; if (ambient_dim <= 4) { @@ -513,23 +513,20 @@ void make_tc(std::vector &points, } else { - std::cerr << "Exporting the TC as a Simplicial_complex... "; max_dim = tc.export_TC(complex, false); - std::cerr << "done.\n"; } - std::cerr << "Computing stats of the complex...\n"; complex.display_stats(); if (intrinsic_dim == 2) { - std::cerr << "Computing Euler characteristic of the complex...\n"; + std::cerr << "\nComputing Euler characteristic of the complex...\n"; std::size_t num_vertices = complex.num_K_simplices<0>(); std::size_t num_edges = complex.num_K_simplices<1>(); std::size_t num_triangles = complex.num_K_simplices<2>(); std::cerr << "Euler characteristic: V - E + F = " << num_vertices << " - " << num_edges << " + " << num_triangles << " = " - << yellow + << blue << (std::ptrdiff_t) num_vertices - (std::ptrdiff_t) num_edges + (std::ptrdiff_t) num_triangles @@ -549,7 +546,10 @@ void make_tc(std::vector &points, // Collapse //=========================================================================== if (collapse) + { complex.collapse(max_dim); + complex.display_stats(); + } //=========================================================================== // Is the result a pure pseudomanifold? @@ -567,9 +567,6 @@ void make_tc(std::vector &points, &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, &unconnected_stars_simplices); - // Stats about the simplices - complex.display_stats(); - //=========================================================================== // Export to OFF //=========================================================================== @@ -583,10 +580,10 @@ void make_tc(std::vector &points, &wrong_dim_simplices, &wrong_number_of_cofaces_simplices, &unconnected_stars_simplices); std::cerr - << " OFF colors:" << std::endl - << " * Red: wrong dim simplices" << std::endl - << " * Green: wrong number of cofaces simplices" << std::endl - << " * Blue: not-connected stars" << std::endl; + << " 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(); } @@ -595,26 +592,23 @@ void make_tc(std::vector &points, // Display info //=========================================================================== - std::cerr << std::endl - << "================================================" << std::endl - << "Number of vertices: " << tc.number_of_vertices() << std::endl - << "Pure pseudomanifold: " << yellow - << (is_pure_pseudomanifold ? "YES" : "NO") << white << 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 perturb): " << export_before_time << std::endl + 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") << std::endl - << " * Fix inconsistencies 2: " << fix2_time << std::endl - << " * Export to OFF (after perturb): " << export_after_perturb_time << std::endl - << " * Export to OFF (after fix2): "<< export_after_fix2_time << std::endl + << (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 << std::endl - << "================================================" << std::endl - << std::endl; + << export_after_collapse_time << "\n" + << "================================================\n"; //=========================================================================== // Export info @@ -651,7 +645,7 @@ int main() unsigned int seed = static_cast(time(NULL)); CGAL::default_random = CGAL::Random(seed); - std::cerr << "Random seed = " << seed << std::endl; + std::cerr << "Random seed = " << seed << "\n"; std::ifstream script_file; script_file.open(BENCHMARK_SCRIPT_FILENAME); @@ -680,7 +674,7 @@ int main() num_threads > 0 ? num_threads : tbb::task_scheduler_init::automatic); #endif - std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' found." << std::endl; + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' found.\n"; script_file.seekg(0); while (script_file.good()) { @@ -690,10 +684,10 @@ int main() { boost::replace_all(line, "\t", " "); boost::trim_all(line); - std::cerr << std::endl << std::endl; - std::cerr << "*****************************************" << std::endl; - std::cerr << "******* " << line << std::endl; - std::cerr << "*****************************************" << std::endl; + std::cerr << "\n\n"; + std::cerr << "*****************************************\n"; + std::cerr << "******* " << line << "\n"; + std::cerr << "*****************************************\n"; std::stringstream sstr(line); std::string input; @@ -747,7 +741,7 @@ int main() CGAL_TC_SET_PERFORMANCE_DATA("Num_threads", "N/A"); #endif - std::cerr << std::endl << "TC #" << i << "..." << std::endl; + std::cerr << "\nTC #" << i << "...\n"; #ifdef CGAL_TC_PROFILING Wall_clock_timer t_gen; @@ -833,7 +827,7 @@ int main() #ifdef CGAL_TC_PROFILING std::cerr << "Point set generated/loaded in " << t_gen.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; #endif if (!points.empty()) @@ -850,13 +844,12 @@ int main() sparsity, perturb=='Y', add_high_dim_simpl=='Y', collapse=='Y', time_limit_for_perturb, input.c_str()); - std::cerr << "TC #" << i++ << " done." << std::endl; - std::cerr << std::endl << "---------------------------------" - << std::endl << std::endl; + std::cerr << "TC #" << i++ << " done.\n"; + std::cerr << "\n---------------------------------\n"; } else { - std::cerr << "TC #" << i++ << ": no points loaded." << std::endl; + std::cerr << "TC #" << i++ << ": no points loaded.\n"; } XML_perf_data::commit(); @@ -872,7 +865,7 @@ int main() // Or not script? else { - std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found." << std::endl; + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found.\n"; } system("pause"); diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 669ce57f4f8..70efc0ec772 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -26,6 +26,7 @@ #include #include #include +#include "CGAL/Tangential_complex/console_color.h" #include #include @@ -86,13 +87,13 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE //#define CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS -//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 0.96 +#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 1.9 // 0.95 namespace CGAL { using namespace Tangential_complex_; -enum Fix_inconsistencies_status { +enum Fix_inconsistencies_status { TC_FIXED = 0, TIME_LIMIT_REACHED, FIX_NOT_PERFORMED }; class Vertex_data @@ -371,7 +372,7 @@ public: { #ifdef CGAL_TC_PERTURB_TANGENT_SPACE std::cerr << "Cannot use CGAL_TC_PERTURB_TANGENT_SPACE and set " - << " tangent spaces manually at the same time" << std::endl; + << " tangent spaces manually at the same time\n"; std::exit(EXIT_FAILURE); #endif #ifdef CGAL_TC_EXPORT_NORMALS @@ -390,6 +391,11 @@ public: void compute_tangential_complex() { +#ifdef CGAL_TC_PERFORM_EXTRA_CHECKS + std::cerr << red << "WARNING: CGAL_TC_PERFORM_EXTRA_CHECKS is defined." + << "Computation might be slower than usual.\n" << white; +#endif + #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) Wall_clock_timer t; #endif @@ -433,7 +439,7 @@ public: #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) std::cerr << "Tangential complex computed in " << t.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; #endif } @@ -489,6 +495,10 @@ public: void refresh_tangential_complex() { +#if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) + std::cerr << yellow << "\nRefreshing TC... " << white; +#endif + #ifdef CGAL_TC_PROFILING Wall_clock_timer t; #endif @@ -509,8 +519,10 @@ public: } #ifdef CGAL_TC_PROFILING - std::cerr << "Tangential complex refreshed in " << t.elapsed() - << " seconds." << std::endl; + std::cerr << yellow << "done in " << t.elapsed() + << " seconds.\n" << white; +#elif defined(CGAL_TC_VERBOSE) + std::cerr << yellow << "done.\n" << white; #endif } @@ -519,6 +531,10 @@ public: void refresh_tangential_complex( Point_indices_range const& perturbed_points_indices) { +#if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) + std::cerr << yellow << "\nRefreshing TC... " << white; +#endif + #ifdef CGAL_TC_PROFILING Wall_clock_timer t; #endif @@ -543,17 +559,19 @@ public: } #ifdef CGAL_TC_PROFILING - std::cerr << "Tangential complex refreshed in " << t.elapsed() - << " seconds." << std::endl; + std::cerr << yellow << "done in " << t.elapsed() + << " seconds.\n" << white; +#elif defined(CGAL_TC_VERBOSE) + std::cerr << yellow << "done.\n" << white; #endif } // time_limit in seconds: 0 = no fix to do, < 0 = no time limit Fix_inconsistencies_status fix_inconsistencies_using_perturbation( unsigned int &num_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, + std::size_t &initial_num_inconsistent_stars, + std::size_t &best_num_inconsistent_stars, + std::size_t &final_num_inconsistent_stars, double time_limit = -1.) { if (time_limit == 0.) @@ -561,34 +579,46 @@ public: Wall_clock_timer t; -#ifdef CGAL_TC_VERBOSE - std::cerr << "Fixing inconsistencies..." << std::endl; -#endif - #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES std::pair stats_before = number_of_inconsistent_simplices(false); # ifdef CGAL_TC_VERBOSE std::cerr << "Initial number of inconsistencies: " - << stats_before.second << std::endl; + << stats_before.second << "\n"; # endif if (stats_before.second == 0) { # ifdef CGAL_TC_VERBOSE - std::cerr << "Nothing to fix." << std::endl; + std::cerr << "Nothing to fix.\n"; # endif return TC_FIXED; } #endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES bool done = false; - best_num_inconsistent_local_tr = m_triangulations.size(); + best_num_inconsistent_stars = m_triangulations.size(); num_steps = 0; while (!done) { - std::size_t num_inconsistent_local_tr = 0; +#ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES + std::cerr + << "\nBefore fix step:\n" + << " * Total number of simplices in stars (incl. duplicates): " + << stats_before.first << "\n" + << " * Num inconsistent simplices in stars (incl. duplicates): " + << red << stats_before.second << white + << " (" << 100. * stats_before.second / stats_before.first << "%)\n"; +#endif + +#if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) + std::cerr << yellow + << "\nAttempt to fix inconsistencies using perturbations - step #" + << num_steps + 1 << "... " << white; +#endif + + std::size_t num_inconsistent_stars = 0; std::vector updated_points; #ifdef CGAL_TC_PROFILING @@ -606,7 +636,7 @@ public: Try_to_solve_inconsistencies_in_a_local_triangulation( *this, num_inconsistencies, tls_updated_points) ); - num_inconsistent_local_tr = + num_inconsistent_stars = num_inconsistencies.combine(std::plus()); updated_points = tls_updated_points.combine( [](std::vector const& x, std::vector const& y) { // CJTODO: C++11 @@ -623,93 +653,83 @@ public: { for (std::size_t i = 0 ; i < m_triangulations.size() ; ++i) { - num_inconsistent_local_tr += + num_inconsistent_stars += try_to_solve_inconsistencies_in_a_local_triangulation( i, std::back_inserter(updated_points)); } } + double fix_step_time = t_fix_step.elapsed(); + +#if defined(CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES) || defined(CGAL_TC_VERBOSE) + std::cerr + << "\nEncountered during fix:\n" + << " * Num stars containing inconsistent simplices: " + << red << num_inconsistent_stars << white + << " (" << 100. * num_inconsistent_stars / m_points.size() << "%)\n"; +#endif + #ifdef CGAL_TC_PROFILING - std::cerr << "Attempt to fix inconsistencies: " << t_fix_step.elapsed() - << " seconds." << std::endl; + std::cerr << yellow << "done in " << fix_step_time + << " seconds.\n" << white; +#elif defined(CGAL_TC_VERBOSE) + std::cerr << yellow << "done.\n" << white; #endif #ifdef CGAL_TC_GLOBAL_REFRESH - if (num_inconsistent_local_tr > 0) + if (num_inconsistent_stars > 0) refresh_tangential_complex(updated_points); + +# ifdef CGAL_TC_PERFORM_EXTRA_CHECKS + // DEBUGGING: confirm that all stars were actually refreshed + std::size_t num_inc_1 = number_of_inconsistent_simplices(false).second; + refresh_tangential_complex(); + std::size_t num_inc_2 = number_of_inconsistent_simplices(false).second; + if (num_inc_1 != num_inc_2) + std::cerr << red << "REFRESHMENT CHECK: FAILED. (" + << num_inc_1 << " vs " << num_inc_2 << ")\n" << white; + else + std::cerr << green << "REFRESHMENT CHECK: PASSED.\n" << white; +# endif #endif #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES - if (num_inconsistent_local_tr > 0) - { - std::pair stats_after = - number_of_inconsistent_simplices(false); + std::pair stats_after = + number_of_inconsistent_simplices(false); - std::cerr << std::endl - << "==========================================================" - << std::endl - << "Inconsistencies (detailed stats):\n" - << " * Number of vertices: " << m_points.size() << std::endl - << std::endl - << " * BEFORE fix_inconsistencies_using_perturbation:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " - << stats_before.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second - << " (" << 100. * stats_before.second / stats_before.first << "%)" - << std::endl - /*<< " * Num inconsistent stars: " - << num_inconsistent_local_tr - << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" - << std::endl*/ - << std::endl - << " * AFTER fix_inconsistencies_using_perturbation:" << std::endl - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second - << " (" << 100. * stats_after.second / stats_after.first << "%)" - << std::endl - << "==========================================================" - << std::endl; + std::cerr + << "\nAfter fix:\n" + << " * Total number of simplices in stars (incl. duplicates): " + << stats_after.first << "\n" + << " * Num inconsistent simplices in stars (incl. duplicates): " + << red << stats_after.second << white + << " (" << 100. * stats_after.second / stats_after.first << "%)\n"; - stats_before = stats_after; - } - -#else // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES -# ifdef CGAL_TC_VERBOSE - std::cerr << std::endl - << "==========================================================" - << std::endl - << "fix_inconsistencies_using_perturbation():\n" - << " * " << m_points.size() << " vertices" << std::endl - << " * " << num_inconsistent_local_tr - << " (" << 100. * num_inconsistent_local_tr / m_points.size() << "%)" - << " inconsistent stars encountered" << std::endl - << "==========================================================" - << std::endl; -# endif -#endif // CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES + stats_before = stats_after; +#endif if (num_steps == 0) - initial_num_inconsistent_local_tr = num_inconsistent_local_tr; + initial_num_inconsistent_stars = num_inconsistent_stars; - if (num_inconsistent_local_tr < best_num_inconsistent_local_tr) - best_num_inconsistent_local_tr = num_inconsistent_local_tr; + if (num_inconsistent_stars < best_num_inconsistent_stars) + best_num_inconsistent_stars = num_inconsistent_stars; - final_num_inconsistent_local_tr = num_inconsistent_local_tr; + final_num_inconsistent_stars = num_inconsistent_stars; ++num_steps; - done = (num_inconsistent_local_tr == 0); + done = (num_inconsistent_stars == 0); if (!done && time_limit > 0. && t.elapsed() > time_limit) { #ifdef CGAL_TC_VERBOSE - std::cerr << "Time limit reached." << std::endl; + std::cerr << red << "Time limit reached.\n" << white; #endif return TIME_LIMIT_REACHED; } } +#ifdef CGAL_TC_VERBOSE + std::cerr << green << "Fixed!\n" << white; +#endif return TC_FIXED; } @@ -748,19 +768,17 @@ public: if (verbose) { - std::cerr << std::endl - << "==========================================================" - << std::endl + std::cerr + << "\n==========================================================\n" << "Inconsistencies:\n" - << " * Number of vertices: " << m_points.size() << std::endl + << " * Number of vertices: " << m_points.size() << "\n" << " * Total number of simplices in stars (incl. duplicates): " - << num_simplices << std::endl + << num_simplices << "\n" << " * Number of inconsistent simplices in stars (incl. duplicates): " - << num_inconsistent_simplices << std::endl + << num_inconsistent_simplices << "\n" << " * Percentage of inconsistencies: " - << 100. * num_inconsistent_simplices / num_simplices << "%" << std::endl - << "==========================================================" - << std::endl; + << 100. * num_inconsistent_simplices / num_simplices << "%\n" + << "==========================================================\n"; } return std::make_pair(num_simplices, num_inconsistent_simplices); @@ -770,6 +788,14 @@ public: int export_TC(Simplicial_complex &complex, bool export_infinite_simplices = false) const { +#if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) + std::cerr << yellow + << "\nExporting the TC as a Simplicial_complex... " << white; +#endif +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t; +#endif + int max_dim = -1; // For each triangulation @@ -792,6 +818,14 @@ public: complex.add_simplex(c); } } + +#ifdef CGAL_TC_PROFILING + std::cerr << yellow << "done in " << t.elapsed() + << " seconds.\n" << white; +#elif defined(CGAL_TC_VERBOSE) + std::cerr << yellow << "done.\n" << white; +#endif + return max_dim; } @@ -824,12 +858,11 @@ public: number_of_inconsistent_simplices(false); std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl + << stats_after.first << "\n" << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << std::endl + << stats_after.second << "\n" << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%" - << std::endl; + << 100. * stats_after.second / stats_after.first << "%\n"; } // Returns true if some inconsistencies were found @@ -840,12 +873,11 @@ public: number_of_inconsistent_simplices(false); std::cerr << "BEFORE check_and_solve_inconsistencies_by_filtering_simplices_out():\n" << " - Total number of simplices in stars (incl. duplicates): " - << stats_before.first << std::endl + << stats_before.first << "\n" << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second << std::endl + << stats_before.second << "\n" << " - Percentage of inconsistencies: " - << 100. * stats_before.second / stats_before.first << "%" - << std::endl; + << 100. * stats_before.second / stats_before.first << "%\n"; bool inconsistencies_found = false; @@ -861,12 +893,11 @@ public: number_of_inconsistent_simplices(false); std::cerr << "AFTER check_and_solve_inconsistencies_by_filtering_simplices_out():\n" << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << std::endl + << stats_after.first << "\n" << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << std::endl + << stats_after.second << "\n" << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%" - << std::endl; + << 100. * stats_after.second / stats_after.first << "%\n"; return inconsistencies_found; } @@ -1024,7 +1055,7 @@ public: #endif #ifdef CGAL_TC_VERBOSE - std::cerr << "Fixing inconsistencies using alpha TC..." << std::endl; + std::cerr << "Fixing inconsistencies using alpha TC...\n"; #endif //------------------------------------------------------------------------- @@ -1054,9 +1085,9 @@ public: << "Num inconsistent simplices found when filling the priority queues: " << num_inconsistent_simplices; # ifdef CGAL_TC_PROFILING - std::cerr << " (" << t_pq.elapsed() << " s)" << std::endl; + std::cerr << " (" << t_pq.elapsed() << " s)\n"; # endif - std::cerr << std::endl; + std::cerr << "\n"; #endif //------------------------------------------------------------------------- @@ -1157,7 +1188,7 @@ public: if (is_simplex_in_star(ii, z)) { is_this_simplex_somewhere = true; - std::cerr << "The simplex is in star #" << ii << std::endl; + std::cerr << "The simplex is in star #" << ii << "\n"; break; } } @@ -1168,28 +1199,28 @@ public: if (m_ambient_dim <= 3) { if (is_simplex_in_the_ambient_delaunay(full_s)) - std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + std::cerr << "The simplex is in the ambiant Delaunay.\n"; else - std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + std::cerr << "The simplex is NOT in the ambiant Delaunay.\n"; std::cerr << "Checking simplices of the star #" - << saa.m_center_point_index << std::endl; + << saa.m_center_point_index << "\n"; Star const& star = m_stars[saa.m_center_point_index]; for (Star::const_iterator is = star.begin(), is_end = star.end() ; is != is_end ; ++is) { if (is_simplex_in_the_ambient_delaunay(*is)) - std::cerr << "The simplex is in the ambiant Delaunay." << std::endl; + std::cerr << "The simplex is in the ambiant Delaunay.\n"; else { - std::cerr << "The simplex is NOT in the ambiant Delaunay." << std::endl; + std::cerr << "The simplex is NOT in the ambiant Delaunay.\n"; for(auto ii : *is) // CJTODO C++11 perturb(ii); } } } - std::cerr << "Perturbing the points..." << std::endl; + std::cerr << "Perturbing the points...\n"; perturb(saa.m_center_point_index); for(auto ii : saa.m_simplex) // CJTODO C++11 perturb(ii); @@ -1205,7 +1236,7 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << "Num inconsistent simplices found when filling the priority queues: " - << num_inconsistent_simplices << std::endl; + << num_inconsistent_simplices << "\n"; #endif } // CJTODO TEMP @@ -1234,7 +1265,7 @@ public: #ifdef CGAL_TC_PROFILING std::cerr << "Tangential complex fixed in " << t.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; #endif } #endif // CGAL_ALPHA_TC @@ -1267,27 +1298,22 @@ public: if (m_ambient_dim < 2) { - std::cerr << "Error: export_to_off => ambient dimension should be >= 2." - << std::endl; - os << "Error: export_to_off => ambient dimension should be >= 2." - << std::endl; + std::cerr << "Error: export_to_off => ambient dimension should be >= 2.\n"; + os << "Error: export_to_off => ambient dimension should be >= 2.\n"; return os; } if (m_ambient_dim > 3) { std::cerr << "Warning: export_to_off => ambient dimension should be " - "<= 3. Only the first 3 coordinates will be exported." - << std::endl; + "<= 3. Only the first 3 coordinates will be exported.\n"; } if (m_intrinsic_dim < 1 || m_intrinsic_dim > 3) { std::cerr << "Error: export_to_off => intrinsic dimension should be " - "between 1 and 3." - << std::endl; + "between 1 and 3.\n"; os << "Error: export_to_off => intrinsic dimension should be " - "between 1 and 3." - << std::endl; + "between 1 and 3.\n"; return os; } @@ -1542,16 +1568,15 @@ public: #ifdef CGAL_TC_VERBOSE std::cerr << (incorrect_simplices->empty() ? "OK " : "ERROR ") - << "check_if_all_simplices_are_in_the_ambient_delaunay:" - << std::endl + << "check_if_all_simplices_are_in_the_ambient_delaunay:\n" << " Number of simplices in ambient RT: " << amb_dt_simplices.size() - << std::endl + << "\n" << " Number of unique simplices in TC stars: " << p_simplices->size() - << std::endl + << "\n" << " Number of infinite full cells in TC stars: " << num_infinite_cells - << std::endl + << "\n" << " Number of wrong simplices: " << incorrect_simplices->size() - << std::endl; + << "\n"; #endif return incorrect_simplices->empty(); } @@ -1657,6 +1682,10 @@ private: for (Indexed_simplex::const_iterator it_index = s.begin(); it_index != s.end() ; ++it_index) { + // Infinite vertex? Much too far! + if (*it_index == std::numeric_limits::max()) + return true; + if (is_one_of_the_coord_far_from_origin( compute_perturbed_point(*it_index), limit, only_test_the_first_n_coords)) return true; @@ -1707,7 +1736,7 @@ private: center_vertex = triangulation.insert(proj_wp); center_vertex->data() = i; if (verbose) - std::cerr << "* Inserted point #" << i << std::endl; + std::cerr << "* Inserted point #" << i << "\n"; #ifdef CGAL_TC_VERY_VERBOSE std::size_t num_attempts_to_insert_points = 1; @@ -1797,7 +1826,7 @@ private: ++num_inserted_points; #endif if (verbose) - std::cerr << "* Inserted point #" << neighbor_point_idx << std::endl; + std::cerr << "* Inserted point #" << neighbor_point_idx << "\n"; vh->data() = neighbor_point_idx; @@ -1876,7 +1905,7 @@ private: std::size_t i, Points_ds const& updated_pts_ds, bool verbose = false) { if (verbose) - std::cerr << "** Refreshing tangent tri #" << i << " **" << std::endl; + std::cerr << "** Refreshing tangent tri #" << i << " **\n"; if (m_squared_star_spheres_radii_incl_margin[i] == FT(-1)) return compute_tangent_triangulation(i, verbose); @@ -1905,8 +1934,8 @@ private: void compute_tangent_triangulation(std::size_t i, bool verbose = false) { if (verbose) - std::cerr << "** Computing tangent tri #" << i << " **" << std::endl; - //std::cerr << "***********************************************" << std::endl; + std::cerr << "** Computing tangent tri #" << i << " **\n"; + //std::cerr << "***********************************************\n"; // No need to lock the mutex here since this will not be called while // other threads are perturbing the positions @@ -1915,7 +1944,7 @@ private: #if defined(CGAL_TC_VERY_VERBOSE) && defined(CGAL_ALPHA_TC) std::cerr << "Base dimension, incl. thickening vectors: " - << tsb.dimension() << std::endl; + << tsb.dimension() << "\n"; #endif // Estimate the tangent space if (!m_are_tangent_spaces_computed[i]) @@ -2405,7 +2434,7 @@ next_face: //Vector n = m_k.point_to_vector_d_object()(p); //n = scaled_vec(n, FT(1)/sqrt(sqlen(n))); - //std::cerr << "IP = " << scalar_pdct(n, ts[0]) << " & " << scalar_pdct(n, ts[1]) << std::endl; + //std::cerr << "IP = " << scalar_pdct(n, ts[0]) << " & " << scalar_pdct(n, ts[1]) << "\n"; return tsb; @@ -3387,7 +3416,7 @@ next_face: for (i = 0 ; i < num_coords ; ++i) os << " " << CGAL::to_double(coord(*it_os->begin(), i)); #endif - os << std::endl; + os << "\n"; } #ifdef CGAL_TC_EXPORT_NORMALS ++it_os; @@ -3538,7 +3567,7 @@ next_face: std::size_t neighbor_point_idx = nn_it->first; FT point_to_Cp_power_sqdist = k_power_dist( global_Cp, compute_perturbed_weighted_point(neighbor_point_idx)); - //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP + //std::cerr << point_to_Cp_power_sqdist << "\n"; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_Cp_power_sqdist <= FT(0) && inconsistent_simplex.find(neighbor_point_idx) == @@ -3589,13 +3618,13 @@ next_face: switch(sid) { case ON_NEGATIVE_SIDE: - std::cerr << "ON_NEGATIVE_SIDE" << std::endl; // CJTODO TEMP + std::cerr << "ON_NEGATIVE_SIDE\n"; // CJTODO TEMP break; case ON_POSITIVE_SIDE: - std::cerr << "ON_POSITIVE_SIDE" << std::endl; // CJTODO TEMP + std::cerr << "ON_POSITIVE_SIDE\n"; // CJTODO TEMP break; case ON_ORIENTED_BOUNDARY: - std::cerr << "ON_ORIENTED_BOUNDARY" << std::endl; // CJTODO TEMP + std::cerr << "ON_ORIENTED_BOUNDARY\n"; // CJTODO TEMP break; } }*/ @@ -3614,9 +3643,9 @@ next_face: std::cerr << q_idx << " "; std::copy(s.begin(), s.end(), std::ostream_iterator(std::cerr, " ")); - std::cerr << std::endl; + std::cerr << "\n"; } - std::cerr << std::endl; + std::cerr << "\n"; }*/ // CJTODO TEMP DEBUG @@ -3636,7 +3665,7 @@ next_face: k_scalar_pdct(m_orth_spaces[q_idx][0], pq)); csv_stream << inside_pt_indices.size() << " ; "; csv_stream << dot_product_1 << " ; " << dot_product_2; - csv_stream << std::endl; + csv_stream << "\n"; }*/ // CJTODO TEMP DEBUG @@ -3660,8 +3689,8 @@ next_face: std::cerr << dot_products_between_normals << ", "; //csv_stream << " ; " <first; FT point_to_C_power_sqdist = k_power_dist(C, compute_perturbed_weighted_point(neighbor_point_idx)); - //std::cerr << point_to_Cp_power_sqdist << std::endl; // CJTODO TEMP + //std::cerr << point_to_Cp_power_sqdist << "\n"; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_C_power_sqdist <= FT(-0.000001) && inconsistent_simplex.find(neighbor_point_idx) == @@ -3824,7 +3853,7 @@ next_face: k_scalar_pdct(m_orth_spaces[*it_point_idx][0], pq)); csv_stream << "0 ; "; csv_stream << dot_product_1 << " ; " << dot_product_2; - csv_stream << std::endl; + csv_stream << "\n"; }*/ } @@ -4329,37 +4358,33 @@ next_face: } } ++num_OFF_simplices; - os << std::endl; + os << "\n"; } if (is_star_inconsistent) ++num_inconsistent_stars; } #ifdef CGAL_TC_VERBOSE - std::cerr << std::endl - << "==========================================================" - << std::endl + std::cerr + << "\n==========================================================\n" << "Export from list of stars to OFF:\n" - << " * Number of vertices: " << m_points.size() << std::endl + << " * Number of vertices: " << m_points.size() << "\n" << " * Total number of maximal simplices: " << num_maximal_simplices - << std::endl; + << "\n"; if (color_inconsistencies) { std::cerr << " * Number of inconsistent stars: " << num_inconsistent_stars << " (" << (m_points.size() > 0 ? - 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)" - << std::endl + 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)\n" << " * Number of inconsistent maximal simplices: " << num_inconsistent_maximal_simplices << " (" << (num_maximal_simplices > 0 ? 100. * num_inconsistent_maximal_simplices / num_maximal_simplices - : 0.) << "%)" - << std::endl; + : 0.) << "%)\n"; } - std::cerr << "==========================================================" - << std::endl; + std::cerr << "==========================================================\n"; #endif return os; @@ -4501,20 +4526,18 @@ public: } ++num_OFF_simplices; - os << std::endl; + os << "\n"; } } #ifdef CGAL_TC_VERBOSE - std::cerr << std::endl - << "==========================================================" - << std::endl + std::cerr + << "\n==========================================================\n" << "Export from complex to OFF:\n" - << " * Number of vertices: " << m_points.size() << std::endl + << " * Number of vertices: " << m_points.size() << "\n" << " * Total number of maximal simplices: " << num_maximal_simplices - << std::endl - << "==========================================================" - << std::endl; + << "\n" + << "==========================================================\n"; #endif return os; @@ -4527,12 +4550,11 @@ public: std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO TEMP if (m_intrinsic_dim < 3) { - std::cerr << std::endl - << "==========================================================" << std::endl - << "check_correlation_between_inconsistencies_and_fatness():" << std::endl - << "Intrinsic dimension should be >= 3." << std::endl - << "==========================================================" << std::endl - << std::endl; + std::cerr + << "\n==========================================================\n" + << "check_correlation_between_inconsistencies_and_fatness():\n" + << "Intrinsic dimension should be >= 3.\n" + << "==========================================================\n\n"; } std::size_t num_consistent_simplices = 0; @@ -4560,13 +4582,13 @@ public: { ++num_inconsistent_simplices; sum_vol_edge_ratio_inconsistent += fatness; - csv_inconsistent << fatness << std::endl; + csv_inconsistent << fatness << "\n"; } else { ++num_consistent_simplices; sum_vol_edge_ratio_consistent += fatness; - csv_consistent << fatness << std::endl; + csv_consistent << fatness << "\n"; } } } @@ -4576,18 +4598,16 @@ public: double avg_vol_edge_ratio_consistent = sum_vol_edge_ratio_consistent / num_consistent_simplices; - std::cerr << std::endl - << "==========================================================" - << std::endl + std::cerr + << "\n==========================================================\n" << "check_correlation_between_inconsistencies_and_fatness()\n" << " * Avg. volume/longest_edge^d ratio of consistent simplices: " << avg_vol_edge_ratio_consistent - << " (" << num_consistent_simplices << " simplices)" << std::endl + << " (" << num_consistent_simplices << " simplices)\n" << " * Avg. volume/longest_edge^d ratio of inconsistent simplices: " << avg_vol_edge_ratio_inconsistent - << " (" << num_inconsistent_simplices << " simplices)" << std::endl - << "==========================================================" - << std::endl; + << " (" << num_inconsistent_simplices << " simplices)\n" + << "==========================================================\n"; } private: diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index a0105521ce4..5c162124af3 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -24,6 +24,7 @@ #include #include +#include "CGAL/Tangential_complex/console_color.h" #include #include @@ -201,18 +202,17 @@ public: #ifdef CGAL_TC_VERBOSE if (!quiet) - std::cerr << "done." << std::endl; + std::cerr << "done.\n"; #endif } void display_stats() const { - std::cerr << "==========================================================\n"; - std::cerr << "Complex stats:\n"; + std::cerr << yellow << "Complex stats:\n" << white; if (m_complex.empty()) { - std::cerr << "No simplices.\n"; + std::cerr << " * No simplices.\n"; } else { @@ -231,11 +231,9 @@ public: it_map != simplex_stats.end() ; ++it_map) { std::cerr << " * " << it_map->first << "-simplices: " - << it_map->second << std::endl; + << it_map->second << "\n"; } } - - std::cerr << "==========================================================\n"; } // verbose_level = 0, 1 or 2 @@ -266,7 +264,7 @@ public: { if (verbose_level >= 2) std::cerr << "Found a simplex with dim = " - << it_simplex->size() - 1 << std::endl; + << it_simplex->size() - 1 << "\n"; ++num_wrong_dim_simplices; } else @@ -304,13 +302,18 @@ public: if (verbose_level >= 1) { - std::cerr << "is_pure_manifold: " << (ret ? "YES" : "NO") << std::endl; - if (!ret) + std::cerr << "Pure pseudo-manifold: "; + if (ret) { - std::cerr << " * Number of wrong dimension simplices: " - << num_wrong_dim_simplices << std::endl - << " * Number of wrong number of cofaces: " - << num_wrong_number_of_cofaces << std::endl; + 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"; } } @@ -325,7 +328,7 @@ public: template std::size_t num_K_simplices() const { - std::set k_simplices; + std::set k_simplices; for (Complex::const_iterator it_simplex = m_complex.begin(), it_simplex_end = m_complex.end() ; @@ -391,7 +394,7 @@ public: { if (verbose_level >= 2) std::cerr << "Found a simplex with dim = " - << it_simplex->size() - 1 << std::endl; + << it_simplex->size() - 1 << "\n"; ++num_wrong_dim_simplices; if (p_wrong_dim_simplices) p_wrong_dim_simplices->insert(*it_simplex); @@ -487,7 +490,7 @@ public: { if (verbose_level >= 2) std::cerr << "Error: star #" << center_vertex_index - << " is not connected" << std::endl; + << " is not connected\n"; ++num_unconnected_stars; if (p_unconnected_stars_simplices) { @@ -513,16 +516,20 @@ public: if (verbose_level >= 1) { - std::cerr << "is_pure_pseudo_manifold: " - << (ret ? "YES" : "NO") << std::endl; - if (!ret) + std::cerr << "Pure pseudo-manifold: "; + if (ret) { - std::cerr << " * Number of wrong dimension simplices: " - << num_wrong_dim_simplices << std::endl + 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 << std::endl + << num_wrong_number_of_cofaces << "\n" << " * Number of not-connected stars: " - << num_unconnected_stars << std::endl; + << num_unconnected_stars << "\n"; } } diff --git a/Tangential_complex/benchmark/Tangential_complex/console_color.h b/Tangential_complex/include/CGAL/Tangential_complex/console_color.h similarity index 83% rename from Tangential_complex/benchmark/Tangential_complex/console_color.h rename to Tangential_complex/include/CGAL/Tangential_complex/console_color.h index 50554178257..69435f3c189 100644 --- a/Tangential_complex/benchmark/Tangential_complex/console_color.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/console_color.h @@ -65,4 +65,17 @@ inline std::ostream& white(std::ostream &s) 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 diff --git a/Tangential_complex/include/CGAL/Tangential_complex/protected_sets.h b/Tangential_complex/include/CGAL/Tangential_complex/protected_sets.h new file mode 100644 index 00000000000..641165edd90 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/protected_sets.h @@ -0,0 +1,564 @@ +#ifndef PROTECTED_SETS_H +#define PROTECTED_SETS_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +typedef CGAL::Epick_d 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 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_Vector; +typedef CGAL::Euclidean_distance 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& 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 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& 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>& full_cells) +{ + // Store vertex indices in a map + int ind = 0; //index of a vertex + std::map 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 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& 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 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 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 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& marked_cells, bool power_protection) +{ + Euclidean_distance ed; + std::vector 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 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 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::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& landmarks_ind, FT delta, std::vector>& 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 index_list; + // shuffle the list of indexes (via a vector) + { + std::vector 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::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 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{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{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::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 From 4f7de28d923ab747c1a24003135588bc0d82870a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 4 Feb 2016 10:39:45 +0100 Subject: [PATCH 257/269] Improved console output + faster export_TC --- .../Tangential_complex/benchmark_tc.cpp | 2 +- .../include/CGAL/Tangential_complex.h | 138 ++++++++++-------- .../Tangential_complex/Simplicial_complex.h | 3 + 3 files changed, 81 insertions(+), 62 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index f9462605ce5..48c5c34401c 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -449,7 +449,7 @@ void make_tc(std::vector &points, //std::cerr << yellow << "FINAL CHECK...\n" << white; //std::size_t num_inc = tc.number_of_inconsistent_simplices(true).second; //tc.refresh_tangential_complex(); - //if (tc.number_of_inconsistent_simplices(true).second != num_inc) + //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; diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 70efc0ec772..2f4408332d0 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -580,15 +580,15 @@ public: Wall_clock_timer t; #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES - std::pair stats_before = + CGAL::cpp11::tuple stats_before = number_of_inconsistent_simplices(false); # ifdef CGAL_TC_VERBOSE std::cerr << "Initial number of inconsistencies: " - << stats_before.second << "\n"; + << CGAL::cpp11::get<1>(stats_before) << "\n"; # endif - if (stats_before.second == 0) + if (CGAL::cpp11::get<1>(stats_before) == 0) { # ifdef CGAL_TC_VERBOSE std::cerr << "Nothing to fix.\n"; @@ -606,10 +606,13 @@ public: std::cerr << "\nBefore fix step:\n" << " * Total number of simplices in stars (incl. duplicates): " - << stats_before.first << "\n" + << CGAL::cpp11::get<0>(stats_before) << "\n" << " * Num inconsistent simplices in stars (incl. duplicates): " - << red << stats_before.second << white - << " (" << 100. * stats_before.second / stats_before.first << "%)\n"; + << red << CGAL::cpp11::get<1>(stats_before) << white << " (" + << 100. * CGAL::cpp11::get<1>(stats_before) / CGAL::cpp11::get<0>(stats_before) << "%)\n" + << " * Number of stars containing inconsistent simplices: " + << red << CGAL::cpp11::get<2>(stats_before) << white << " (" + << 100. * CGAL::cpp11::get<2>(stats_before) / m_points.size() << "%)\n"; #endif #if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) @@ -681,10 +684,12 @@ public: refresh_tangential_complex(updated_points); # ifdef CGAL_TC_PERFORM_EXTRA_CHECKS - // DEBUGGING: confirm that all stars were actually refreshed - std::size_t num_inc_1 = number_of_inconsistent_simplices(false).second; + // Confirm that all stars were actually refreshed + std::size_t num_inc_1 = + CGAL::cpp11::get<1>(number_of_inconsistent_simplices(false)); refresh_tangential_complex(); - std::size_t num_inc_2 = number_of_inconsistent_simplices(false).second; + std::size_t num_inc_2 = + CGAL::cpp11::get<1>(number_of_inconsistent_simplices(false)); if (num_inc_1 != num_inc_2) std::cerr << red << "REFRESHMENT CHECK: FAILED. (" << num_inc_1 << " vs " << num_inc_2 << ")\n" << white; @@ -694,16 +699,19 @@ public: #endif #ifdef CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES - std::pair stats_after = + CGAL::cpp11::tuple stats_after = number_of_inconsistent_simplices(false); std::cerr << "\nAfter fix:\n" << " * Total number of simplices in stars (incl. duplicates): " - << stats_after.first << "\n" + << CGAL::cpp11::get<0>(stats_after) << "\n" << " * Num inconsistent simplices in stars (incl. duplicates): " - << red << stats_after.second << white - << " (" << 100. * stats_after.second / stats_after.first << "%)\n"; + << red << CGAL::cpp11::get<1>(stats_after) << white << " (" + << 100. * CGAL::cpp11::get<1>(stats_after) / CGAL::cpp11::get<0>(stats_after) << "%)\n" + << " * Number of stars containing inconsistent simplices: " + << red << CGAL::cpp11::get<2>(stats_after) << white << " (" + << 100. * CGAL::cpp11::get<2>(stats_after) / m_points.size() << "%)\n"; stats_before = stats_after; #endif @@ -716,14 +724,17 @@ public: final_num_inconsistent_stars = num_inconsistent_stars; - ++num_steps; done = (num_inconsistent_stars == 0); - if (!done && time_limit > 0. && t.elapsed() > time_limit) + if (!done) { + ++num_steps; + if (time_limit > 0. && t.elapsed() > time_limit) + { #ifdef CGAL_TC_VERBOSE - std::cerr << red << "Time limit reached.\n" << white; + std::cerr << red << "Time limit reached.\n" << white; #endif - return TIME_LIMIT_REACHED; + return TIME_LIMIT_REACHED; + } } } @@ -733,8 +744,10 @@ public: return TC_FIXED; } - // Return a pair - std::pair number_of_inconsistent_simplices( + // Return a tuple + // + CGAL::cpp11::tuple + number_of_inconsistent_simplices( #ifdef CGAL_TC_VERBOSE bool verbose = true #else @@ -744,9 +757,12 @@ public: { std::size_t num_simplices = 0; std::size_t num_inconsistent_simplices = 0; + std::size_t num_inconsistent_stars = 0; // For each triangulation for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) { + bool is_star_inconsistent = false; + // For each cell Star::const_iterator it_inc_simplex = m_stars[idx].begin(); Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); @@ -760,10 +776,14 @@ public: c.insert(idx); // Add the missing index if (!is_simplex_consistent(c)) + { ++num_inconsistent_simplices; + is_star_inconsistent = true; + } ++num_simplices; } + num_inconsistent_stars += is_star_inconsistent; } if (verbose) @@ -771,22 +791,32 @@ public: std::cerr << "\n==========================================================\n" << "Inconsistencies:\n" - << " * Number of vertices: " << m_points.size() << "\n" << " * Total number of simplices in stars (incl. duplicates): " << num_simplices << "\n" << " * Number of inconsistent simplices in stars (incl. duplicates): " - << num_inconsistent_simplices << "\n" - << " * Percentage of inconsistencies: " - << 100. * num_inconsistent_simplices / num_simplices << "%\n" + << num_inconsistent_simplices << " (" + << 100. * num_inconsistent_simplices / num_simplices << "%)\n" + << " * Number of stars containing inconsistent simplices: " + << num_inconsistent_stars << " (" + << 100. * num_inconsistent_stars / m_points.size() << "%)\n" << "==========================================================\n"; } - return std::make_pair(num_simplices, num_inconsistent_simplices); + return std::make_tuple( + num_simplices, num_inconsistent_simplices, num_inconsistent_stars); } // Return the max dimension of the simplices + // check_lower_and_higher_dim_simplices : 0 (false), 1 (true), 2 (auto) + // If the check is enabled, 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 + // "auto" (= 2) will enable the check as a soon as it encounters a + // simplex whose dimension is different from the previous ones. + // N.B.: The check is quite expensive. int export_TC(Simplicial_complex &complex, - bool export_infinite_simplices = false) const + bool export_infinite_simplices = false, + int check_lower_and_higher_dim_simplices = 2) const { #if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) std::cerr << yellow @@ -806,16 +836,35 @@ public: Star::const_iterator it_inc_simplex_end = m_stars[idx].end(); for ( ; it_inc_simplex != it_inc_simplex_end ; ++it_inc_simplex) { + Indexed_simplex c = *it_inc_simplex; + // Don't export infinite cells - if (!export_infinite_simplices && is_infinite(*it_inc_simplex)) + if (!export_infinite_simplices && is_infinite(c)) continue; - Indexed_simplex c = *it_inc_simplex; + // Unusual simplex dim? + if (check_lower_and_higher_dim_simplices == 2 + && max_dim != -1 + && static_cast(c.size()) != max_dim) + { + // Let's activate the check + std::cerr << red << + "Info: check_lower_and_higher_dim_simplices ACTIVATED. " + "Export might be take some time...\n" << white; + check_lower_and_higher_dim_simplices = 1; + } + if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); // Add the missing center vertex c.insert(idx); - complex.add_simplex(c); + +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + if (is_one_of_the_coord_far_from_origin(c, CGAL_TC_ALVAREZ_SURFACE_WINDOW, 2)) + continue; +#endif + + complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1); } } @@ -852,33 +901,11 @@ public: } } while (inconsistencies_found); } - - // CJTODO TEMP - std::pair stats_after = - number_of_inconsistent_simplices(false); - std::cerr << "AFTER check_and_solve_inconsistencies_by_adding_higher_dim_simplices():\n" - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << "\n" - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << "\n" - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%\n"; } // Returns true if some inconsistencies were found bool check_and_solve_inconsistencies_by_filtering_simplices_out() { - // CJTODO TEMP - std::pair stats_before = - number_of_inconsistent_simplices(false); - std::cerr << "BEFORE check_and_solve_inconsistencies_by_filtering_simplices_out():\n" - << " - Total number of simplices in stars (incl. duplicates): " - << stats_before.first << "\n" - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_before.second << "\n" - << " - Percentage of inconsistencies: " - << 100. * stats_before.second / stats_before.first << "%\n"; - bool inconsistencies_found = false; // CJTODO: parallel_for??? @@ -888,17 +915,6 @@ public: inconsistencies_found = true; } - // CJTODO TEMP - std::pair stats_after = - number_of_inconsistent_simplices(false); - std::cerr << "AFTER check_and_solve_inconsistencies_by_filtering_simplices_out():\n" - << " - Total number of simplices in stars (incl. duplicates): " - << stats_after.first << "\n" - << " - Num inconsistent simplices in stars (incl. duplicates): " - << stats_after.second << "\n" - << " - Percentage of inconsistencies: " - << 100. * stats_after.second / stats_after.first << "%\n"; - return inconsistencies_found; } diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 5c162124af3..15eafae7afc 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -46,6 +46,9 @@ public: typedef std::set Simplex; typedef std::set 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 void add_simplex( const std::set &s, bool perform_checks = true) { From f2ad04c39a7a7c7f4d8655ed4421d6e4be3c5b67 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Feb 2016 11:07:45 +0100 Subject: [PATCH 258/269] Improved output --- .../Tangential_complex/benchmark_mesh_d.cpp | 49 +++++++++---------- Tangential_complex/include/CGAL/Mesh_d.h | 8 +++ 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp index 0e5aea227d1..0338d46ffeb 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -14,7 +14,6 @@ #include #include "../../test/Tangential_complex/testing_utilities.h" -#include "console_color.h" #include #include @@ -120,7 +119,7 @@ void make_mesh( 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() << std::endl; + << num_points_before << " / " << points.size() << "\n"; } //=========================================================================== @@ -186,18 +185,17 @@ void make_mesh( // Display info //=========================================================================== - std::cerr << std::endl - << "================================================" << std::endl - << "Number of vertices: " << mesh.number_of_vertices() << std::endl + std::cerr + << "\n================================================\n" + << "Number of vertices: " << mesh.number_of_vertices() << "\n" << "Pure pseudomanifold: " << yellow - << (is_pure_pseudomanifold ? "YES" : "NO") << white << std::endl - << "Computation times (seconds): " << std::endl - << " * Mesh: " << init_time + computation_time << std::endl - << " - Init + kd-tree = " << init_time << std::endl - << " - Mesh computation = " << computation_time << std::endl - //<< " * Export to OFF : " << export_before_time << std::endl - << "================================================" << std::endl - << std::endl; + << (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() @@ -214,7 +212,7 @@ int main() unsigned int seed = static_cast(time(NULL)); CGAL::default_random = CGAL::Random(seed); - std::cerr << "Random seed = " << seed << std::endl; + std::cerr << "Random seed = " << seed << "\n"; std::ifstream script_file; script_file.open(BENCHMARK_SCRIPT_FILENAME); @@ -241,7 +239,7 @@ int main() #endif std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME - << "' found." << std::endl; + << "' found.\n"; script_file.seekg(0); while (script_file.good()) { @@ -251,10 +249,10 @@ int main() { boost::replace_all(line, "\t", " "); boost::trim_all(line); - std::cerr << std::endl << std::endl; - std::cerr << "*****************************************" << std::endl; - std::cerr << "******* " << line << std::endl; - std::cerr << "*****************************************" << std::endl; + std::cerr << "\n\n"; + std::cerr << "*****************************************\n"; + std::cerr << "******* " << line << "\n"; + std::cerr << "*****************************************\n"; std::stringstream sstr(line); std::string input; @@ -297,7 +295,7 @@ int main() input_stripped = input_stripped.substr( slash_index, input_stripped.find_last_of('.') - slash_index); - std::cerr << std::endl << "Mesh #" << i << "..." << std::endl; + std::cerr << "\nMesh #" << i << "...\n"; #ifdef CGAL_MESH_D_PROFILING Wall_clock_timer t_gen; @@ -381,7 +379,7 @@ int main() #ifdef CGAL_MESH_D_PROFILING std::cerr << "Point set generated/loaded in " << t_gen.elapsed() - << " seconds." << std::endl; + << " seconds.\n"; #endif if (!points.empty()) @@ -398,13 +396,12 @@ int main() points, intrinsic_dim, sparsify == 'Y', sparsity, input.c_str()); - std::cerr << "Mesh #" << i++ << " done." << std::endl; - std::cerr << std::endl << "---------------------------------" - << std::endl << std::endl; + std::cerr << "Mesh #" << i++ << " done.\n"; + std::cerr << "\n---------------------------------\n\n"; } else { - std::cerr << "Mesh #" << i++ << ": no points loaded." << std::endl; + std::cerr << "Mesh #" << i++ << ": no points loaded.\n"; } } } @@ -418,7 +415,7 @@ int main() // Or not script? else { - std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found." << std::endl; + std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found.\n"; } system("pause"); diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h index 94ef8b3a613..3d72ea2e4d5 100644 --- a/Tangential_complex/include/CGAL/Mesh_d.h +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -352,6 +352,12 @@ public: m_k.scaled_vector_d_object()( m_k.point_to_vector_d_object()(*intersection), weight)); } + else + { + // CJTODO TEMP DEBUG + std::cerr << std::hex << (unsigned int)&k_face << std::dec + << red << "No intersection" << white << "\n"; + } } if (sum_weights > 0) { @@ -366,6 +372,8 @@ public: Point const& p0 = (*k_face.begin())->point(); for (auto neighbor_vh : nghb) // CJTODO: C++11 { + // If a neighbor is closer than p0 to the average intersection, then + // the average intersection is inside another Voronoi cell if (m_k.squared_distance_d_object()(p0, avg_inters) > m_k.squared_distance_d_object()(neighbor_vh->point(), avg_inters)) { From a1e866eb6d868f7519b1da891c6542ec3806861c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Feb 2016 11:09:04 +0100 Subject: [PATCH 259/269] Add Simplicial_complex::load_simplices_from_OFF + minor changes --- .../Tangential_complex/benchmark_tc.cpp | 14 +--- .../include/CGAL/Tangential_complex.h | 13 ++-- .../Tangential_complex/Simplicial_complex.h | 67 +++++++++++++++++++ 3 files changed, 74 insertions(+), 20 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 48c5c34401c..422a7d9ce26 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -519,19 +519,7 @@ void make_tc(std::vector &points, complex.display_stats(); if (intrinsic_dim == 2) - { - std::cerr << "\nComputing Euler characteristic of the complex...\n"; - std::size_t num_vertices = complex.num_K_simplices<0>(); - std::size_t num_edges = complex.num_K_simplices<1>(); - std::size_t num_triangles = complex.num_K_simplices<2>(); - std::cerr << "Euler characteristic: V - E + F = " - << num_vertices << " - " << num_edges << " + " << num_triangles << " = " - << blue - << (std::ptrdiff_t) num_vertices - - (std::ptrdiff_t) num_edges - + (std::ptrdiff_t) num_triangles - << white << "\n"; - } + complex.euler_characteristic(true); // CJTODO TEMP: Export to OFF with higher-dim simplices colored /*std::set > higher_dim_simplices; diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2f4408332d0..2ba43a69ea7 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -87,7 +87,7 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE //#define CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS -#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 1.9 // 0.95 +//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 1.9 // 0.95 namespace CGAL { @@ -392,9 +392,13 @@ public: void compute_tangential_complex() { #ifdef CGAL_TC_PERFORM_EXTRA_CHECKS - std::cerr << red << "WARNING: CGAL_TC_PERFORM_EXTRA_CHECKS is defined." + std::cerr << red << "WARNING: CGAL_TC_PERFORM_EXTRA_CHECKS is defined. " << "Computation might be slower than usual.\n" << white; #endif +#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW + std::cerr << red << "WARNING: CGAL_TC_ALVAREZ_SURFACE_WINDOW is defined (" + << CGAL_TC_ALVAREZ_SURFACE_WINDOW << ").\n" << white; +#endif #if defined(CGAL_TC_PROFILING) && defined(CGAL_LINKED_WITH_TBB) Wall_clock_timer t; @@ -583,11 +587,6 @@ public: CGAL::cpp11::tuple stats_before = number_of_inconsistent_simplices(false); -# ifdef CGAL_TC_VERBOSE - std::cerr << "Initial number of inconsistencies: " - << CGAL::cpp11::get<1>(stats_before) << "\n"; -# endif - if (CGAL::cpp11::get<1>(stats_before) == 0) { # ifdef CGAL_TC_VERBOSE diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index 15eafae7afc..bda063aa1d9 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -36,6 +36,8 @@ #include #include +#include +#include namespace CGAL { namespace Tangential_complex_ { @@ -90,6 +92,47 @@ public: m_complex.insert(s); } + // 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 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; @@ -353,6 +396,30 @@ public: 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, From e84351f14b2c70b902afa8932d8edb7e2755fc44 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 5 Feb 2016 11:10:00 +0100 Subject: [PATCH 260/269] Small app to compute the euler charact from an OFF file --- .../Tangential_complex/CMakeLists.txt | 39 +++++++++++++++++++ .../Tangential_complex/euler_charact.cpp | 19 +++++++++ 2 files changed, 58 insertions(+) create mode 100644 Tangential_complex/applications/Tangential_complex/CMakeLists.txt create mode 100644 Tangential_complex/applications/Tangential_complex/euler_charact.cpp diff --git a/Tangential_complex/applications/Tangential_complex/CMakeLists.txt b/Tangential_complex/applications/Tangential_complex/CMakeLists.txt new file mode 100644 index 00000000000..0f87ac4302d --- /dev/null +++ b/Tangential_complex/applications/Tangential_complex/CMakeLists.txt @@ -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() + diff --git a/Tangential_complex/applications/Tangential_complex/euler_charact.cpp b/Tangential_complex/applications/Tangential_complex/euler_charact.cpp new file mode 100644 index 00000000000..01e0e1b9970 --- /dev/null +++ b/Tangential_complex/applications/Tangential_complex/euler_charact.cpp @@ -0,0 +1,19 @@ +#include + +using namespace CGAL::Tangential_complex_; + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + std::cout << "Usage: euler_charact \n"; + return 0; + } + + Simplicial_complex complex; + complex.load_simplices_from_OFF(argv[1]); + + complex.euler_characteristic(true); + + return 0; +} From a53c2f83b65975d13acb42342d91eef8608ff593 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Feb 2016 15:02:20 +0100 Subject: [PATCH 261/269] add_simplex now tells if the simplex was actually inserted + empty() function + is_pure_pseudomanifold now optionally handles borders --- .../Tangential_complex/Simplicial_complex.h | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h index bda063aa1d9..b1cacf241c1 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Simplicial_complex.h @@ -51,7 +51,8 @@ public: // 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 - void add_simplex( + // Returns true if the simplex was added + bool add_simplex( const std::set &s, bool perform_checks = true) { if (perform_checks) @@ -71,7 +72,7 @@ public: s.begin(), s.end())) { // No need to insert it, then - return; + return false; } // Check if the simplex includes some lower-dim simplices if (it_simplex->size() < num_pts @@ -89,7 +90,7 @@ public: m_complex.erase(*it); } } - m_complex.insert(s); + return m_complex.insert(s).second; } // Ignore the point coordinates @@ -138,6 +139,11 @@ public: return m_complex; } + bool empty() + { + return m_complex.empty(); + } + void clear() { m_complex.clear(); @@ -285,6 +291,7 @@ public: // 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, @@ -331,7 +338,8 @@ public: it_map_elt != it_map_end ; ++it_map_elt) { - if (it_map_elt->second != 2) + 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 " @@ -424,6 +432,7 @@ public: 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, @@ -440,6 +449,7 @@ public: *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, @@ -536,7 +546,8 @@ public: boost::add_edge(km1_gv, *kface_it, adj_graph); } - if (dm1_to_d_it->second.size() != 2) + 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) From 2f099f2305ad356a90ec60a664f49e80bf93ac80 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Feb 2016 15:04:13 +0100 Subject: [PATCH 262/269] Move load_points_from_file + add class Orthogonal_projection --- .../CGAL/Tangential_complex/utilities.h | 118 ++++++++++++++++++ .../Tangential_complex/testing_utilities.h | 102 ++------------- 2 files changed, 127 insertions(+), 93 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h index ecaf69a734b..6b32e832d3c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/utilities.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/utilities.h @@ -30,6 +30,7 @@ #include #include +#include #include // CJTODO: this is C++11 => use boost.Atomic (but it's too recent) // or tbb::atomic (works for doubles, but not officially) @@ -355,6 +356,87 @@ namespace Tangential_complex_ { 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::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 + 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 Basis compute_gram_schmidt_basis(Basis const& input_basis, K const& k) { @@ -371,6 +453,42 @@ namespace Tangential_complex_ { return output_basis; } + // Functor to compute stereographic projection from S^3(sphere_radius) to R^3 + template + 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 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 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 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 diff --git a/Tangential_complex/test/Tangential_complex/testing_utilities.h b/Tangential_complex/test/Tangential_complex/testing_utilities.h index 1c70713f7d8..36bc179c3a6 100644 --- a/Tangential_complex/test/Tangential_complex/testing_utilities.h +++ b/Tangential_complex/test/Tangential_complex/testing_utilities.h @@ -171,7 +171,7 @@ sparsify_point_set( std::vector dropped_points(input_pts.size(), false); - // Parse the following points, and add them if they are not too close to + // 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() ; @@ -185,18 +185,20 @@ sparsify_point_set( INS_range ins_range = points_ds.query_incremental_ANN(*it_pt); - // Drop it if there is another point that: - // - is closer that min_squared_dist - // - and has a higher index + // 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; - typename Kernel::FT sq_dist = nn_it->second; - // The neighbor is too close, we drop the neighbor - if (sq_dist < min_squared_dist) + // 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; } @@ -210,92 +212,6 @@ sparsify_point_set( return output; } -template< - typename Kernel, typename OutputIteratorPoints> - bool load_points_from_file( - const std::string &filename, - OutputIteratorPoints points, - std::size_t only_first_n_points = std::numeric_limits::max()) -{ - typedef typename Kernel::Point_d Point; - - std::ifstream in(filename); - if (!in.is_open()) - { - std::cerr << "Could not open '" << filename << "'" << std::endl; - return false; - } - - Point p; - int num_ppints; - in >> num_ppints; - - std::size_t i = 0; - while (i < only_first_n_points && in >> p) - { - *points++ = p; - ++i; - } - -#ifdef CGAL_TC_VERBOSE - std::cerr << "'" << filename << "' loaded." << std::endl; -#endif - - return true; - } - -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::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; -} - template std::vector generate_points_on_plane( std::size_t num_points, int intrinsic_dim, int ambient_dim) From 17a81c31248c3e66a167bc8dd3c120449b9abef8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 10 Feb 2016 15:12:49 +0100 Subject: [PATCH 263/269] export_TC can now give the list of inconsistent simplices + ... + Add export_point_set + Allow to export the sparsified point set + Better OFF output (no more duplicated triangles) + Clean-up --- .../Tangential_complex/benchmark_tc.cpp | 115 ++++++++------- .../include/CGAL/Tangential_complex.h | 131 ++++++++++++------ 2 files changed, 149 insertions(+), 97 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 422a7d9ce26..28285a2c728 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -6,6 +6,19 @@ # define TBB_USE_THREADING_TOOL #endif +#include + +//#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 + +const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 500000; // 1e10 + #include #include #include @@ -41,13 +54,6 @@ typedef CGAL::Tangential_complex< Kernel, CGAL::Dynamic_dimension_tag, CGAL::Parallel_tag> TC; -//#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 - #ifdef TC_PROTECT_POINT_SET_DELTA # include // CJTODO TEST @@ -57,6 +63,8 @@ typedef CGAL::Tangential_complex< std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv"); #endif +using namespace CGAL::Tangential_complex_; + class XML_perf_data { public: @@ -167,6 +175,7 @@ private: int m_max_allowed_dim; }; +// color_inconsistencies: only works if p_complex = NULL template bool export_to_off( TC const& tc, @@ -186,12 +195,15 @@ bool export_to_off( 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 }; - CGAL::Tangential_complex_::S3_to_R3_stereographic_projection + S3_to_R3_stereographic_projection proj_functor(0.2, Point(4, ¢er_pt[0], ¢er_pt[4]), k); #else CGAL::Identity proj_functor; + //Kernel k; + //std::array sel = { 1, 3, 5 }; + //Orthogonal_projection proj_functor(sel, k); #endif if (tc.intrinsic_dimension() <= 3) @@ -320,6 +332,11 @@ void make_tc(std::vector &points, 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 @@ -367,41 +384,6 @@ void make_tc(std::vector &points, tc.compute_tangential_complex(); double computation_time = t.elapsed(); t.reset(); - //=========================================================================== - // CJTODO TEMP - //=========================================================================== - /*{ - TC::Simplicial_complex complex; - int max_dim = tc.export_TC(complex, false); - complex.display_stats(); - - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_ALPHA_COMPLEX.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(complex, off_stream); - - // Collapse - complex.collapse(max_dim); - { - std::stringstream output_filename; - output_filename << "output/" << input_name_stripped << "_" << intrinsic_dim - << "_in_R" << ambient_dim << "_AFTER_COLLAPSE.off"; - std::ofstream off_stream(output_filename.str().c_str()); - tc.export_to_off(complex, off_stream); - } - std::size_t num_wrong_dim_simplices, - num_wrong_number_of_cofaces, - num_unconnected_stars; - bool pure_manifold = complex.is_pure_pseudomanifold( - intrinsic_dim, tc.number_of_vertices(), false, 1, - &num_wrong_dim_simplices, &num_wrong_number_of_cofaces, - &num_unconnected_stars); - complex.display_stats(); - } - return;*/ - // CJTODO TEMP =========================== - #ifdef CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY if (ambient_dim <= 4) tc.check_if_all_simplices_are_in_the_ambient_delaunay(); @@ -412,9 +394,17 @@ void make_tc(std::vector &points, //=========================================================================== // Export to OFF //=========================================================================== + + // Create complex + int max_dim = -1; + TC::Simplicial_complex complex; + std::set > 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") ? t.elapsed() : -1); + (export_to_off(tc, input_name_stripped, "_INITIAL_TC", true, + &complex, &inconsistent_simplices) ? t.elapsed() : -1); t.reset(); unsigned int num_perturb_steps = 0; @@ -458,8 +448,15 @@ void make_tc(std::vector &points, //========================================================================= // Export to OFF //========================================================================= + + // Re-build the complex + std::set > 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); + 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(); @@ -477,10 +474,8 @@ void make_tc(std::vector &points, // CJTODO TEST //tc.check_and_solve_inconsistencies_by_filtering_simplices_out(); - int max_dim = -1; double fix2_time = -1; double export_after_fix2_time = -1.; - TC::Simplicial_complex complex; if (add_high_dim_simpl) { //========================================================================= @@ -494,7 +489,7 @@ void make_tc(std::vector &points, tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices(); #endif fix2_time = t.elapsed(); t.reset(); - max_dim = tc.export_TC(complex, false); + /*std::set > not_delaunay_simplices; if (ambient_dim <= 4) { @@ -505,15 +500,22 @@ void make_tc(std::vector &points, //========================================================================= // Export to OFF //========================================================================= + + // Re-build the complex + std::set > 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); + tc, input_name_stripped, "_AFTER_FIX2", false, &complex, + &inconsistent_simplices); double export_after_fix2_time = (exported ? t.elapsed() : -1); t.reset(); } else { - max_dim = tc.export_TC(complex, false); + std::set > inconsistent_simplices; + max_dim = tc.export_TC(complex, false, 2, &inconsistent_simplices); } complex.display_stats(); @@ -528,7 +530,7 @@ void make_tc(std::vector &points, std::inserter(higher_dim_simplices, higher_dim_simplices.begin())); export_to_off( tc, input_name_stripped, "_BEFORE_COLLAPSE", false, &complex, - &higher_dim_simplices);*/ + &inconsistent_simplices, &higher_dim_simplices);*/ //=========================================================================== // Collapse @@ -549,7 +551,13 @@ void make_tc(std::vector &points, std::set > wrong_number_of_cofaces_simplices; std::set > unconnected_stars_simplices; bool is_pure_pseudomanifold = complex.is_pure_pseudomanifold( - intrinsic_dim, tc.number_of_vertices(), false, 1, + 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, @@ -810,7 +818,8 @@ int main() { load_points_from_file( input, std::back_inserter(points), - std::back_inserter(tangent_spaces)/*, 600*/); + std::back_inserter(tangent_spaces), + ONLY_LOAD_THE_FIRST_N_POINTS); } #ifdef CGAL_TC_PROFILING diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 2ba43a69ea7..3ee12855b3c 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -44,7 +44,7 @@ # include -#include // CJTODO TEMP +#include // CJTODO DEBUG? #include #include @@ -79,7 +79,7 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) -//static std::ofstream csv_stream("output/stats.csv"); // CJTODO TEMP +//static std::ofstream csv_stream("output/stats.csv"); // CJTODO DEBUG //CJTODO: debug //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_SPHERE_2 @@ -87,7 +87,6 @@ typedef CGAL::MP_Float ET; //#define CGAL_TC_COMPUTE_TANGENT_PLANES_FOR_TORUS_D //#define CGAL_TC_ADD_NOISE_TO_TANGENT_SPACE //#define CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS -//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 1.9 // 0.95 namespace CGAL { @@ -391,6 +390,34 @@ public: void compute_tangential_complex() { + // CJTODO TEMP + /*{ + INS_range ins_range = m_points_ds.query_incremental_ANN( + m_k.construct_point_d_object()(8, ORIGIN)); + int c = 0; + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() && c < 10 ; + ++nn_it, ++c) + { + std::size_t neighbor_point_idx = nn_it->first; + FT sqdist = nn_it->second; + std::cerr << neighbor_point_idx << ":" << CGAL::sqrt(sqdist) << "\n"; + } + } + { + INS_range ins_range = m_points_ds.query_incremental_ANN( + m_points[234]); + int c = 0; + for (INS_iterator nn_it = ins_range.begin() ; + nn_it != ins_range.end() && c < 10 ; + ++nn_it, ++c) + { + std::size_t neighbor_point_idx = nn_it->first; + FT sqdist = nn_it->second; + std::cerr << neighbor_point_idx << ":" << CGAL::sqrt(sqdist) << "\n"; + } + }*/ + #ifdef CGAL_TC_PERFORM_EXTRA_CHECKS std::cerr << red << "WARNING: CGAL_TC_PERFORM_EXTRA_CHECKS is defined. " << "Computation might be slower than usual.\n" << white; @@ -805,6 +832,7 @@ public: num_simplices, num_inconsistent_simplices, num_inconsistent_stars); } + // First clears the complex then exports the TC into it // Return the max dimension of the simplices // check_lower_and_higher_dim_simplices : 0 (false), 1 (true), 2 (auto) // If the check is enabled, the function: @@ -815,7 +843,8 @@ public: // N.B.: The check is quite expensive. int export_TC(Simplicial_complex &complex, bool export_infinite_simplices = false, - int check_lower_and_higher_dim_simplices = 2) const + int check_lower_and_higher_dim_simplices = 2, + std::set *p_inconsistent_simplices = NULL) const { #if defined(CGAL_TC_VERBOSE) || defined(CGAL_TC_PROFILING) std::cerr << yellow @@ -826,6 +855,7 @@ public: #endif int max_dim = -1; + complex.clear(); // For each triangulation for (std::size_t idx = 0 ; idx < m_points.size() ; ++idx) @@ -863,7 +893,15 @@ public: continue; #endif - complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1); + // Try to insert the simplex + bool added = + complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1); + + // Inconsistent? + if (p_inconsistent_simplices && added && !is_simplex_consistent(c)) + { + p_inconsistent_simplices->insert(c); + } } } @@ -995,7 +1033,7 @@ private: } else { - std::cerr << "***************** Intersection is not a point ********************\n"; // CJTODO TEMP + std::cerr << "***************** Intersection is not a point ********************\n"; // CJTODO DEBUG // Compute the intersection between Voronoi_cell(s) and Tq // We need Q, i.e. the vertices which are common neighbors of all // vertices of full_simplex in the Delaunay triangulation, but we @@ -1049,7 +1087,7 @@ private: pqueues[simplex_dim - m_intrinsic_dim].push( Simplex_and_alpha(p, is, squared_alpha, thickening_v)); - // CJTODO TEMP + // CJTODO DEBUG /*std::cerr << "Just inserted the simplex "; std::copy(full_simplex.begin(), full_simplex.end(), @@ -1152,7 +1190,7 @@ public: FT(0), /* sqlen_threshold: default value */ true /* add_to_thickening_vectors */); - // CJTODO TEMP + // CJTODO DEBUG if (!vec_added) { std::cerr << "FYI: the thickening vector was not added " @@ -1194,7 +1232,7 @@ public: Indexed_simplex full_s = saa.m_simplex; full_s.insert(saa.m_center_point_index); - // CJTODO TEMP + // CJTODO DEBUG bool is_this_simplex_somewhere = false; for(auto ii : saa.m_simplex) // CJTODO C++11 { @@ -1210,7 +1248,7 @@ public: if (!is_this_simplex_somewhere) std::cerr << "WOW The simplex is NOWHERE!\n"; - // CJTODO TEMP + // CJTODO DEBUG if (m_ambient_dim <= 3) { if (is_simplex_in_the_ambient_delaunay(full_s)) @@ -1254,7 +1292,7 @@ public: << num_inconsistent_simplices << "\n"; #endif } - // CJTODO TEMP + // CJTODO DEBUG else { std::cerr << "SUCCESS: " @@ -2013,7 +2051,6 @@ private: else { update_star__with_thickening_vector(i); - //check_if_all_simplices_are_in_the_ambient_delaunay(); // CJTODO TEMP } #else update_star__no_thickening_vectors(i); @@ -3380,6 +3417,30 @@ next_face: return is_inconsistent; } + // 1st line: number of points + // Then one point per line + std::ostream &export_point_set( + std::ostream & os, + bool use_perturbed_points = false, + const char *coord_separator = " ") const + { + if (use_perturbed_points) + { + std::vector perturbed_points; + perturbed_points.reserve(m_points.size()); + for (std::size_t i = 0 ; i < m_points.size() ; ++i) + perturbed_points.push_back(compute_perturbed_point(i)); + + return export_point_set( + m_k, perturbed_points, os, coord_separator); + } + else + { + return export_point_set( + m_k, m_points, os, coord_separator); + } + } + template > std::ostream &export_vertices_to_off( std::ostream & os, std::size_t &num_vertices, @@ -3414,22 +3475,22 @@ next_face: use_perturbed_points ? compute_perturbed_point(i) : *it_p); for (int ii = 0 ; ii < N ; ++ii) { - int i = 0; + int j = 0; #if CGAL_TC_BETTER_EXPORT_FOR_FLAT_TORUS // For flat torus os << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 2)) << " " << (2 + 1 * CGAL::to_double(coord(p, 0))) * CGAL::to_double(coord(p, 3)) << " " << 1 * CGAL::to_double(coord(p, 1)); #else - for ( ; i < num_coords ; ++i) - os << CGAL::to_double(coord(p, i)) << " "; + for ( ; j < num_coords ; ++j) + os << CGAL::to_double(coord(p, j)) << " "; #endif - if (i == 2) + if (j == 2) os << "0"; #ifdef CGAL_TC_EXPORT_NORMALS - for (i = 0 ; i < num_coords ; ++i) - os << " " << CGAL::to_double(coord(*it_os->begin(), i)); + for (j = 0 ; j < num_coords ; ++j) + os << " " << CGAL::to_double(coord(*it_os->begin(), j)); #endif os << "\n"; } @@ -3564,7 +3625,7 @@ next_face: unproject_point(Cq, m_tangent_spaces[q_idx], q_tr_traits), circumsphere_sqradius_q); - // CJTODO TEMP ==================== + // CJTODO DEBUG ==================== /*{ INS_range ins_range = m_points_ds.query_incremental_ANN(k_drop_w(global_Cp)); for (INS_iterator nn_it = ins_range.begin() ; @@ -3573,8 +3634,6 @@ next_face: { FT neighbor_sqdist = nn_it->second; - //std::cerr << nn_it->first << " : " << neighbor_sqdist << " / "; // CJTODO TEMP - // When we're sure we got all the potential points, break //if (neighbor_sqdist > circumsphere_sqradius_p + m_sq_half_sparsity) // break; @@ -3582,7 +3641,6 @@ next_face: std::size_t neighbor_point_idx = nn_it->first; FT point_to_Cp_power_sqdist = k_power_dist( global_Cp, compute_perturbed_weighted_point(neighbor_point_idx)); - //std::cerr << point_to_Cp_power_sqdist << "\n"; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_Cp_power_sqdist <= FT(0) && inconsistent_simplex.find(neighbor_point_idx) == @@ -3630,24 +3688,12 @@ next_face: auto sid = (o == NEGATIVE ? side(simplex_pts_in_Tq.rbegin(), simplex_pts_in_Tq.rend(), p) : side(simplex_pts_in_Tq.begin(), simplex_pts_in_Tq.end(), p)); - switch(sid) - { - case ON_NEGATIVE_SIDE: - std::cerr << "ON_NEGATIVE_SIDE\n"; // CJTODO TEMP - break; - case ON_POSITIVE_SIDE: - std::cerr << "ON_POSITIVE_SIDE\n"; // CJTODO TEMP - break; - case ON_ORIENTED_BOUNDARY: - std::cerr << "ON_ORIENTED_BOUNDARY\n"; // CJTODO TEMP - break; - } }*/ } CGAL_assertion_msg(!inside_pt_indices.empty(), "There should be at least one vertex inside the sphere"); - // CJTODO TEMP DEBUG + // CJTODO DEBUG /*if (inside_pt_indices.empty()) { //compute_tangent_triangulation(q_idx, true); @@ -3663,7 +3709,7 @@ next_face: std::cerr << "\n"; }*/ - // CJTODO TEMP DEBUG + // CJTODO DEBUG // If co-intrinsic dimension = 1, let's compare normals /*if (m_ambient_dim - m_intrinsic_dim == 1) { @@ -3683,7 +3729,7 @@ next_face: csv_stream << "\n"; }*/ - // CJTODO TEMP DEBUG + // CJTODO DEBUG if (inside_pt_indices.size() > 1) { std::cerr << "Warning: " << inside_pt_indices.size() << " insiders in " @@ -3754,7 +3800,7 @@ next_face: } } - // CJTODO TEMP ==================== + // CJTODO DEBUG ==================== /*{ typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object(); typename K::Point_weight_d k_weight = m_k.point_weight_d_object(); @@ -3768,8 +3814,6 @@ next_face: { FT neighbor_sqdist = nn_it->second; - //std::cerr << nn_it->first << " : " << neighbor_sqdist << " / "; // CJTODO TEMP - // When we're sure we got all the potential points, break if (neighbor_sqdist > k_weight(C) + m_sq_half_sparsity) break; @@ -3777,7 +3821,6 @@ next_face: std::size_t neighbor_point_idx = nn_it->first; FT point_to_C_power_sqdist = k_power_dist(C, compute_perturbed_weighted_point(neighbor_point_idx)); - //std::cerr << point_to_Cp_power_sqdist << "\n"; // CJTODO TEMP // If the point is ACTUALLY "inside" S if (point_to_C_power_sqdist <= FT(-0.000001) && inconsistent_simplex.find(neighbor_point_idx) == @@ -3848,7 +3891,7 @@ next_face: inconsistencies_found = true; break; } - // CJTODO TEMP + // CJTODO DEBUG /*else if (m_ambient_dim - m_intrinsic_dim == 1) { typename K::Difference_of_points_d k_diff_pts = @@ -4561,8 +4604,8 @@ public: // Return a pair void check_correlation_between_inconsistencies_and_fatness() const { - std::ofstream csv_consistent("output/correlation_consistent.csv"); // CJTODO TEMP - std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO TEMP + std::ofstream csv_consistent("output/correlation_consistent.csv"); // CJTODO DEBUG + std::ofstream csv_inconsistent("output/correlation_inconsistent.csv"); // CJTODO DEBUG if (m_intrinsic_dim < 3) { std::cerr From 26a8b93870c7a664de0a3f539585a8aafb1586a8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Feb 2016 19:53:01 +0100 Subject: [PATCH 264/269] Add CGAL_TC_EXPORT_ALL_COORDS_IN_OFF macro --- .../Tangential_complex/benchmark_tc.cpp | 3 ++- .../include/CGAL/Tangential_complex.h | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp index 28285a2c728..cabb38fc335 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -15,7 +15,8 @@ //#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_SPARSIFIED_POINT_SET +//#define CGAL_TC_EXPORT_ALL_COORDS_IN_OFF const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 500000; // 1e10 diff --git a/Tangential_complex/include/CGAL/Tangential_complex.h b/Tangential_complex/include/CGAL/Tangential_complex.h index 3ee12855b3c..cd81510902e 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex.h +++ b/Tangential_complex/include/CGAL/Tangential_complex.h @@ -2669,6 +2669,7 @@ next_face: } // Project the point in the tangent space + // Resulting point coords are expressed in tsb's space Tr_bare_point project_point(const Point &p, const Tangent_space_basis &tsb) const { @@ -2703,6 +2704,7 @@ next_face: // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p + // Resulting point coords are expressed in tsb's space Tr_point project_point_and_compute_weight(const Weighted_point &wp, const Tangent_space_basis &tsb, const Tr_traits &tr_traits) const @@ -2715,11 +2717,15 @@ next_face: k_drop_w(wp), k_point_weight(wp), tsb, tr_traits); } + // Same as above, with slightly different parameters Tr_point project_point_and_compute_weight(const Point &p, const FT w, const Tangent_space_basis &tsb, const Tr_traits &tr_traits) const { const int point_dim = m_k.point_dimension_d_object()(p); + + typename K::Construct_point_d constr_pt = + m_k.construct_point_d_object(); typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); typename K::Difference_of_points_d diff_points = @@ -2739,7 +2745,7 @@ next_face: // Ambiant-space coords of the projected point std::vector p_proj(ccci(origin), ccci(origin, 0)); coords.reserve(tsb.dimension()); - for (std::size_t i = 0 ; i < m_intrinsic_dim ; ++i) + for (std::size_t i = 0 ; i < tsb.dimension() ; ++i) { // Local coords are given by the scalar product with the vectors of tsb FT c = scalar_pdct(v, tsb[i]); @@ -2769,14 +2775,13 @@ next_face: FT sq_dist_to_proj_pt = 0; if (!same_dim) { - Point projected_pt(point_dim, p_proj.begin(), p_proj.end()); + Point projected_pt = constr_pt(point_dim, p_proj.begin(), p_proj.end()); sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt); } return tr_traits.construct_weighted_point_d_object() ( - tr_traits.construct_point_d_object()( - static_cast(coords.size()), coords.begin(), coords.end()), + constr_pt(static_cast(coords.size()), coords.begin(), coords.end()), w - sq_dist_to_proj_pt ); } @@ -3462,7 +3467,12 @@ next_face: typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); +#ifdef CGAL_TC_EXPORT_ALL_COORDS_IN_OFF + int num_coords = m_ambient_dim; +#else int num_coords = min(m_ambient_dim, 3); +#endif + #ifdef CGAL_TC_EXPORT_NORMALS OS_container::const_iterator it_os = m_orth_spaces.begin(); #endif From 233bfc4f4d5f04a585c1c2e7f23cd8e966c7b7ab Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 12 Feb 2016 19:54:09 +0100 Subject: [PATCH 265/269] Fix usage of load_points_from_file --- .../Tangential_complex/benchmark_mesh_d.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp index 0338d46ffeb..1471adbf990 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -6,6 +6,9 @@ # define TBB_USE_THREADING_TOOL #endif +#include + +const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 100000000; #include #include @@ -160,7 +163,7 @@ void make_mesh( std::set > wrong_number_of_cofaces_simplices; std::set > unconnected_stars_simplices; bool is_pure_pseudomanifold = mesh.complex().is_pure_pseudomanifold( - intrinsic_dim, mesh.number_of_vertices(), false, 1, + 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, @@ -302,6 +305,7 @@ int main() #endif std::vector points; + Mesh::TS_container tangent_spaces; if (input == "generate_moment_curve") { @@ -373,8 +377,10 @@ int main() } else { - load_points_from_file( - input, std::back_inserter(points)/*, 600*/); + load_points_from_file( + input, std::back_inserter(points), + std::back_inserter(tangent_spaces), + ONLY_LOAD_THE_FIRST_N_POINTS); } #ifdef CGAL_MESH_D_PROFILING From 7756c3ae9afdc89376c4f06bfc489981d2aeaec1 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 22 Feb 2016 16:14:14 +0100 Subject: [PATCH 266/269] Faster intersection computation --- .../Tangential_complex/benchmark_mesh_d.cpp | 11 +- Tangential_complex/include/CGAL/Mesh_d.h | 185 ++++++++++++++---- 2 files changed, 154 insertions(+), 42 deletions(-) diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp index 1471adbf990..ce01f749e6e 100644 --- a/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_mesh_d.cpp @@ -38,13 +38,13 @@ const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt"; typedef CGAL::Epick_d Kernel; typedef Kernel::FT FT; typedef Kernel::Point_d Point; -typedef CGAL::Mesh_d< - Kernel, CGAL::Dynamic_dimension_tag, - CGAL::Parallel_tag> Mesh; +typedef CGAL::Mesh_d 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 @@ -90,6 +90,7 @@ void make_mesh( const char *input_name = "mesh") { Kernel k; + Kernel lk; // local kernel (intrinsic dim) //=========================================================================== // Init @@ -131,9 +132,9 @@ void make_mesh( #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); + points_not_sparse.begin(), points_not_sparse.end(), k, lk); #else - Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim, k); + Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim, k, lk); #endif double init_time = t.elapsed(); t.reset(); diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h index 3d72ea2e4d5..c935f376355 100644 --- a/Tangential_complex/include/CGAL/Mesh_d.h +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -80,7 +80,7 @@ private: /// The class Mesh_d represents a d-dimensional mesh template < typename Kernel_, // ambiant kernel - typename DimensionTag, // intrinsic dimension + typename Local_kernel_, // local kernel (intrinsic dimension) typename Concurrency_tag = CGAL::Parallel_tag, typename Tr = Delaunay_triangulation < @@ -98,17 +98,19 @@ class Mesh_d typedef Kernel_ K; typedef typename K::FT FT; typedef typename K::Point_d Point; + typedef typename K::Weighted_point_d Weighted_point; typedef typename K::Vector_d Vector; + typedef Local_kernel_ LK; + typedef typename LK::Point_d Local_point; + typedef typename LK::Weighted_point_d Local_weighted_point; + typedef Tr Triangulation; typedef typename Triangulation::Vertex_handle Tr_vertex_handle; typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle; typedef typename Triangulation::Finite_full_cell_const_iterator Tr_finite_full_cell_const_iterator; - typedef Basis Tangent_space_basis; - typedef Basis Orthogonal_space_basis; - typedef std::vector Points; typedef Point_cloud_data_structure Points_ds; @@ -121,8 +123,11 @@ class Mesh_d typedef std::set Indexed_simplex; public: + typedef Basis Tangent_space_basis; + typedef Basis Orthogonal_space_basis; typedef std::vector TS_container; typedef std::vector OS_container; + private: // For transform_iterator @@ -163,9 +168,11 @@ public: #ifdef CGAL_MESH_D_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM InputIterator first_for_tse, InputIterator last_for_tse, #endif - const K &k = K() + const K &k = K(), + const LK &lk = LK() ) : m_k(k) + , m_lk(lk) , m_intrinsic_dim(intrinsic_dimension) , m_half_sparsity(0.5*sparsity) , m_sq_half_sparsity(m_half_sparsity*m_half_sparsity) @@ -287,7 +294,7 @@ public: } }*/ - Get_functor::type sum_vecs(m_k); + Get_functor::type sum_vecs(m_k); // Extract complex // CJTODO: parallelize @@ -311,7 +318,7 @@ public: bool keep_it = false; bool is_uncertain = false; -#ifdef MESH_D_FILTER_BY_TESTING_ALL_VERTICES_TANGENT_PLANES +#ifdef CGAL_MESH_D_FILTER_BY_TESTING_ALL_VERTICES_TANGENT_PLANES int num_intersections = 0; for (auto vh : kf) // CJTODO C++11 { @@ -331,34 +338,30 @@ public: } #else // Compute the intersection with all tangent planes of the vertices - // of the k-face + // of the k-face then compute a weighted barycenter FT sum_weights = 0; Vector weighted_sum_of_inters = m_k.construct_vector_d_object()(m_ambient_dim); for (auto vh : kf) // CJTODO C++11 { - boost::optional intersection = + Point intersection = compute_aff_of_voronoi_face_and_tangent_subspace_intersection( boost::adaptors::transform(kf, vertex_handle_to_point), +#ifdef CGAL_MESH_D_USE_LINEAR_PROG_TO_COMPUTE_INTERSECTION m_orth_spaces[vh->data()]); +#else + m_tangent_spaces[vh->data()]); +#endif - if (intersection) - { - FT weight = - FT(1) / m_k.squared_distance_d_object()(vh->point(), *intersection); - sum_weights += weight; - weighted_sum_of_inters = sum_vecs( - weighted_sum_of_inters, - m_k.scaled_vector_d_object()( - m_k.point_to_vector_d_object()(*intersection), weight)); - } - else - { - // CJTODO TEMP DEBUG - std::cerr << std::hex << (unsigned int)&k_face << std::dec - << red << "No intersection" << white << "\n"; - } + FT weight = + FT(1) / m_k.squared_distance_d_object()(vh->point(), intersection); + sum_weights += weight; + weighted_sum_of_inters = sum_vecs( + weighted_sum_of_inters, + m_k.scaled_vector_d_object()( + m_k.point_to_vector_d_object()(intersection), weight)); } + if (sum_weights > 0) { // Compute the weighted barycenter @@ -674,6 +677,85 @@ private: return common_neighbors; } + Point unproject_point(const Local_point &lp, + const Tangent_space_basis &tsb) const + { + typename K::Translated_point_d k_transl = + m_k.translated_point_d_object(); + typename K::Scaled_vector_d k_scaled_vec = + m_k.scaled_vector_d_object(); + typename LK::Compute_coordinate_d coord = + m_lk.compute_coordinate_d_object(); + + Point global_point = m_points[tsb.origin()]; + for (int i = 0 ; i < m_intrinsic_dim ; ++i) + { + global_point = k_transl( + global_point, k_scaled_vec(tsb[i], coord(lp, i))); + } + + return global_point; + } + + // Project the point in the tangent space + // The weight will be the squared distance between p and the projection of p + // Resulting point coords are expressed in tsb's space + Local_weighted_point project_point_and_compute_weight( + const Point &p, const FT w, const Tangent_space_basis &tsb) const + { + const int point_dim = m_k.point_dimension_d_object()(p); + + typename K::Construct_point_d constr_pt = + m_k.construct_point_d_object(); + typename K::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename K::Difference_of_points_d diff_points = + m_k.difference_of_points_d_object(); + typename K::Compute_coordinate_d coord = + m_k.compute_coordinate_d_object(); + typename K::Construct_cartesian_const_iterator_d ccci = + m_k.construct_cartesian_const_iterator_d_object(); + + typename LK::Construct_point_d local_constr_pt = + m_lk.construct_point_d_object(); + + Point const& origin = m_points[tsb.origin()]; + Vector v = diff_points(p, origin); + + // Same dimension? Then the weight is 0 + bool same_dim = (point_dim == tsb.dimension()); + + std::vector coords; + // Ambiant-space coords of the projected point + std::vector p_proj(ccci(origin), ccci(origin, 0)); + coords.reserve(tsb.dimension()); + for (std::size_t i = 0 ; i < tsb.dimension() ; ++i) + { + // Local coords are given by the scalar product with the vectors of tsb + FT c = scalar_pdct(v, tsb[i]); + coords.push_back(c); + + // p_proj += c * tsb[i] + for (int j = 0 ; j < point_dim ; ++j) + p_proj[j] += c * coord(tsb[i], j); + } + + // Same dimension? Then the weight is 0 + FT sq_dist_to_proj_pt = 0; + if (!same_dim) + { + Point projected_pt = constr_pt(point_dim, p_proj.begin(), p_proj.end()); + sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt); + } + + return m_lk.construct_weighted_point_d_object() + ( + local_constr_pt( + static_cast(coords.size()), coords.begin(), coords.end()), + w - sq_dist_to_proj_pt + ); + } + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Q: vertices which are common neighbors of all vertices of P // Note that the computation is made in global coordinates. @@ -688,12 +770,9 @@ private: // Fv: Voronoi k-face // Fd: dual, (D-k)-face of Delaunay (p0, p1, ..., pn) - typename Kernel::Scalar_product_d scalar_pdct = - m_k.scalar_product_d_object(); - typename Kernel::Point_to_vector_d pt_to_vec = - m_k.point_to_vector_d_object(); - typename Kernel::Compute_coordinate_d coord = - m_k.compute_coordinate_d_object(); + typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object(); + typename K::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object(); + typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object(); std::size_t card_P = P.size(); std::size_t card_Q = Q.size(); @@ -829,22 +908,53 @@ private: return ret; } +#ifdef CGAL_MESH_D_USE_LINEAR_PROG_TO_COMPUTE_INTERSECTION + // CJTODO TEMP: this is the old slow code => remove this macro + // Returns any point of the intersection between aff(voronoi_cell) and a // tangent space. // P: dual face in Delaunay triangulation (p0, p1, ..., pn) // Return value: the point coordinates are expressed in the tsb base template - boost::optional - compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + Point + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( Point_range_a const& P, Orthogonal_space_basis const& orthogonal_subspace_basis) const { - // As we're only interested by aff(v), Q is empty - return compute_voronoi_face_and_tangent_subspace_intersection( - P, std::vector(), - orthogonal_subspace_basis); + // As we're only interested by aff(v), Q is empty + return *compute_voronoi_face_and_tangent_subspace_intersection( + P, std::vector(), + orthogonal_subspace_basis); + } + +#else + + // Returns any point of the intersection between aff(voronoi_cell) and a + // tangent space. + // P: dual face in Delaunay triangulation (p0, p1, ..., pn) + // Return value: the point coordinates are expressed in the tsb base + template + Point + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + Point_range const& P, + Tangent_space_basis const& tangent_subspace_basis) const + { + std::vector projected_pts; + for (auto const& p : P) + { + projected_pts.push_back( + project_point_and_compute_weight(p, FT(0), tangent_subspace_basis)); } + Local_weighted_point power_center = + m_lk.power_center_d_object()(projected_pts.begin(), projected_pts.end()); + + return unproject_point( + m_lk.point_drop_weight_d_object()(power_center), tangent_subspace_basis); + } + +#endif + std::map get_k_faces_and_neighbor_vertices(Triangulation const& tr) { typedef std::map K_faces_and_neighbor_vertices; @@ -1159,6 +1269,7 @@ public: private: const K m_k; + const LK m_lk; const int m_intrinsic_dim; const double m_half_sparsity; const double m_sq_half_sparsity; From 6817479015156d30e30230c363da48f2fb7868bb Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 2 Mar 2016 16:16:42 +0100 Subject: [PATCH 267/269] Clean-up --- .../CGAL/Tangential_complex/Point_cloud.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h index 293b61fa520..9543e827a40 100644 --- a/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h +++ b/Tangential_complex/include/CGAL/Tangential_complex/Point_cloud.h @@ -21,21 +21,15 @@ #ifndef POINT_CLOUD_H #define POINT_CLOUD_H -#include -#include - #include #include #include #include -#include -#include -#include #include -#include -#include +#include +#include #ifdef CGAL_TC_ANN_IS_AVAILABLE # include @@ -188,9 +182,9 @@ template class Point_cloud_adaptator__nanoflann { public: - typedef typename Point_container_::value_type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + 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) From 3f6989dcd7322116c7ed7a22835db9ed7555c9b8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 2 Mar 2016 16:17:57 +0100 Subject: [PATCH 268/269] Try to translate the tangent plane to be closer to the surface --- Tangential_complex/include/CGAL/Mesh_d.h | 182 ++++++++++++++++++----- 1 file changed, 147 insertions(+), 35 deletions(-) diff --git a/Tangential_complex/include/CGAL/Mesh_d.h b/Tangential_complex/include/CGAL/Mesh_d.h index c935f376355..868f2fabd54 100644 --- a/Tangential_complex/include/CGAL/Mesh_d.h +++ b/Tangential_complex/include/CGAL/Mesh_d.h @@ -232,6 +232,15 @@ public: Wall_clock_timer t; #endif + typedef CGAL::Epick_d Orth_K; + typedef typename Orth_K::Point_d Orth_K_point; + typedef typename Orth_K::Vector_d Orth_K_vector; + + int orth_dim = m_ambient_dim - m_intrinsic_dim; + Orth_K orth_k(orth_dim); + + Get_functor::type orth_k_sum_vecs(orth_k); + // Tangent and orthogonal spaces for (std::size_t i = 0; i < m_points.size(); ++i) { @@ -341,7 +350,7 @@ public: // of the k-face then compute a weighted barycenter FT sum_weights = 0; Vector weighted_sum_of_inters = - m_k.construct_vector_d_object()(m_ambient_dim); + orth_k.construct_vector_d_object()(m_ambient_dim); for (auto vh : kf) // CJTODO C++11 { Point intersection = @@ -369,6 +378,67 @@ public: m_k.scaled_vector_d_object()( weighted_sum_of_inters, FT(1) / sum_weights)); + //**************************************************************** + // Translate the tangent plane to be closer to the surface + //**************************************************************** + + // Estimate the normal subspace at point "avg_inters" + Tangent_space_basis tsb; + Orthogonal_space_basis osb; + tsb = compute_tangent_space( + avg_inters, std::numeric_limits::max(), + true/*normalize*/, &osb); + + unsigned int num_points_for_nghb_query = static_cast( + std::pow(BASE_VALUE_FOR_PCA, m_intrinsic_dim)); + KNS_range kns_range = m_points_ds.query_ANN( + avg_inters, num_points_for_nghb_query, false); + + FT sum_weights_of_barycenter = 0; + Orth_K_vector weighted_sum_of_neighbors = + orth_k.construct_vector_d_object()(orth_dim); + KNS_iterator nn_it = kns_range.begin(); + for (unsigned int j = 0 ; + j < num_points_for_nghb_query && nn_it != kns_range.end() ; + ++j, ++nn_it) + { + Point const& nghb = m_points[nn_it->first]; + + Orth_K_point proj_nghb = project_point(nghb, osb, orth_k, &avg_inters); + + FT weight = + FT(1) / m_k.squared_distance_d_object()(nghb, avg_inters); + sum_weights_of_barycenter += weight; + weighted_sum_of_neighbors = orth_k_sum_vecs( + weighted_sum_of_neighbors, + orth_k.scaled_vector_d_object()( + orth_k.point_to_vector_d_object()(proj_nghb), weight)); + } + + //sum_weights_of_barycenter *= 8; // CJTODO TEMP + + // Compute the weighted barycenter + Point translated_origin = unproject_point( + orth_k.vector_to_point_d_object()( + orth_k.scaled_vector_d_object()( + weighted_sum_of_neighbors, FT(1) / sum_weights_of_barycenter)), + osb, + orth_k, + &avg_inters); + + Point translated_inters = + compute_aff_of_voronoi_face_and_tangent_subspace_intersection( + boost::adaptors::transform(kf, vertex_handle_to_point), + tsb, &translated_origin); + + // CJTODO TEMP: exact intersection for the sphere of radius 1 + //translated_inters = orth_k.vector_to_point_d_object()( + // normalize_vector(orth_k.point_to_vector_d_object()(avg_inters), m_k)); + + //**************************************************************** + // Keep the simplex or not? + //**************************************************************** + keep_it = true; // Check if the averaged intersection "i" is inside the Voronoi cell, i.e. // for each common neighbor qi, (i - p0)˛ <= (i - qi)˛ @@ -377,8 +447,8 @@ public: { // If a neighbor is closer than p0 to the average intersection, then // the average intersection is inside another Voronoi cell - if (m_k.squared_distance_d_object()(p0, avg_inters) > - m_k.squared_distance_d_object()(neighbor_vh->point(), avg_inters)) + if (m_k.squared_distance_d_object()(p0, translated_inters) > + m_k.squared_distance_d_object()(neighbor_vh->point(), translated_inters)) { keep_it = false; break; @@ -436,9 +506,10 @@ private: return *s.rbegin() == std::numeric_limits::max(); } + // If i = std::numeric_limits::max(), it is ignored Tangent_space_basis compute_tangent_space( const Point &p - , const std::size_t i + , const std::size_t i = std::numeric_limits::max() , bool normalize_basis = true , Orthogonal_space_basis *p_orth_space_basis = NULL) { @@ -454,7 +525,8 @@ private: Tangent_space_basis ts(i); ts.reserve(m_intrinsic_dim); ts.push_back(scaled_vec(t, FT(1)/CGAL::sqrt(sqlen(t)))); - m_are_tangent_spaces_computed[i] = true; + if (i != std::numeric_limits::max()) + m_are_tangent_spaces_computed[i] = true; return ts; @@ -476,7 +548,8 @@ private: ts.push_back(scaled_vec(t1, FT(1)/CGAL::sqrt(sqlen(t1)))); ts.push_back(scaled_vec(t2, FT(1)/CGAL::sqrt(sqlen(t2)))); - m_are_tangent_spaces_computed[i] = true; + if (i != std::numeric_limits::max()) + m_are_tangent_spaces_computed[i] = true; return ts; @@ -493,7 +566,8 @@ private: ts.push_back(t); } - m_are_tangent_spaces_computed[i] = true; + if (i != std::numeric_limits::max()) + m_are_tangent_spaces_computed[i] = true; //return compute_gram_schmidt_basis(ts, m_k); return ts; @@ -551,7 +625,7 @@ private: Eigen::MatrixXd cov = centered.adjoint() * centered; Eigen::SelfAdjointEigenSolver eig(cov); - Tangent_space_basis tsb(i); // p = compute_perturbed_point(i) here + Tangent_space_basis tsb(i); // The eigenvectors are sorted in increasing order of their corresponding // eigenvalues @@ -599,7 +673,8 @@ private: } } - m_are_tangent_spaces_computed[i] = true; + if (i != std::numeric_limits::max()) + m_are_tangent_spaces_computed[i] = true; //************************************************************************* @@ -677,31 +752,66 @@ private: return common_neighbors; } - Point unproject_point(const Local_point &lp, - const Tangent_space_basis &tsb) const + template + Point unproject_point(Projected_point const& lp, + Basis_ const& basis, Projection_space_kernel const& lk, + Point const* origin = NULL) const { typename K::Translated_point_d k_transl = m_k.translated_point_d_object(); typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object(); - typename LK::Compute_coordinate_d coord = - m_lk.compute_coordinate_d_object(); + typename Projection_space_kernel::Compute_coordinate_d coord = + lk.compute_coordinate_d_object(); - Point global_point = m_points[tsb.origin()]; - for (int i = 0 ; i < m_intrinsic_dim ; ++i) + Point global_point = (origin ? *origin : m_points[basis.origin()]); + for (int i = 0 ; i < basis.dimension() ; ++i) { global_point = k_transl( - global_point, k_scaled_vec(tsb[i], coord(lp, i))); + global_point, k_scaled_vec(basis[i], coord(lp, i))); } return global_point; } + // Project the point on a subspace + // Resulting point coords are expressed in basis' space + template + typename Projection_space_kernel::Point_d project_point( + const Point &p, const Basis_ &basis, Projection_space_kernel const& psk, + Point const* origin = NULL) const + { + typename K::Scalar_product_d scalar_pdct = + m_k.scalar_product_d_object(); + typename K::Difference_of_points_d diff_points = + m_k.difference_of_points_d_object(); + + Point const& orig = (origin ? *origin : m_points[basis.origin()]); + Vector v = diff_points(p, orig); + + std::vector coords; + // Ambiant-space coords of the projected point + coords.reserve(basis.dimension()); + for (std::size_t i = 0 ; i < basis.dimension() ; ++i) + { + // Local coords are given by the scalar product with the vectors of basis + FT coord = scalar_pdct(v, basis[i]); + coords.push_back(coord); + } + + return psk.construct_point_d_object()(static_cast( + coords.size()), coords.begin(), coords.end()); + } + // Project the point in the tangent space // The weight will be the squared distance between p and the projection of p // Resulting point coords are expressed in tsb's space - Local_weighted_point project_point_and_compute_weight( - const Point &p, const FT w, const Tangent_space_basis &tsb) const + template + typename Projection_space_kernel::Weighted_point_d + project_point_and_compute_weight( + const Point &p, const FT w, const Basis_ &basis, + Projection_space_kernel const& psk, + Point const* origin = NULL) const { const int point_dim = m_k.point_dimension_d_object()(p); @@ -716,28 +826,28 @@ private: typename K::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object(); - typename LK::Construct_point_d local_constr_pt = - m_lk.construct_point_d_object(); + typename Projection_space_kernel::Construct_point_d local_constr_pt = + psk.construct_point_d_object(); - Point const& origin = m_points[tsb.origin()]; - Vector v = diff_points(p, origin); + Point const& orig = (origin ? *origin : m_points[basis.origin()]); + Vector v = diff_points(p, orig); // Same dimension? Then the weight is 0 - bool same_dim = (point_dim == tsb.dimension()); + bool same_dim = (point_dim == basis.dimension()); std::vector coords; // Ambiant-space coords of the projected point - std::vector p_proj(ccci(origin), ccci(origin, 0)); - coords.reserve(tsb.dimension()); - for (std::size_t i = 0 ; i < tsb.dimension() ; ++i) + std::vector p_proj(ccci(orig), ccci(orig, 0)); + coords.reserve(basis.dimension()); + for (std::size_t i = 0 ; i < basis.dimension() ; ++i) { - // Local coords are given by the scalar product with the vectors of tsb - FT c = scalar_pdct(v, tsb[i]); + // Local coords are given by the scalar product with the vectors of basis + FT c = scalar_pdct(v, basis[i]); coords.push_back(c); - // p_proj += c * tsb[i] + // p_proj += c * basis[i] for (int j = 0 ; j < point_dim ; ++j) - p_proj[j] += c * coord(tsb[i], j); + p_proj[j] += c * coord(basis[i], j); } // Same dimension? Then the weight is 0 @@ -748,7 +858,7 @@ private: sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt); } - return m_lk.construct_weighted_point_d_object() + return psk.construct_weighted_point_d_object() ( local_constr_pt( static_cast(coords.size()), coords.begin(), coords.end()), @@ -937,20 +1047,22 @@ private: Point compute_aff_of_voronoi_face_and_tangent_subspace_intersection( Point_range const& P, - Tangent_space_basis const& tangent_subspace_basis) const + Tangent_space_basis const& tangent_subspace_basis, + Point const* origin = NULL) const { std::vector projected_pts; for (auto const& p : P) { - projected_pts.push_back( - project_point_and_compute_weight(p, FT(0), tangent_subspace_basis)); + projected_pts.push_back(project_point_and_compute_weight( + p, FT(0), tangent_subspace_basis, m_lk, origin)); } Local_weighted_point power_center = m_lk.power_center_d_object()(projected_pts.begin(), projected_pts.end()); return unproject_point( - m_lk.point_drop_weight_d_object()(power_center), tangent_subspace_basis); + m_lk.point_drop_weight_d_object()(power_center), + tangent_subspace_basis, m_lk, origin); } #endif From 9d8e3fb03e051f98b51e66e7ca33a0b830e4731a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 16 Mar 2016 17:44:37 +0100 Subject: [PATCH 269/269] Export to RIB (RenderMan) Can be rendered using Pixie --- .../CGAL/Tangential_complex/RIB_exporter.h | 288 ++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 Tangential_complex/include/CGAL/Tangential_complex/RIB_exporter.h diff --git a/Tangential_complex/include/CGAL/Tangential_complex/RIB_exporter.h b/Tangential_complex/include/CGAL/Tangential_complex/RIB_exporter.h new file mode 100644 index 00000000000..fb19551e8e1 --- /dev/null +++ b/Tangential_complex/include/CGAL/Tangential_complex/RIB_exporter.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 + +#include +#include + +namespace CGAL { +namespace Tangential_complex_ { + +template +class RIB_exporter +{ + typedef typename PointRandomAccessRange::value_type Point; +public: + + typedef std::tuple 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 > triangles; + // Get the triangles composing the simplex + combinations(simplex, 3, std::back_inserter(triangles)); + for (auto const& t : triangles) + write_triangle(t); + } + } + + template + 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