From 9544a1cfb20e98f602611e334e278abee672c239 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 29 Jul 2014 17:23:05 +0200 Subject: [PATCH 01/92] 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 02/92] 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 03/92] 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 04/92] 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 05/92] 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 06/92] 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 07/92] 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 08/92] 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 09/92] 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 10/92] 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 11/92] 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 12/92] 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 13/92] 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 14/92] 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 15/92] 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 16/92] 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 17/92] 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 18/92] 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 19/92] 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 20/92] 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 21/92] 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 22/92] 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 23/92] 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 24/92] 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 25/92] 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 26/92] 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 27/92] 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 28/92] 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 29/92] 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 30/92] 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 31/92] 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 32/92] 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 33/92] 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 34/92] 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 35/92] 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 36/92] 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 37/92] 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 38/92] 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 39/92] 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 40/92] 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 41/92] 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 42/92] 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 43/92] 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 44/92] 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 45/92] 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 46/92] 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 47/92] 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 48/92] 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 49/92] 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 50/92] 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 51/92] 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 52/92] 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 53/92] 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 54/92] 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 55/92] 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 56/92] 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 57/92] 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 58/92] 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 59/92] 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 60/92] 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 61/92] 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 62/92] 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 63/92] 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 64/92] 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 65/92] 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 66/92] 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 67/92] 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 68/92] 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 69/92] 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 70/92] 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 71/92] 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 72/92] 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 73/92] 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 74/92] 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 75/92] 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 76/92] 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 77/92] 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 78/92] 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 79/92] 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 80/92] 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 81/92] 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 82/92] 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 83/92] 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 84/92] 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 85/92] 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 86/92] 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 87/92] 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 88/92] 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 89/92] 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 90/92] "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 91/92] 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 92/92] 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; }