From f6a78c1b7ea70b71fdb96f2fc17c44700e4b980a Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 31 Oct 2019 11:48:57 +0100 Subject: Add a get_point method for Alpha_complex_3d. Change Point_3 type to be either Weighted_point_3 or Bare_point_3 (new type). Add some get_point method tests. --- .../benchmark/Alpha_complex_3d_benchmark.cpp | 10 +-- .../example/Alpha_complex_3d_from_points.cpp | 2 +- .../Weighted_alpha_complex_3d_from_points.cpp | 12 ++-- src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 77 +++++++++++++++------- .../test/Alpha_complex_3d_unit_test.cpp | 53 ++++++++++++++- .../test/Periodic_alpha_complex_3d_unit_test.cpp | 37 +++++++---- .../test/Weighted_alpha_complex_3d_unit_test.cpp | 50 +++++++++----- ...eighted_periodic_alpha_complex_3d_unit_test.cpp | 24 +++---- .../utilities/alpha_complex_3d_persistence.cpp | 4 +- 9 files changed, 189 insertions(+), 80 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp b/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp index 005a712a..e84f5229 100644 --- a/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp +++ b/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp @@ -71,10 +71,10 @@ void benchmark_points_on_torus_3D(const std::string& msg) { for (int nb_points = 1000; nb_points <= 125000; nb_points *= 5) { std::cout << " Alpha complex 3d on torus with " << nb_points << " points." << std::endl; std::vector points_on_torus = Gudhi::generate_points_on_torus_3D(nb_points, 1.0, 0.5); - std::vector points; + std::vector points; for (auto p : points_on_torus) { - points.push_back(typename Alpha_complex_3d::Point_3(p[0], p[1], p[2])); + points.push_back(typename Alpha_complex_3d::Bare_point_3(p[0], p[1], p[2])); } Gudhi::Clock ac_create_clock(" benchmark_points_on_torus_3D - Alpha complex 3d creation"); @@ -115,7 +115,7 @@ void benchmark_weighted_points_on_torus_3D(const std::string& msg) { std::cout << " Alpha complex 3d on torus with " << nb_points << " points." << std::endl; std::vector points_on_torus = Gudhi::generate_points_on_torus_3D(nb_points, 1.0, 0.5); - using Point = typename Weighted_alpha_complex_3d::Point_3; + using Point = typename Weighted_alpha_complex_3d::Bare_point_3; using Weighted_point = typename Weighted_alpha_complex_3d::Weighted_point_3; std::vector points; @@ -158,7 +158,7 @@ void benchmark_periodic_points(const std::string& msg) { for (double nb_points = 10.; nb_points <= 40.; nb_points += 10.) { std::cout << " Periodic alpha complex 3d with " << nb_points * nb_points * nb_points << " points." << std::endl; - using Point = typename Periodic_alpha_complex_3d::Point_3; + using Point = typename Periodic_alpha_complex_3d::Bare_point_3; std::vector points; for (double i = 0; i < nb_points; i++) { @@ -206,7 +206,7 @@ void benchmark_weighted_periodic_points(const std::string& msg) { std::cout << " Weighted periodic alpha complex 3d with " << nb_points * nb_points * nb_points << " points." << std::endl; - using Point = typename Weighted_periodic_alpha_complex_3d::Point_3; + using Point = typename Weighted_periodic_alpha_complex_3d::Bare_point_3; using Weighted_point = typename Weighted_periodic_alpha_complex_3d::Weighted_point_3; std::vector points; diff --git a/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp index 0e359a27..7bd35cc6 100644 --- a/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp @@ -8,7 +8,7 @@ #include // for numeric limits using Alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d; -using Point = Alpha_complex_3d::Point_3; +using Point = Alpha_complex_3d::Bare_point_3; using Vector_of_points = std::vector; int main(int argc, char **argv) { diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp index ac11b68c..fcf80802 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp @@ -10,7 +10,7 @@ // Complexity = FAST, weighted = true, periodic = false using Weighted_alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d; -using Point = Weighted_alpha_complex_3d::Point_3; +using Bare_point = Weighted_alpha_complex_3d::Bare_point_3; using Weighted_point = Weighted_alpha_complex_3d::Weighted_point_3; int main(int argc, char **argv) { @@ -18,11 +18,11 @@ int main(int argc, char **argv) { // Init of a list of points and weights from a small molecule // ---------------------------------------------------------------------------- std::vector weighted_points; - weighted_points.push_back(Weighted_point(Point(1, -1, -1), 4.)); - weighted_points.push_back(Weighted_point(Point(-1, 1, -1), 4.)); - weighted_points.push_back(Weighted_point(Point(-1, -1, 1), 4.)); - weighted_points.push_back(Weighted_point(Point(1, 1, 1), 4.)); - weighted_points.push_back(Weighted_point(Point(2, 2, 2), 1.)); + weighted_points.push_back(Weighted_point(Bare_point(1, -1, -1), 4.)); + weighted_points.push_back(Weighted_point(Bare_point(-1, 1, -1), 4.)); + weighted_points.push_back(Weighted_point(Bare_point(-1, -1, 1), 4.)); + weighted_points.push_back(Weighted_point(Bare_point(1, 1, 1), 4.)); + weighted_points.push_back(Weighted_point(Bare_point(2, 2, 2), 1.)); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index 13ebb9c1..c36bed1f 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -43,7 +43,7 @@ #include #include #include -#include +#include // for std::size_t #include // for std::unique_ptr #include // for std::conditional and std::enable_if #include // for numeric_limits<> @@ -225,23 +225,23 @@ class Alpha_complex_3d { * Must be compatible with double. */ using FT = typename Alpha_shape_3::FT; - /** \brief Gives public access to the Point_3 type. Here is a Point_3 constructor example: + /** \brief Gives public access to the Bare_point_3 (bare aka. unweighed) type. + * Here is a Bare_point_3 constructor example: \code{.cpp} using Alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d; // x0 = 1., y0 = -1.1, z0 = -1.. -Alpha_complex_3d::Point_3 p0(1., -1.1, -1.); +Alpha_complex_3d::Bare_point_3 p0(1., -1.1, -1.); \endcode * */ - using Point_3 = typename Kernel::Point_3; + using Bare_point_3 = typename Kernel::Point_3; /** \brief Gives public access to the Weighted_point_3 type. A Weighted point can be constructed as follows: \code{.cpp} -using Weighted_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d; +using Weighted_alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d; // x0 = 1., y0 = -1.1, z0 = -1., weight = 4. -Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point_3(1., -1.1, -1.), 4.); +Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_point_3(1., -1.1, -1.), 4.); \endcode * * Note: This type is defined to void if Alpha complex is not weighted. @@ -249,6 +249,11 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point * */ using Weighted_point_3 = typename Triangulation_3::Weighted_point_3; + /** \brief `Alpha_complex_3d::Point_3` type is either a `Alpha_complex_3d::Bare_point_3` (Weighted = false) or a + * `Alpha_complex_3d::Weighted_point_3` (Weighted = true). + */ + using Point_3 = typename std::conditional::type; + private: using Dispatch = CGAL::Dispatch_output_iterator, @@ -264,13 +269,13 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point public: /** \brief Alpha_complex constructor from a list of points. * - * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3` or + * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Bare_point_3` or * `Alpha_complex_3d::Weighted_point_3`. * * @pre Available if Alpha_complex_3d is not Periodic. * * The type InputPointRange must be a range for which std::begin and std::end return input iterators on a - * `Alpha_complex_3d::Point_3` or a `Alpha_complex_3d::Weighted_point_3`. + * `Alpha_complex_3d::Bare_point_3` or a `Alpha_complex_3d::Weighted_point_3`. */ template Alpha_complex_3d(const InputPointRange& points) { @@ -284,13 +289,13 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point * * @exception std::invalid_argument In debug mode, if points and weights do not have the same size. * - * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3`. + * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Bare_point_3`. * @param[in] weights Range of weights on points. Weights shall be in double. * * @pre Available if Alpha_complex_3d is Weighted and not Periodic. * * The type InputPointRange must be a range for which std::begin and - * std::end return input iterators on a `Alpha_complex_3d::Point_3`. + * std::end return input iterators on a `Alpha_complex_3d::Bare_point_3`. * The type WeightRange must be a range for which std::begin and * std::end return an input iterator on a double. */ @@ -318,7 +323,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point * * @exception std::invalid_argument In debug mode, if the size of the cuboid in every directions is not the same. * - * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3` or + * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Bare_point_3` or * `Alpha_complex_3d::Weighted_point_3`. * @param[in] x_min Iso-oriented cuboid x_min. * @param[in] y_min Iso-oriented cuboid y_min. @@ -330,7 +335,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point * @pre Available if Alpha_complex_3d is Periodic. * * The type InputPointRange must be a range for which std::begin and std::end return input iterators on a - * `Alpha_complex_3d::Point_3` or a `Alpha_complex_3d::Weighted_point_3`. + * `Alpha_complex_3d::Bare_point_3` or a `Alpha_complex_3d::Weighted_point_3`. * * @note In weighted version, please check weights are greater than zero, and lower than 1/64*cuboid length * squared. @@ -366,7 +371,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point * @exception std::invalid_argument In debug mode, if a weight is negative, zero, or greater than 1/64*cuboid length * squared. * - * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3`. + * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Bare_point_3`. * @param[in] weights Range of weights on points. Weights shall be in double. * @param[in] x_min Iso-oriented cuboid x_min. * @param[in] y_min Iso-oriented cuboid y_min. @@ -378,7 +383,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point * @pre Available if Alpha_complex_3d is Weighted and Periodic. * * The type InputPointRange must be a range for which std::begin and - * std::end return input iterators on a `Alpha_complex_3d::Point_3`. + * std::end return input iterators on a `Alpha_complex_3d::Bare_point_3`. * The type WeightRange must be a range for which std::begin and * std::end return an input iterator on a double. * The type of x_min, y_min, z_min, x_max, y_max and z_max must be a double. @@ -452,9 +457,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point return false; // ----- >> } - // using Filtration_value = typename SimplicialComplexForAlpha3d::Filtration_value; using Complex_vertex_handle = typename SimplicialComplexForAlpha3d::Vertex_handle; - using Alpha_shape_simplex_tree_map = std::unordered_map; using Simplex_tree_vector_vertex = std::vector; #ifdef DEBUG_TRACES @@ -474,7 +477,6 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point std::cout << "filtration_with_alpha_values returns : " << objects.size() << " objects" << std::endl; #endif // DEBUG_TRACES - Alpha_shape_simplex_tree_map map_cgal_simplex_tree; using Alpha_value_iterator = typename std::vector::const_iterator; Alpha_value_iterator alpha_value_iterator = alpha_values.begin(); for (auto object_iterator : objects) { @@ -484,7 +486,8 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point if (const Cell_handle* cell = CGAL::object_cast(&object_iterator)) { for (auto i = 0; i < 4; i++) { #ifdef DEBUG_TRACES - std::cout << "from cell[" << i << "]=" << (*cell)->vertex(i)->point() << std::endl; + std::cout << "from cell[" << i << "] - Point coordinates (" << (*cell)->vertex(i)->point() << ")" + << std::endl; #endif // DEBUG_TRACES vertex_list.push_back((*cell)->vertex(i)); } @@ -495,7 +498,8 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point for (auto i = 0; i < 4; i++) { if ((*facet).second != i) { #ifdef DEBUG_TRACES - std::cout << "from facet=[" << i << "]" << (*facet).first->vertex(i)->point() << std::endl; + std::cout << "from facet=[" << i << "] - Point coordinates (" << (*facet).first->vertex(i)->point() << ")" + << std::endl; #endif // DEBUG_TRACES vertex_list.push_back((*facet).first->vertex(i)); } @@ -506,7 +510,8 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point } else if (const Edge* edge = CGAL::object_cast(&object_iterator)) { for (auto i : {(*edge).second, (*edge).third}) { #ifdef DEBUG_TRACES - std::cout << "from edge[" << i << "]=" << (*edge).first->vertex(i)->point() << std::endl; + std::cout << "from edge[" << i << "] - Point coordinates (" << (*edge).first->vertex(i)->point() << ")" + << std::endl; #endif // DEBUG_TRACES vertex_list.push_back((*edge).first->vertex(i)); } @@ -516,7 +521,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point } else if (const Alpha_vertex_handle* vertex = CGAL::object_cast(&object_iterator)) { #ifdef DEBUG_TRACES count_vertices++; - std::cout << "from vertex=" << (*vertex)->point() << std::endl; + std::cout << "from vertex - Point coordinates (" << (*vertex)->point() << ")" << std::endl; #endif // DEBUG_TRACES vertex_list.push_back((*vertex)); } @@ -528,7 +533,8 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point // alpha shape not found Complex_vertex_handle vertex = map_cgal_simplex_tree.size(); #ifdef DEBUG_TRACES - std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] not found - insert " << vertex << std::endl; + std::cout << "Point (" << the_alpha_shape_vertex->point() << ") not found - insert new vertex id " << vertex + << std::endl; #endif // DEBUG_TRACES the_simplex.push_back(vertex); map_cgal_simplex_tree.emplace(the_alpha_shape_vertex, vertex); @@ -536,7 +542,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point // alpha shape found Complex_vertex_handle vertex = the_map_iterator->second; #ifdef DEBUG_TRACES - std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] found in " << vertex << std::endl; + std::cout << "Point (" << the_alpha_shape_vertex->point() << ") found as vertex id " << vertex << std::endl; #endif // DEBUG_TRACES the_simplex.push_back(vertex); } @@ -567,9 +573,32 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point return true; } + /** \brief get_point returns the point corresponding to the vertex given as parameter. + * + * @param[in] vertex Vertex handle of the point to retrieve. + * @return The point found. + * @exception std::out_of_range In case vertex is not found (cf. std::vector::at). + */ + const Point_3& get_point(std::size_t vertex) { + if (map_cgal_simplex_tree.size() != cgal_vertex_iterator_vector.size()) { + cgal_vertex_iterator_vector.resize(map_cgal_simplex_tree.size()); + for (auto map_iterator = map_cgal_simplex_tree.begin(); map_iterator != map_cgal_simplex_tree.end(); map_iterator++) { + cgal_vertex_iterator_vector[map_iterator->second] = map_iterator->first; + } + + } + auto cgal_vertex_iterator = cgal_vertex_iterator_vector.at(vertex); + return cgal_vertex_iterator->point(); + } + private: // use of a unique_ptr on cgal Alpha_shape_3, as copy and default constructor is not available - no need to be freed std::unique_ptr alpha_shape_3_ptr_; + + // Map type to switch from CGAL vertex iterator to simplex tree vertex handle. + std::unordered_map map_cgal_simplex_tree; + // Vector type to switch from simplex tree vertex handle to CGAL vertex iterator. + std::vector cgal_vertex_iterator_vector; }; } // namespace alpha_complex diff --git a/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp index 1102838a..cd698a27 100644 --- a/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp @@ -56,21 +56,52 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { // ----------------- std::cout << "Fast alpha complex 3d" << std::endl; - Fast_alpha_complex_3d alpha_complex(get_points()); + std::vector points = get_points(); + Fast_alpha_complex_3d alpha_complex(points); Gudhi::Simplex_tree<> stree; alpha_complex.create_complex(stree); + for (std::size_t index = 0; index < points.size(); index++) { + bool found = false; + for (auto point : points) { + if (point == alpha_complex.get_point(index)) { + found = true; + break; + } + } + // Check all points from alpha complex are found in the input point cloud + BOOST_CHECK(found); + } + // Exception if we go out of range + BOOST_CHECK_THROW(alpha_complex.get_point(points.size()), std::out_of_range); + // ----------------- // Exact version // ----------------- std::cout << "Exact alpha complex 3d" << std::endl; - Exact_alpha_complex_3d exact_alpha_complex(get_points()); + std::vector exact_points = get_points(); + Exact_alpha_complex_3d exact_alpha_complex(exact_points); Gudhi::Simplex_tree<> exact_stree; exact_alpha_complex.create_complex(exact_stree); + for (std::size_t index = 0; index < exact_points.size(); index++) { + bool found = false; + Exact_alpha_complex_3d::Bare_point_3 ap = exact_alpha_complex.get_point(index); + for (auto point : points) { + if ((point.x() == ap.x()) && (point.y() == ap.y()) && (point.z() == ap.z())) { + found = true; + break; + } + } + // Check all points from alpha complex are found in the input point cloud + BOOST_CHECK(found); + } + // Exception if we go out of range + BOOST_CHECK_THROW(exact_alpha_complex.get_point(exact_points.size()), std::out_of_range); + // --------------------- // Compare both versions // --------------------- @@ -110,11 +141,27 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { // ----------------- std::cout << "Safe alpha complex 3d" << std::endl; - Safe_alpha_complex_3d safe_alpha_complex(get_points()); + std::vector safe_points = get_points(); + Safe_alpha_complex_3d safe_alpha_complex(safe_points); Gudhi::Simplex_tree<> safe_stree; safe_alpha_complex.create_complex(safe_stree); + for (std::size_t index = 0; index < safe_points.size(); index++) { + bool found = false; + Safe_alpha_complex_3d::Bare_point_3 ap = safe_alpha_complex.get_point(index); + for (auto point : points) { + if ((point.x() == ap.x()) && (point.y() == ap.y()) && (point.z() == ap.z())) { + found = true; + break; + } + } + // Check all points from alpha complex are found in the input point cloud + BOOST_CHECK(found); + } + // Exception if we go out of range + BOOST_CHECK_THROW(safe_alpha_complex.get_point(safe_points.size()), std::out_of_range); + // --------------------- // Compare both versions // --------------------- diff --git a/src/Alpha_complex/test/Periodic_alpha_complex_3d_unit_test.cpp b/src/Alpha_complex/test/Periodic_alpha_complex_3d_unit_test.cpp index ac3791a4..731763fa 100644 --- a/src/Alpha_complex/test/Periodic_alpha_complex_3d_unit_test.cpp +++ b/src/Alpha_complex/test/Periodic_alpha_complex_3d_unit_test.cpp @@ -44,11 +44,11 @@ typedef boost::mpl::list p_points; + using Bare_point_3 = typename Periodic_alpha_complex_3d::Bare_point_3; + std::vector p_points; // Not important, this is not what we want to check - p_points.push_back(Point_3(0.0, 0.0, 0.0)); + p_points.push_back(Bare_point_3(0.0, 0.0, 0.0)); std::cout << "Check exception throw in debug mode" << std::endl; // Check it throws an exception when the cuboid is not iso @@ -73,13 +73,13 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_periodic) { // --------------------- std::cout << "Fast periodic alpha complex 3d" << std::endl; - using Creator = CGAL::Creator_uniform_3; + using Creator = CGAL::Creator_uniform_3; CGAL::Random random(7); - CGAL::Random_points_in_cube_3 in_cube(1, random); - std::vector p_points; + CGAL::Random_points_in_cube_3 in_cube(1, random); + std::vector p_points; for (int i = 0; i < 50; i++) { - Fast_periodic_alpha_complex_3d::Point_3 p = *in_cube++; + Fast_periodic_alpha_complex_3d::Bare_point_3 p = *in_cube++; p_points.push_back(p); } @@ -88,15 +88,30 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_periodic) { Gudhi::Simplex_tree<> stree; periodic_alpha_complex.create_complex(stree); + for (std::size_t index = 0; index < p_points.size(); index++) { + bool found = false; + Fast_periodic_alpha_complex_3d::Bare_point_3 ap = periodic_alpha_complex.get_point(index); + for (auto point : p_points) { + if ((point.x() == ap.x()) && (point.y() == ap.y()) && (point.z() == ap.z())) { + found = true; + break; + } + } + // Check all points from alpha complex are found in the input point cloud + BOOST_CHECK(found); + } + // Exception if we go out of range + BOOST_CHECK_THROW(periodic_alpha_complex.get_point(p_points.size()), std::out_of_range); + // ---------------------- // Exact periodic version // ---------------------- std::cout << "Exact periodic alpha complex 3d" << std::endl; - std::vector e_p_points; + std::vector e_p_points; for (auto p : p_points) { - e_p_points.push_back(Exact_periodic_alpha_complex_3d::Point_3(p[0], p[1], p[2])); + e_p_points.push_back(Exact_periodic_alpha_complex_3d::Bare_point_3(p[0], p[1], p[2])); } Exact_periodic_alpha_complex_3d exact_alpha_complex(e_p_points, -1., -1., -1., 1., 1., 1.); @@ -142,10 +157,10 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_periodic) { // ---------------------- std::cout << "Safe periodic alpha complex 3d" << std::endl; - std::vector s_p_points; + std::vector s_p_points; for (auto p : p_points) { - s_p_points.push_back(Safe_periodic_alpha_complex_3d::Point_3(p[0], p[1], p[2])); + s_p_points.push_back(Safe_periodic_alpha_complex_3d::Bare_point_3(p[0], p[1], p[2])); } Safe_periodic_alpha_complex_3d safe_alpha_complex(s_p_points, -1., -1., -1., 1., 1., 1.); diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_3d_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_3d_unit_test.cpp index 44deb930..8035f6e8 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_3d_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_3d_unit_test.cpp @@ -43,14 +43,14 @@ typedef boost::mpl::list w_points; - w_points.push_back(Point_3(0.0, 0.0, 0.0)); - w_points.push_back(Point_3(0.0, 0.0, 0.2)); - w_points.push_back(Point_3(0.2, 0.0, 0.2)); - // w_points.push_back(Point_3(0.6, 0.6, 0.0)); - // w_points.push_back(Point_3(0.8, 0.8, 0.2)); - // w_points.push_back(Point_3(0.2, 0.8, 0.6)); + using Bare_point_3 = typename Weighted_alpha_complex_3d::Bare_point_3; + std::vector w_points; + w_points.push_back(Bare_point_3(0.0, 0.0, 0.0)); + w_points.push_back(Bare_point_3(0.0, 0.0, 0.2)); + w_points.push_back(Bare_point_3(0.2, 0.0, 0.2)); + // w_points.push_back(Bare_point_3(0.6, 0.6, 0.0)); + // w_points.push_back(Bare_point_3(0.8, 0.8, 0.2)); + // w_points.push_back(Bare_point_3(0.2, 0.8, 0.6)); // weights size is different from w_points size to make weighted Alpha_complex_3d throw in debug mode std::vector weights = {0.01, 0.005, 0.006, 0.01, 0.009, 0.001}; @@ -62,14 +62,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted_throw, Weighted_alpha_compl BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted, Weighted_alpha_complex_3d, weighted_variants_type_list) { std::cout << "Weighted alpha complex 3d from points and weights" << std::endl; - using Point_3 = typename Weighted_alpha_complex_3d::Point_3; - std::vector w_points; - w_points.push_back(Point_3(0.0, 0.0, 0.0)); - w_points.push_back(Point_3(0.0, 0.0, 0.2)); - w_points.push_back(Point_3(0.2, 0.0, 0.2)); - w_points.push_back(Point_3(0.6, 0.6, 0.0)); - w_points.push_back(Point_3(0.8, 0.8, 0.2)); - w_points.push_back(Point_3(0.2, 0.8, 0.6)); + using Bare_point_3 = typename Weighted_alpha_complex_3d::Bare_point_3; + std::vector w_points; + w_points.push_back(Bare_point_3(0.0, 0.0, 0.0)); + w_points.push_back(Bare_point_3(0.0, 0.0, 0.2)); + w_points.push_back(Bare_point_3(0.2, 0.0, 0.2)); + w_points.push_back(Bare_point_3(0.6, 0.6, 0.0)); + w_points.push_back(Bare_point_3(0.8, 0.8, 0.2)); + w_points.push_back(Bare_point_3(0.2, 0.8, 0.6)); // weights size is different from w_points size to make weighted Alpha_complex_3d throw in debug mode std::vector weights = {0.01, 0.005, 0.006, 0.01, 0.009, 0.001}; @@ -91,6 +91,24 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted, Weighted_alpha_complex_3d, Gudhi::Simplex_tree<> stree_bis; alpha_complex_w_p.create_complex(stree_bis); + for (std::size_t index = 0; index < weighted_points.size(); index++) { + bool found = false; + Weighted_point_3 awp = alpha_complex_w_p.get_point(index); + for (auto weighted_point : weighted_points) { + if ((weighted_point.weight() == awp.weight()) && + (weighted_point.x() == awp.x()) && + (weighted_point.y() == awp.y()) && + (weighted_point.z() == awp.z())) { + found = true; + break; + } + } + // Check all points from alpha complex are found in the input point cloud + BOOST_CHECK(found); + } + // Exception if we go out of range + BOOST_CHECK_THROW(alpha_complex_w_p.get_point(weighted_points.size()), std::out_of_range); + // --------------------- // Compare both versions // --------------------- diff --git a/src/Alpha_complex/test/Weighted_periodic_alpha_complex_3d_unit_test.cpp b/src/Alpha_complex/test/Weighted_periodic_alpha_complex_3d_unit_test.cpp index 670c7799..b09e92d5 100644 --- a/src/Alpha_complex/test/Weighted_periodic_alpha_complex_3d_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_periodic_alpha_complex_3d_unit_test.cpp @@ -47,13 +47,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted_periodic_throw, Weighted_pe wp_variants_type_list) { std::cout << "Weighted periodic alpha complex 3d exception throw" << std::endl; - using Creator = CGAL::Creator_uniform_3; + using Creator = CGAL::Creator_uniform_3; CGAL::Random random(7); - CGAL::Random_points_in_cube_3 in_cube(1, random); - std::vector wp_points; + CGAL::Random_points_in_cube_3 in_cube(1, random); + std::vector wp_points; for (int i = 0; i < 50; i++) { - typename Weighted_periodic_alpha_complex_3d::Point_3 p = *in_cube++; + typename Weighted_periodic_alpha_complex_3d::Bare_point_3 p = *in_cube++; wp_points.push_back(p); } std::vector p_weights; @@ -117,13 +117,13 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_weighted_periodic) { // --------------------- std::cout << "Fast weighted periodic alpha complex 3d" << std::endl; - using Creator = CGAL::Creator_uniform_3; + using Creator = CGAL::Creator_uniform_3; CGAL::Random random(7); - CGAL::Random_points_in_cube_3 in_cube(1, random); - std::vector p_points; + CGAL::Random_points_in_cube_3 in_cube(1, random); + std::vector p_points; for (int i = 0; i < 50; i++) { - Fast_weighted_periodic_alpha_complex_3d::Point_3 p = *in_cube++; + Fast_weighted_periodic_alpha_complex_3d::Bare_point_3 p = *in_cube++; p_points.push_back(p); } std::vector p_weights; @@ -142,10 +142,10 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_weighted_periodic) { // ---------------------- std::cout << "Exact weighted periodic alpha complex 3d" << std::endl; - std::vector e_p_points; + std::vector e_p_points; for (auto p : p_points) { - e_p_points.push_back(Exact_weighted_periodic_alpha_complex_3d::Point_3(p[0], p[1], p[2])); + e_p_points.push_back(Exact_weighted_periodic_alpha_complex_3d::Bare_point_3(p[0], p[1], p[2])); } Exact_weighted_periodic_alpha_complex_3d exact_alpha_complex(e_p_points, p_weights, -1., -1., -1., 1., 1., 1.); @@ -191,10 +191,10 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_weighted_periodic) { // ---------------------- std::cout << "Safe weighted periodic alpha complex 3d" << std::endl; - std::vector s_p_points; + std::vector s_p_points; for (auto p : p_points) { - s_p_points.push_back(Safe_weighted_periodic_alpha_complex_3d::Point_3(p[0], p[1], p[2])); + s_p_points.push_back(Safe_weighted_periodic_alpha_complex_3d::Bare_point_3(p[0], p[1], p[2])); } Safe_weighted_periodic_alpha_complex_3d safe_alpha_complex(s_p_points, p_weights, -1., -1., -1., 1., 1., 1.); diff --git a/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp b/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp index 2272576e..929fc2e8 100644 --- a/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp +++ b/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp @@ -62,9 +62,9 @@ bool read_cuboid_file(const std::string &cuboid_file, double &x_min, double &y_m } template -std::vector read_off(const std::string &off_file_points) { +std::vector read_off(const std::string &off_file_points) { // Read the OFF file (input file name given as parameter) and triangulate points - Gudhi::Points_3D_off_reader off_reader(off_file_points); + Gudhi::Points_3D_off_reader off_reader(off_file_points); // Check the read operation was correct if (!off_reader.is_valid()) { std::cerr << "Unable to read OFF file " << off_file_points << std::endl; -- cgit v1.2.3 From f670d1e58ff94fd724c41ff34871b57f6ac95cc0 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 4 Nov 2019 10:51:28 +0100 Subject: Use Point_3 instead of Bare_point_3 in non-weighted cases --- src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp | 6 +++--- src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp b/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp index e84f5229..99ad94b9 100644 --- a/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp +++ b/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp @@ -71,10 +71,10 @@ void benchmark_points_on_torus_3D(const std::string& msg) { for (int nb_points = 1000; nb_points <= 125000; nb_points *= 5) { std::cout << " Alpha complex 3d on torus with " << nb_points << " points." << std::endl; std::vector points_on_torus = Gudhi::generate_points_on_torus_3D(nb_points, 1.0, 0.5); - std::vector points; + std::vector points; for (auto p : points_on_torus) { - points.push_back(typename Alpha_complex_3d::Bare_point_3(p[0], p[1], p[2])); + points.push_back(typename Alpha_complex_3d::Point_3(p[0], p[1], p[2])); } Gudhi::Clock ac_create_clock(" benchmark_points_on_torus_3D - Alpha complex 3d creation"); @@ -158,7 +158,7 @@ void benchmark_periodic_points(const std::string& msg) { for (double nb_points = 10.; nb_points <= 40.; nb_points += 10.) { std::cout << " Periodic alpha complex 3d with " << nb_points * nb_points * nb_points << " points." << std::endl; - using Point = typename Periodic_alpha_complex_3d::Bare_point_3; + using Point = typename Periodic_alpha_complex_3d::Point_3; std::vector points; for (double i = 0; i < nb_points; i++) { diff --git a/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp index 7bd35cc6..0e359a27 100644 --- a/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp @@ -8,7 +8,7 @@ #include // for numeric limits using Alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d; -using Point = Alpha_complex_3d::Bare_point_3; +using Point = Alpha_complex_3d::Point_3; using Vector_of_points = std::vector; int main(int argc, char **argv) { -- cgit v1.2.3 From c7d99937affeeac7ef1de05baa42d0392c8d5dc3 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 4 Nov 2019 14:33:50 +0100 Subject: Clarification : Points must be in Bare_point_3 or in Weighted_point_3 *means* points must be in Point_3 --- src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index c36bed1f..652a40a4 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -269,13 +269,12 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_ public: /** \brief Alpha_complex constructor from a list of points. * - * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Bare_point_3` or - * `Alpha_complex_3d::Weighted_point_3`. + * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3`. * * @pre Available if Alpha_complex_3d is not Periodic. * * The type InputPointRange must be a range for which std::begin and std::end return input iterators on a - * `Alpha_complex_3d::Bare_point_3` or a `Alpha_complex_3d::Weighted_point_3`. + * `Alpha_complex_3d::Point_3`. */ template Alpha_complex_3d(const InputPointRange& points) { @@ -323,8 +322,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_ * * @exception std::invalid_argument In debug mode, if the size of the cuboid in every directions is not the same. * - * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Bare_point_3` or - * `Alpha_complex_3d::Weighted_point_3`. + * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3`. * @param[in] x_min Iso-oriented cuboid x_min. * @param[in] y_min Iso-oriented cuboid y_min. * @param[in] z_min Iso-oriented cuboid z_min. @@ -335,7 +333,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_ * @pre Available if Alpha_complex_3d is Periodic. * * The type InputPointRange must be a range for which std::begin and std::end return input iterators on a - * `Alpha_complex_3d::Bare_point_3` or a `Alpha_complex_3d::Weighted_point_3`. + * `Alpha_complex_3d::Point_3`. * * @note In weighted version, please check weights are greater than zero, and lower than 1/64*cuboid length * squared. -- cgit v1.2.3 From b3043e49f09551187e848e0aacf88d1cf5e271e4 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 4 Nov 2019 15:09:28 +0100 Subject: Use range-for loop --- src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index 652a40a4..cb9cb926 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -580,8 +580,8 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_ const Point_3& get_point(std::size_t vertex) { if (map_cgal_simplex_tree.size() != cgal_vertex_iterator_vector.size()) { cgal_vertex_iterator_vector.resize(map_cgal_simplex_tree.size()); - for (auto map_iterator = map_cgal_simplex_tree.begin(); map_iterator != map_cgal_simplex_tree.end(); map_iterator++) { - cgal_vertex_iterator_vector[map_iterator->second] = map_iterator->first; + for (auto map_iterator : map_cgal_simplex_tree) { + cgal_vertex_iterator_vector[map_iterator.second] = map_iterator.first; } } -- cgit v1.2.3 From 73785832fd7df6a300985d1edf3a386b64e0ce19 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 4 Nov 2019 22:44:27 +0100 Subject: Epeck is now the default value. Epick and Epeck in doc. User warning on ctor if Epeck with CGAL < 5.X --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 8919cdb9..0cb4accb 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -20,7 +20,8 @@ #include // isnan, fmax #include -#include +#include // For EXACT or SAFE version +#include // For FAST version #include #include // for CGAL::Identity_property_map #include @@ -39,17 +40,20 @@ // Make compilation fail - required for external projects - https://github.com/GUDHI/gudhi-devel/issues/10 #if CGAL_VERSION_NR < 1041101000 -# error Alpha_complex_3d is only available for CGAL >= 4.11 +# error Alpha_complex is only available for CGAL >= 4.11 #endif #if !EIGEN_VERSION_AT_LEAST(3,1,0) -# error Alpha_complex_3d is only available for Eigen3 >= 3.1.0 installed with CGAL +# error Alpha_complex is only available for Eigen3 >= 3.1.0 installed with CGAL #endif namespace Gudhi { namespace alpha_complex { +template struct Is_Epick_D { static const bool value = false; }; +template struct Is_Epick_D> { static const bool value = true; }; + /** * \class Alpha_complex Alpha_complex.h gudhi/Alpha_complex.h * \brief Alpha complex data structure. @@ -63,17 +67,20 @@ namespace alpha_complex { * * Please refer to \ref alpha_complex for examples. * - * The complex is a template class requiring an Epick_d CGAL::Epeck_d, + * or an CGAL::Epick_d dD Geometry Kernel * \cite cgal:s-gkd-15b from CGAL as template, default value is CGAL::Epick_d + * href="https://doc.cgal.org/latest/Kernel_d/structCGAL_1_1Epeck__d.html">CGAL::Epeck_d * < * CGAL::Dynamic_dimension_tag > * * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. * */ -template> +template> class Alpha_complex { public: // Add an int in TDS to save point index in the structure @@ -184,6 +191,12 @@ class Alpha_complex { private: template void init_from_range(const InputPointRange& points) { + #if CGAL_VERSION_NR < 1050000000 + if (Is_Epick_D::value) + std::cerr << "It is strongly advised to use a CGAL version from 5.0 for performance reasons." + << "Your CGAL version is " << CGAL_VERSION << std::endl; + #endif + auto first = std::begin(points); auto last = std::end(points); -- cgit v1.2.3 From c9c023d407cd2f8e0d2202531d8cc64ed40fd3e5 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 5 Nov 2019 09:21:30 +0100 Subject: Do not print #define variable --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 0cb4accb..27a4ba04 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -193,8 +193,7 @@ class Alpha_complex { void init_from_range(const InputPointRange& points) { #if CGAL_VERSION_NR < 1050000000 if (Is_Epick_D::value) - std::cerr << "It is strongly advised to use a CGAL version from 5.0 for performance reasons." - << "Your CGAL version is " << CGAL_VERSION << std::endl; + std::cerr << "It is strongly advised to use a CGAL version from 5.0 for performance reasons." << std::endl; #endif auto first = std::begin(points); -- cgit v1.2.3 From 2f2027474924f3c14bc1384e3b704f27c338e09b Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 5 Nov 2019 09:30:39 +0100 Subject: Add Alpha complex tests with Epeck_d - the new default one --- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 01e4cee3..40b3fe09 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -15,6 +15,7 @@ #include #include +#include #include // float comparison #include @@ -28,12 +29,16 @@ #include // Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d; +typedef CGAL::Epeck_d< CGAL::Dynamic_dimension_tag > Exact_kernel_d; // Use static dimension_tag for the user not to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dimension_tag<3> > Kernel_s; +typedef CGAL::Epeck_d< CGAL::Dimension_tag<3> > Exact_kernel_s; +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Inexact_kernel_d; +// Use static dimension_tag for the user not to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dimension_tag<3> > Inexact_kernel_s; // The triangulation uses the default instantiation of the TriangulationDataStructure template parameter -typedef boost::mpl::list list_of_kernel_variants; +typedef boost::mpl::list list_of_kernel_variants; BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_OFF_file, TestedKernel, list_of_kernel_variants) { // ---------------------------------------------------------------------------- @@ -86,7 +91,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_OFF_file, TestedKernel, list_of } // Use static dimension_tag for the user not to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Kernel_4; +typedef CGAL::Epeck_d< CGAL::Dimension_tag<4> > Kernel_4; typedef Kernel_4::Point_d Point_4; typedef std::vector Vector_4_Points; -- cgit v1.2.3 From caa4fc8d87c2842442a3ae78bc5d7ed4124253b0 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 5 Nov 2019 15:41:09 +0100 Subject: Use Epeck_d for examples. Add an Epick_d (fast version) example and test it --- .../example/Alpha_complex_from_off.cpp | 5 +- .../example/Alpha_complex_from_points.cpp | 5 +- src/Alpha_complex/example/CMakeLists.txt | 16 +++++- .../example/Fast_alpha_complex_from_off.cpp | 65 ++++++++++++++++++++++ src/Alpha_complex/include/gudhi/Alpha_complex.h | 15 +++-- 5 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 src/Alpha_complex/example/Fast_alpha_complex_from_off.cpp (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index d411e90a..6b5f1a74 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -2,8 +2,6 @@ // to construct a simplex_tree from alpha complex #include -#include - #include #include @@ -23,8 +21,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- - using Kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alpha_complex::Alpha_complex<> alpha_complex_from_file(off_file_name); std::streambuf* streambufffer; std::ofstream ouput_file_stream; diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 981aa470..6526ca3a 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -2,12 +2,13 @@ // to construct a simplex_tree from alpha complex #include -#include +#include #include #include -using Kernel = CGAL::Epick_d< CGAL::Dimension_tag<2> >; +// Explicit dimension 2 Epeck_d kernel +using Kernel = CGAL::Epeck_d< CGAL::Dimension_tag<2> >; using Point = Kernel::Point_d; using Vector_of_points = std::vector; diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index b069b443..b0337934 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -5,9 +5,12 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) target_link_libraries(Alpha_complex_example_from_points ${CGAL_LIBRARY}) add_executable ( Alpha_complex_example_from_off Alpha_complex_from_off.cpp ) target_link_libraries(Alpha_complex_example_from_off ${CGAL_LIBRARY}) + add_executable ( Alpha_complex_example_fast_from_off Fast_alpha_complex_from_off.cpp ) + target_link_libraries(Alpha_complex_example_fast_from_off ${CGAL_LIBRARY}) if (TBB_FOUND) target_link_libraries(Alpha_complex_example_from_points ${TBB_LIBRARIES}) target_link_libraries(Alpha_complex_example_from_off ${TBB_LIBRARIES}) + target_link_libraries(Alpha_complex_example_fast_from_off ${TBB_LIBRARIES}) endif() add_test(NAME Alpha_complex_example_from_points COMMAND $) @@ -16,7 +19,13 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" "60.0" "${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt") add_test(NAME Alpha_complex_example_from_off_32 COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" "32.0" "${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt") - if (DIFF_PATH) + + add_test(NAME Alpha_complex_example_fast_from_off_60 COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" "60.0" "${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_60.txt") + add_test(NAME Alpha_complex_example_fast_from_off_32 COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" "32.0" "${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_32.txt") + +if (DIFF_PATH) # Do not forget to copy test results files in current binary dir file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) file(COPY "alphaoffreader_for_doc_60.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) @@ -25,6 +34,11 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_60.txt) add_test(Alpha_complex_example_from_off_32_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt) + + add_test(Alpha_complex_example_fast_from_off_60_diff_files ${DIFF_PATH} + ${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_60.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_60.txt) + add_test(Alpha_complex_example_fast_from_off_32_diff_files ${DIFF_PATH} + ${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt) endif() add_executable ( Alpha_complex_example_weighted_3d_from_points Weighted_alpha_complex_3d_from_points.cpp ) diff --git a/src/Alpha_complex/example/Fast_alpha_complex_from_off.cpp b/src/Alpha_complex/example/Fast_alpha_complex_from_off.cpp new file mode 100644 index 00000000..d6a39a76 --- /dev/null +++ b/src/Alpha_complex/example/Fast_alpha_complex_from_off.cpp @@ -0,0 +1,65 @@ +#include +// to construct a simplex_tree from alpha complex +#include + +#include + +#include +#include + +void usage(int nbArgs, char * const progName) { + std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n"; + std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value [ouput_file.txt]\n"; + std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0\n"; + exit(-1); // ----- >> +} + +int main(int argc, char **argv) { + if ((argc != 3) && (argc != 4)) usage(argc, (argv[0] - 1)); + + std::string off_file_name {argv[1]}; + double alpha_square_max_value {atof(argv[2])}; + + // WARNING : CGAL::Epick_d is fast but not safe (unlike CGAL::Epeck_d) + // (i.e. when the points are on a grid) + using Fast_kernel = CGAL::Epick_d; + // ---------------------------------------------------------------------------- + // Init of an alpha complex from an OFF file + // ---------------------------------------------------------------------------- + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name); + + std::streambuf* streambufffer; + std::ofstream ouput_file_stream; + + if (argc == 4) { + ouput_file_stream.open(std::string(argv[3])); + streambufffer = ouput_file_stream.rdbuf(); + } else { + streambufffer = std::cout.rdbuf(); + } + + Gudhi::Simplex_tree<> simplex; + if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) { + std::ostream output_stream(streambufffer); + + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + output_stream << "Alpha complex is of dimension " << simplex.dimension() << + " - " << simplex.num_simplices() << " simplices - " << + simplex.num_vertices() << " vertices." << std::endl; + + output_stream << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << + std::endl; + for (auto f_simplex : simplex.filtration_simplex_range()) { + output_stream << " ( "; + for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { + output_stream << vertex << " "; + } + output_stream << ") -> " << "[" << simplex.filtration(f_simplex) << "] "; + output_stream << std::endl; + } + } + ouput_file_stream.close(); + return 0; +} diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 27a4ba04..4e0e5159 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -24,7 +24,6 @@ #include // For FAST version #include #include // for CGAL::Identity_property_map -#include #include // for CGAL_VERSION_NR #include // for EIGEN_VERSION_AT_LEAST @@ -249,6 +248,8 @@ class Alpha_complex { * @param[in] complex SimplicialComplexForAlpha to be created. * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$, and there is very * little point using anything else since it does not save time. + * @param[in] exact Exact filtration values computation. Not exact if `Kernel` is not CGAL::Epeck_d. * * @return true if creation succeeds, false otherwise. * @@ -260,7 +261,8 @@ class Alpha_complex { template bool create_complex(SimplicialComplexForAlpha& complex, - Filtration_value max_alpha_square = std::numeric_limits::infinity()) { + Filtration_value max_alpha_square = std::numeric_limits::infinity(), + bool exact = false) { // From SimplicialComplexForAlpha type required to insert into a simplicial complex (with or without subfaces). typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle; typedef typename SimplicialComplexForAlpha::Simplex_handle Simplex_handle; @@ -336,9 +338,12 @@ class Alpha_complex { if (f_simplex_dim > 0) { // squared_radius function initialization Squared_Radius squared_radius = kernel_.compute_squared_radius_d_object(); - CGAL::NT_converter cv; - - alpha_complex_filtration = cv(squared_radius(pointVector.begin(), pointVector.end())); + + if (exact) { + alpha_complex_filtration = CGAL::to_double(CGAL::exact(squared_radius(pointVector.begin(), pointVector.end()))); + } else { + alpha_complex_filtration = CGAL::to_double(squared_radius(pointVector.begin(), pointVector.end())); + } } complex.assign_filtration(f_simplex, alpha_complex_filtration); #ifdef DEBUG_TRACES -- cgit v1.2.3 From f8bc102a7ec525d61e836892df6e1bfef862635f Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 5 Nov 2019 16:46:14 +0100 Subject: Modify alpha_lcomplex_persistence utility for fast, safe and exact versions. Add some tests --- src/Alpha_complex/utilities/CMakeLists.txt | 30 ++++-- .../utilities/alpha_complex_persistence.cpp | 107 +++++++++++++-------- 2 files changed, 86 insertions(+), 51 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/utilities/CMakeLists.txt b/src/Alpha_complex/utilities/CMakeLists.txt index 5295f3cd..57b92942 100644 --- a/src/Alpha_complex/utilities/CMakeLists.txt +++ b/src/Alpha_complex/utilities/CMakeLists.txt @@ -7,9 +7,19 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) if (TBB_FOUND) target_link_libraries(alpha_complex_persistence ${TBB_LIBRARIES}) endif(TBB_FOUND) - add_test(NAME Alpha_complex_utilities_alpha_complex_persistence COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45") - + add_test(NAME Alpha_complex_utilities_safe_alpha_complex_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45" "-o" "safe.pers") + add_test(NAME Alpha_complex_utilities_fast_alpha_complex_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45" "-o" "fast.pers" "-f") + add_test(NAME Alpha_complex_utilities_exact_alpha_complex_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45" "-o" "exact.pers" "-e") + if (DIFF_PATH) + add_test(Alpha_complex_utilities_diff_exact_alpha_complex ${DIFF_PATH} + "exact.pers" "safe.pers") + add_test(Alpha_complex_utilities_diff_fast_alpha_complex ${DIFF_PATH} + "fast.pers" "safe.pers") + endif() + install(TARGETS alpha_complex_persistence DESTINATION bin) add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp) @@ -20,21 +30,21 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_test(NAME Alpha_complex_utilities_alpha_complex_3d COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" - "-p" "2" "-m" "0.45" "-o" "safe.pers") + "-p" "2" "-m" "0.45" "-o" "safe_3d.pers") add_test(NAME Alpha_complex_utilities_exact_alpha_complex_3d COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" - "-p" "2" "-m" "0.45" "-o" "exact.pers" "-e") + "-p" "2" "-m" "0.45" "-o" "exact_3d.pers" "-e") add_test(NAME Alpha_complex_utilities_safe_alpha_complex_3d COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" - "-p" "2" "-m" "0.45" "-o" "fast.pers" "-f") + "-p" "2" "-m" "0.45" "-o" "fast_3d.pers" "-f") if (DIFF_PATH) - add_test(Alpha_complex_utilities_diff_alpha_complex_3d ${DIFF_PATH} - "exact.pers" "safe.pers") - add_test(Alpha_complex_utilities_diff_alpha_complex_3d ${DIFF_PATH} - "fast.pers" "safe.pers") + add_test(Alpha_complex_utilities_diff_exact_alpha_complex_3d ${DIFF_PATH} + "exact_3d.pers" "safe_3d.pers") + add_test(Alpha_complex_utilities_diff_fast_alpha_complex_3d ${DIFF_PATH} + "fast_3d.pers" "safe_3d.pers") endif() add_test(NAME Alpha_complex_utilities_periodic_alpha_complex_3d_persistence COMMAND $ diff --git a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp index fab7bd30..486347cc 100644 --- a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp +++ b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp @@ -24,63 +24,84 @@ using Simplex_tree = Gudhi::Simplex_tree<>; using Filtration_value = Simplex_tree::Filtration_value; -void program_options(int argc, char *argv[], std::string &off_file_points, std::string &output_file_diag, - Filtration_value &alpha_square_max_value, int &coeff_field_characteristic, - Filtration_value &min_persistence); +void program_options(int argc, char *argv[], std::string &off_file_points, bool &exact, bool &fast, + std::string &output_file_diag, Filtration_value &alpha_square_max_value, + int &coeff_field_characteristic, Filtration_value &min_persistence); int main(int argc, char **argv) { std::string off_file_points; std::string output_file_diag; + bool exact_version = false; + bool fast_version = false; Filtration_value alpha_square_max_value; int coeff_field_characteristic; Filtration_value min_persistence; - program_options(argc, argv, off_file_points, output_file_diag, alpha_square_max_value, coeff_field_characteristic, - min_persistence); + program_options(argc, argv, off_file_points, exact_version, fast_version, output_file_diag, alpha_square_max_value, + coeff_field_characteristic, min_persistence); - // ---------------------------------------------------------------------------- - // Init of an alpha complex from an OFF file - // ---------------------------------------------------------------------------- - using Kernel = CGAL::Epick_d; - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_points); + if ((exact_version) && (fast_version)) { + std::cerr << "You cannot set the exact and the fast version." << std::endl; + exit(-1); + } Simplex_tree simplex; - if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) { - // ---------------------------------------------------------------------------- - // Display information about the alpha complex - // ---------------------------------------------------------------------------- - std::cout << "Simplicial complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() - << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; - - // Sort the simplices in the order of the filtration - simplex.initialize_filtration(); - - std::cout << "Simplex_tree dim: " << simplex.dimension() << std::endl; - // Compute the persistence diagram of the complex - Gudhi::persistent_cohomology::Persistent_cohomology pcoh( - simplex); - // initializes the coefficient field for homology - pcoh.init_coefficients(coeff_field_characteristic); - - pcoh.compute_persistent_cohomology(min_persistence); - - // Output the diagram in filediag - if (output_file_diag.empty()) { - pcoh.output_diagram(); - } else { - std::cout << "Result in file: " << output_file_diag << std::endl; - std::ofstream out(output_file_diag); - pcoh.output_diagram(out); - out.close(); + if (fast_version) { + // WARNING : CGAL::Epick_d is fast but not safe (unlike CGAL::Epeck_d) + // (i.e. when the points are on a grid) + using Fast_kernel = CGAL::Epick_d; + + // Init of an alpha complex from an OFF file + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_points); + + if (!alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) { + std::cerr << "Fast Alpha complex simplicial complex creation failed." << std::endl; + exit(-1); } - } + } else { + using Kernel = CGAL::Epeck_d; + // Init of an alpha complex from an OFF file + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_points); + + if (!alpha_complex_from_file.create_complex(simplex, alpha_square_max_value, exact_version)) { + std::cerr << "Alpha complex simplicial complex creation failed." << std::endl; + exit(-1); + } + } + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Simplicial complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() + << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; + + // Sort the simplices in the order of the filtration + simplex.initialize_filtration(); + + std::cout << "Simplex_tree dim: " << simplex.dimension() << std::endl; + // Compute the persistence diagram of the complex + Gudhi::persistent_cohomology::Persistent_cohomology pcoh( + simplex); + // initializes the coefficient field for homology + pcoh.init_coefficients(coeff_field_characteristic); + + pcoh.compute_persistent_cohomology(min_persistence); + + // Output the diagram in filediag + if (output_file_diag.empty()) { + pcoh.output_diagram(); + } else { + std::cout << "Result in file: " << output_file_diag << std::endl; + std::ofstream out(output_file_diag); + pcoh.output_diagram(out); + out.close(); + } return 0; } -void program_options(int argc, char *argv[], std::string &off_file_points, std::string &output_file_diag, - Filtration_value &alpha_square_max_value, int &coeff_field_characteristic, - Filtration_value &min_persistence) { +void program_options(int argc, char *argv[], std::string &off_file_points, bool &exact, bool &fast, + std::string &output_file_diag, Filtration_value &alpha_square_max_value, + int &coeff_field_characteristic, Filtration_value &min_persistence) { namespace po = boost::program_options; po::options_description hidden("Hidden options"); hidden.add_options()("input-file", po::value(&off_file_points), @@ -88,6 +109,10 @@ void program_options(int argc, char *argv[], std::string &off_file_points, std:: po::options_description visible("Allowed options", 100); visible.add_options()("help,h", "produce help message")( + "exact,e", po::bool_switch(&exact), + "To activate exact version of Alpha complex (default is false, not available if fast is set)")( + "fast,f", po::bool_switch(&fast), + "To activate fast version of Alpha complex (default is false, not available if exact is set)")( "output-file,o", po::value(&output_file_diag)->default_value(std::string()), "Name of file in which the persistence diagram is written. Default print in std::cout")( "max-alpha-square-value,r", po::value(&alpha_square_max_value) -- cgit v1.2.3 From 16d84f8c33fe5bdb3b9b5ac14ed13004332a76de Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 5 Nov 2019 16:47:55 +0100 Subject: Modify alpha_complex_persistence utility documentation accordingly to code change --- src/Alpha_complex/utilities/alphacomplex.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/utilities/alphacomplex.md b/src/Alpha_complex/utilities/alphacomplex.md index fcd16a3b..527598a9 100644 --- a/src/Alpha_complex/utilities/alphacomplex.md +++ b/src/Alpha_complex/utilities/alphacomplex.md @@ -46,6 +46,8 @@ for the Alpha complex construction. coefficient field Z/pZ for computing homology. * `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals. +* `-e [ --exact ]` for the exact computation version. +* `-f [ --fast ]` for the fast computation version. **Example** -- cgit v1.2.3 From 0f6714990421d967a5e76676920ab190acc61364 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 5 Nov 2019 20:49:14 +0100 Subject: Exact version only for CGAL < 5.X --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 4e0e5159..22e17226 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -338,12 +338,18 @@ class Alpha_complex { if (f_simplex_dim > 0) { // squared_radius function initialization Squared_Radius squared_radius = kernel_.compute_squared_radius_d_object(); - + +#if CGAL_VERSION_NR < 1050000000 + // With CGAL >= 4.11 and < 5.X, CGAL::exact do not work as it is always exact values + // This is why it is slow and 5.X is advised + alpha_complex_filtration = CGAL::to_double(squared_radius(pointVector.begin(), pointVector.end())); +#else // CGAL_VERSION_NR < 1050000000 if (exact) { alpha_complex_filtration = CGAL::to_double(CGAL::exact(squared_radius(pointVector.begin(), pointVector.end()))); } else { alpha_complex_filtration = CGAL::to_double(squared_radius(pointVector.begin(), pointVector.end())); } +#endif //CGAL_VERSION_NR < 1050000000 } complex.assign_filtration(f_simplex, alpha_complex_filtration); #ifdef DEBUG_TRACES -- cgit v1.2.3 From 8732cd18079a12ab813e863839c48b7c9e504fef Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 6 Nov 2019 07:22:06 +0100 Subject: Add doc warnings --- src/Alpha_complex/doc/Intro_alpha_complex.h | 1 + src/common/doc/main_page.md | 1 + 2 files changed, 2 insertions(+) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index b075d1fc..fd6f4081 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -51,6 +51,7 @@ namespace alpha_complex { * - For people only interested in the topology of the \ref alpha_complex (for instance persistence), * \ref alpha_complex is equivalent to the \ref cech_complex and much smaller if you do not bound the radii. * \ref cech_complex can still make sense in higher dimension precisely because you can bound the radii. + * - For performances reasons, it is advised to use `Alpha_complex` with \ref cgal ≥ 5.0.0. * * \section pointsexample Example from points * diff --git a/src/common/doc/main_page.md b/src/common/doc/main_page.md index d8cbf97f..e8d11fdf 100644 --- a/src/common/doc/main_page.md +++ b/src/common/doc/main_page.md @@ -45,6 +45,7 @@ values of the codimension 1 cofaces that make it not Gabriel otherwise. All simplices that have a filtration value strictly greater than a given alpha squared value are not inserted into the complex.
+ For performances reasons, it is advised to use \ref cgal ≥ 5.0.0. Author: Vincent Rouvreau
-- cgit v1.2.3 From 4ee6ed3caa55eb8e2aec9e4bd69bb8b4561dde7e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 7 Nov 2019 16:31:16 +0100 Subject: Doc review : This remark is only available for the dD case, not for the 3d case. --- src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index cb9cb926..70e864e6 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -97,7 +97,7 @@ struct Value_from_iterator { * \details * The data structure is constructing a CGAL 3D Alpha * Shapes from a range of points (can be read from an OFF file, cf. Points_off_reader). - * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. + * Duplicate points are inserted once in the Alpha_complex. * * \tparam Complexity shall be `Gudhi::alpha_complex::complexity` type. Default value is * `Gudhi::alpha_complex::complexity::SAFE`. -- cgit v1.2.3 From 98469d9e80a881ab4dae6358b7a7e64ce90784b2 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 7 Nov 2019 16:39:36 +0100 Subject: Code review: replace streambufffer with streambuffer - was copied/ pasted from several places --- src/Alpha_complex/example/Alpha_complex_from_off.cpp | 8 ++++---- src/Alpha_complex/example/Fast_alpha_complex_from_off.cpp | 8 ++++---- .../example_rips_complex_from_csv_distance_matrix_file.cpp | 8 ++++---- src/Rips_complex/example/example_rips_complex_from_off_file.cpp | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 6b5f1a74..220a66de 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -23,19 +23,19 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- Gudhi::alpha_complex::Alpha_complex<> alpha_complex_from_file(off_file_name); - std::streambuf* streambufffer; + std::streambuf* streambuffer; std::ofstream ouput_file_stream; if (argc == 4) { ouput_file_stream.open(std::string(argv[3])); - streambufffer = ouput_file_stream.rdbuf(); + streambuffer = ouput_file_stream.rdbuf(); } else { - streambufffer = std::cout.rdbuf(); + streambuffer = std::cout.rdbuf(); } Gudhi::Simplex_tree<> simplex; if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) { - std::ostream output_stream(streambufffer); + std::ostream output_stream(streambuffer); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/example/Fast_alpha_complex_from_off.cpp b/src/Alpha_complex/example/Fast_alpha_complex_from_off.cpp index d6a39a76..f181005a 100644 --- a/src/Alpha_complex/example/Fast_alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Fast_alpha_complex_from_off.cpp @@ -28,19 +28,19 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name); - std::streambuf* streambufffer; + std::streambuf* streambuffer; std::ofstream ouput_file_stream; if (argc == 4) { ouput_file_stream.open(std::string(argv[3])); - streambufffer = ouput_file_stream.rdbuf(); + streambuffer = ouput_file_stream.rdbuf(); } else { - streambufffer = std::cout.rdbuf(); + streambuffer = std::cout.rdbuf(); } Gudhi::Simplex_tree<> simplex; if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) { - std::ostream output_stream(streambufffer); + std::ostream output_stream(streambuffer); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp b/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp index 9e182f1e..b7040453 100644 --- a/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp +++ b/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp @@ -35,19 +35,19 @@ int main(int argc, char **argv) { Distance_matrix distances = Gudhi::read_lower_triangular_matrix_from_csv_file(csv_file_name); Rips_complex rips_complex_from_file(distances, threshold); - std::streambuf* streambufffer; + std::streambuf* streambuffer; std::ofstream ouput_file_stream; if (argc == 5) { ouput_file_stream.open(std::string(argv[4])); - streambufffer = ouput_file_stream.rdbuf(); + streambuffer = ouput_file_stream.rdbuf(); } else { - streambufffer = std::cout.rdbuf(); + streambuffer = std::cout.rdbuf(); } Simplex_tree stree; rips_complex_from_file.create_complex(stree, dim_max); - std::ostream output_stream(streambufffer); + std::ostream output_stream(streambuffer); // ---------------------------------------------------------------------------- // Display information about the Rips complex diff --git a/src/Rips_complex/example/example_rips_complex_from_off_file.cpp b/src/Rips_complex/example/example_rips_complex_from_off_file.cpp index de2e4ea4..36b468a7 100644 --- a/src/Rips_complex/example/example_rips_complex_from_off_file.cpp +++ b/src/Rips_complex/example/example_rips_complex_from_off_file.cpp @@ -34,19 +34,19 @@ int main(int argc, char **argv) { Gudhi::Points_off_reader off_reader(off_file_name); Rips_complex rips_complex_from_file(off_reader.get_point_cloud(), threshold, Gudhi::Euclidean_distance()); - std::streambuf* streambufffer; + std::streambuf* streambuffer; std::ofstream ouput_file_stream; if (argc == 5) { ouput_file_stream.open(std::string(argv[4])); - streambufffer = ouput_file_stream.rdbuf(); + streambuffer = ouput_file_stream.rdbuf(); } else { - streambufffer = std::cout.rdbuf(); + streambuffer = std::cout.rdbuf(); } Simplex_tree stree; rips_complex_from_file.create_complex(stree, dim_max); - std::ostream output_stream(streambufffer); + std::ostream output_stream(streambuffer); // ---------------------------------------------------------------------------- // Display information about the Rips complex -- cgit v1.2.3 From ea296b4a93c37b0e19d4605c1be3e950ed8cd3c2 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 7 Nov 2019 16:45:28 +0100 Subject: Code review: it is with Epeck_d that it is advised to have CGAL >= 5.0. Error message clarification --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 22e17226..9aa30383 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -50,8 +50,8 @@ namespace Gudhi { namespace alpha_complex { -template struct Is_Epick_D { static const bool value = false; }; -template struct Is_Epick_D> { static const bool value = true; }; +template struct Is_Epeck_D { static const bool value = false; }; +template struct Is_Epeck_D> { static const bool value = true; }; /** * \class Alpha_complex Alpha_complex.h gudhi/Alpha_complex.h @@ -191,8 +191,9 @@ class Alpha_complex { template void init_from_range(const InputPointRange& points) { #if CGAL_VERSION_NR < 1050000000 - if (Is_Epick_D::value) - std::cerr << "It is strongly advised to use a CGAL version from 5.0 for performance reasons." << std::endl; + if (Is_Epeck_D::value) + std::cerr << "It is strongly advised to use a CGAL version >= 5.0 with Epeck_d Kernel for performance reasons." + << std::endl; #endif auto first = std::begin(points); -- cgit v1.2.3 From 5a2c3559da581136edb7facf5578bd1443080ef3 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 7 Nov 2019 17:02:38 +0100 Subject: Code review: Add suggested code using NT_converter to simplify the different alpha_complex_filtration computations cases --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 9aa30383..b3d1e6ea 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -25,6 +25,7 @@ #include #include // for CGAL::Identity_property_map #include // for CGAL_VERSION_NR +#include #include // for EIGEN_VERSION_AT_LEAST @@ -340,17 +341,12 @@ class Alpha_complex { // squared_radius function initialization Squared_Radius squared_radius = kernel_.compute_squared_radius_d_object(); -#if CGAL_VERSION_NR < 1050000000 - // With CGAL >= 4.11 and < 5.X, CGAL::exact do not work as it is always exact values - // This is why it is slow and 5.X is advised - alpha_complex_filtration = CGAL::to_double(squared_radius(pointVector.begin(), pointVector.end())); -#else // CGAL_VERSION_NR < 1050000000 - if (exact) { - alpha_complex_filtration = CGAL::to_double(CGAL::exact(squared_radius(pointVector.begin(), pointVector.end()))); - } else { - alpha_complex_filtration = CGAL::to_double(squared_radius(pointVector.begin(), pointVector.end())); - } -#endif //CGAL_VERSION_NR < 1050000000 + CGAL::NT_converter cv; + auto sqrad = squared_radius(pointVector.begin(), pointVector.end()); +#if CGAL_VERSION_NR >= 1050000000 + if(exact) CGAL::exact(sqrad); +#endif + alpha_complex_filtration = cv(sqrad); } complex.assign_filtration(f_simplex, alpha_complex_filtration); #ifdef DEBUG_TRACES -- cgit v1.2.3 From 6d2e5d1cbdecd86ad4d56fc8902542caca2cf2bd Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 15 Nov 2019 23:33:49 +0100 Subject: Code review: Point_3 is an Alpha_shape_3::Point instead of std::conditionnal(...) --- src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index 70e864e6..7f96c94c 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -252,7 +252,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_ /** \brief `Alpha_complex_3d::Point_3` type is either a `Alpha_complex_3d::Bare_point_3` (Weighted = false) or a * `Alpha_complex_3d::Weighted_point_3` (Weighted = true). */ - using Point_3 = typename std::conditional::type; + using Point_3 = typename Alpha_shape_3::Point; private: using Dispatch = -- cgit v1.2.3 From 669039c52bb3e71ad24f95e8a7cf1b2be69a5548 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Sat, 16 Nov 2019 23:46:34 +0100 Subject: Doc review: Add the starting point of the documentation --- src/Alpha_complex/doc/Intro_alpha_complex.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index fd6f4081..adc1378f 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -51,6 +51,16 @@ namespace alpha_complex { * - For people only interested in the topology of the \ref alpha_complex (for instance persistence), * \ref alpha_complex is equivalent to the \ref cech_complex and much smaller if you do not bound the radii. * \ref cech_complex can still make sense in higher dimension precisely because you can bound the radii. + * - Using the default `CGAL::Epeck_d` makes the construction safe. If you pass exact=true to create_complex, the + * filtration values are the exact ones converted to the filtration value type of the simplicial complex. This can be + * very slow. If you pass exact=false (the default), the filtration values are only guaranteed to have a small + * multiplicative error compared to the exact value, see + * CGAL::Lazy_exact_nt::set_relative_precision_of_to_double for details. A drawback, when computing + * persistence, is that an empty exact interval [10^12,10^12] may become a non-empty approximate interval + * [10^12,10^12+10^6]. Using `CGAL::Epick_d` makes the computations slightly faster, and the combinatorics are still + * exact, but the computation of filtration values can exceptionally be arbitrarily bad. In all cases, we still + * guarantee that the output is a valid filtration (faces have a filtration value no larger than their cofaces). * - For performances reasons, it is advised to use `Alpha_complex` with \ref cgal ≥ 5.0.0. * * \section pointsexample Example from points -- cgit v1.2.3 From c8be137d15f40f40c4150f0c0fb9776cd680a36c Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 19 Nov 2019 07:33:46 +0100 Subject: Doc review: Add the starting point of the documentation in the Alpha complex reference --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/Alpha_complex') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index b3d1e6ea..0c2569c8 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -77,8 +77,19 @@ template struct Is_Epeck_D> { static const bool val * < * CGAL::Dynamic_dimension_tag > * - * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. - * + * \remark + * - When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. + * - Using the default `CGAL::Epeck_d` makes the construction safe. If you pass exact=true to create_complex, the + * filtration values are the exact ones converted to the filtration value type of the simplicial complex. This can be + * very slow. If you pass exact=false (the default), the filtration values are only guaranteed to have a small + * multiplicative error compared to the exact value, see + * CGAL::Lazy_exact_nt::set_relative_precision_of_to_double for details. A drawback, when computing + * persistence, is that an empty exact interval [10^12,10^12] may become a non-empty approximate interval + * [10^12,10^12+10^6]. Using `CGAL::Epick_d` makes the computations slightly faster, and the combinatorics are still + * exact, but the computation of filtration values can exceptionally be arbitrarily bad. In all cases, we still + * guarantee that the output is a valid filtration (faces have a filtration value no larger than their cofaces). + * - For performances reasons, it is advised to use `Alpha_complex` with \ref cgal ≥ 5.0.0. */ template> class Alpha_complex { -- cgit v1.2.3