diff options
Diffstat (limited to 'src/Alpha_complex')
10 files changed, 764 insertions, 642 deletions
diff --git a/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp b/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp index 1a33f2b4..005a712a 100644 --- a/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp +++ b/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp @@ -25,7 +25,7 @@ void benchmark_points_on_torus_dD(const std::string& msg) { results_csv << "\"nb_points\";" << "\"nb_simplices\";" << "\"alpha_creation_time(sec.)\";" - << "\"simplex_creation_time(sec.)\";" << std::endl; + << "\"complex_creation_time(sec.)\";" << std::endl; using K = CGAL::Epick_d<CGAL::Dimension_tag<3>>; for (int nb_points = 1000; nb_points <= 125000; nb_points *= 5) { @@ -43,17 +43,17 @@ void benchmark_points_on_torus_dD(const std::string& msg) { ac_create_clock.end(); std::cout << ac_create_clock; - Gudhi::Simplex_tree<> simplex; - Gudhi::Clock st_create_clock(" benchmark_points_on_torus_dD - simplex tree creation"); + Gudhi::Simplex_tree<> complex; + Gudhi::Clock st_create_clock(" benchmark_points_on_torus_dD - complex creation"); st_create_clock.begin(); - alpha_complex_from_points.create_complex(simplex); + alpha_complex_from_points.create_complex(complex); st_create_clock.end(); std::cout << st_create_clock; - results_csv << nb_points << ";" << simplex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";" + results_csv << nb_points << ";" << complex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";" << st_create_clock.num_seconds() << ";" << std::endl; - std::cout << " benchmark_points_on_torus_dD - nb simplices = " << simplex.num_simplices() << std::endl; + std::cout << " benchmark_points_on_torus_dD - nb simplices = " << complex.num_simplices() << std::endl; } } @@ -66,7 +66,7 @@ void benchmark_points_on_torus_3D(const std::string& msg) { results_csv << "\"nb_points\";" << "\"nb_simplices\";" << "\"alpha_creation_time(sec.)\";" - << "\"simplex_creation_time(sec.)\";" << std::endl; + << "\"complex_creation_time(sec.)\";" << std::endl; for (int nb_points = 1000; nb_points <= 125000; nb_points *= 5) { std::cout << " Alpha complex 3d on torus with " << nb_points << " points." << std::endl; @@ -83,17 +83,17 @@ void benchmark_points_on_torus_3D(const std::string& msg) { ac_create_clock.end(); std::cout << ac_create_clock; - Gudhi::Simplex_tree<> simplex; - Gudhi::Clock st_create_clock(" benchmark_points_on_torus_3D - simplex tree creation"); + Gudhi::Simplex_tree<> complex; + Gudhi::Clock st_create_clock(" benchmark_points_on_torus_3D - complex creation"); st_create_clock.begin(); - alpha_complex_from_points.create_complex(simplex); + alpha_complex_from_points.create_complex(complex); st_create_clock.end(); std::cout << st_create_clock; - results_csv << nb_points << ";" << simplex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";" + results_csv << nb_points << ";" << complex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";" << st_create_clock.num_seconds() << ";" << std::endl; - std::cout << " benchmark_points_on_torus_3D - nb simplices = " << simplex.num_simplices() << std::endl; + std::cout << " benchmark_points_on_torus_3D - nb simplices = " << complex.num_simplices() << std::endl; } } @@ -107,7 +107,7 @@ void benchmark_weighted_points_on_torus_3D(const std::string& msg) { results_csv << "\"nb_points\";" << "\"nb_simplices\";" << "\"alpha_creation_time(sec.)\";" - << "\"simplex_creation_time(sec.)\";" << std::endl; + << "\"complex_creation_time(sec.)\";" << std::endl; CGAL::Random random(8); @@ -116,7 +116,7 @@ void benchmark_weighted_points_on_torus_3D(const std::string& msg) { std::vector<K::Point_d> points_on_torus = Gudhi::generate_points_on_torus_3D<K>(nb_points, 1.0, 0.5); using Point = typename Weighted_alpha_complex_3d::Point_3; - using Weighted_point = typename Weighted_alpha_complex_3d::Triangulation_3::Weighted_point; + using Weighted_point = typename Weighted_alpha_complex_3d::Weighted_point_3; std::vector<Weighted_point> points; @@ -130,17 +130,17 @@ void benchmark_weighted_points_on_torus_3D(const std::string& msg) { ac_create_clock.end(); std::cout << ac_create_clock; - Gudhi::Simplex_tree<> simplex; - Gudhi::Clock st_create_clock(" benchmark_weighted_points_on_torus_3D - simplex tree creation"); + Gudhi::Simplex_tree<> complex; + Gudhi::Clock st_create_clock(" benchmark_weighted_points_on_torus_3D - complex creation"); st_create_clock.begin(); - alpha_complex_from_points.create_complex(simplex); + alpha_complex_from_points.create_complex(complex); st_create_clock.end(); std::cout << st_create_clock; - results_csv << nb_points << ";" << simplex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";" + results_csv << nb_points << ";" << complex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";" << st_create_clock.num_seconds() << ";" << std::endl; - std::cout << " benchmark_weighted_points_on_torus_3D - nb simplices = " << simplex.num_simplices() << std::endl; + std::cout << " benchmark_weighted_points_on_torus_3D - nb simplices = " << complex.num_simplices() << std::endl; } } @@ -152,7 +152,7 @@ void benchmark_periodic_points(const std::string& msg) { results_csv << "\"nb_points\";" << "\"nb_simplices\";" << "\"alpha_creation_time(sec.)\";" - << "\"simplex_creation_time(sec.)\";" << std::endl; + << "\"complex_creation_time(sec.)\";" << std::endl; CGAL::Random random(8); @@ -176,17 +176,17 @@ void benchmark_periodic_points(const std::string& msg) { ac_create_clock.end(); std::cout << ac_create_clock; - Gudhi::Simplex_tree<> simplex; - Gudhi::Clock st_create_clock(" benchmark_periodic_points - simplex tree creation"); + Gudhi::Simplex_tree<> complex; + Gudhi::Clock st_create_clock(" benchmark_periodic_points - complex creation"); st_create_clock.begin(); - alpha_complex_from_points.create_complex(simplex); + alpha_complex_from_points.create_complex(complex); st_create_clock.end(); std::cout << st_create_clock; - results_csv << nb_points * nb_points * nb_points << ";" << simplex.num_simplices() << ";" + results_csv << nb_points * nb_points * nb_points << ";" << complex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";" << st_create_clock.num_seconds() << ";" << std::endl; - std::cout << " benchmark_periodic_points - nb simplices = " << simplex.num_simplices() << std::endl; + std::cout << " benchmark_periodic_points - nb simplices = " << complex.num_simplices() << std::endl; } } @@ -198,7 +198,7 @@ void benchmark_weighted_periodic_points(const std::string& msg) { results_csv << "\"nb_points\";" << "\"nb_simplices\";" << "\"alpha_creation_time(sec.)\";" - << "\"simplex_creation_time(sec.)\";" << std::endl; + << "\"complex_creation_time(sec.)\";" << std::endl; CGAL::Random random(8); @@ -207,7 +207,7 @@ void benchmark_weighted_periodic_points(const std::string& msg) { << std::endl; using Point = typename Weighted_periodic_alpha_complex_3d::Point_3; - using Weighted_point = typename Weighted_periodic_alpha_complex_3d::Triangulation_3::Weighted_point; + using Weighted_point = typename Weighted_periodic_alpha_complex_3d::Weighted_point_3; std::vector<Weighted_point> points; for (double i = 0; i < nb_points; i++) { @@ -226,17 +226,17 @@ void benchmark_weighted_periodic_points(const std::string& msg) { ac_create_clock.end(); std::cout << ac_create_clock; - Gudhi::Simplex_tree<> simplex; - Gudhi::Clock st_create_clock(" benchmark_weighted_periodic_points - simplex tree creation"); + Gudhi::Simplex_tree<> complex; + Gudhi::Clock st_create_clock(" benchmark_weighted_periodic_points - complex creation"); st_create_clock.begin(); - alpha_complex_from_points.create_complex(simplex); + alpha_complex_from_points.create_complex(complex); st_create_clock.end(); std::cout << st_create_clock; - results_csv << nb_points * nb_points * nb_points << ";" << simplex.num_simplices() << ";" + results_csv << nb_points * nb_points * nb_points << ";" << complex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";" << st_create_clock.num_seconds() << ";" << std::endl; - std::cout << " benchmark_weighted_periodic_points - nb simplices = " << simplex.num_simplices() << std::endl; + std::cout << " benchmark_weighted_periodic_points - nb simplices = " << complex.num_simplices() << std::endl; } } diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 2fe9f4ca..ab7c4794 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -168,8 +168,10 @@ namespace alpha_complex { * * \section weighted3dexample 3d specific example * - * A specific module for Alpha complex is available in 3d (cf. Alpha_complex_3d) and allows to construct default, exact, - * weighted, periodic or weighted and periodic versions of alpha complexes + * A specific module for Alpha complex is available in 3d (cf. Alpha_complex_3d) and allows to construct standard, + * weighted, periodic or weighted and periodic versions of alpha complexes. Alpha values computation can be + * Gudhi::alpha_complex::complexity::FAST, Gudhi::alpha_complex::complexity::SAFE (default value) or + * Gudhi::alpha_complex::complexity::EXACT. * * This example builds the CGAL 3d weighted alpha shapes from a small molecule, and initializes the alpha complex with * it. This example is taken from <a href="https://doc.cgal.org/latest/Alpha_shapes_3/index.html#title13">CGAL 3d 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 3acebd2e..0e359a27 100644 --- a/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp @@ -7,7 +7,7 @@ #include <vector> #include <limits> // for numeric limits -using Alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, false>; +using Alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, false>; using Point = Alpha_complex_3d::Point_3; using Vector_of_points = std::vector<Point>; 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 68f72f0a..ac11b68c 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 @@ -7,24 +7,17 @@ #include <vector> #include <limits> // for numeric limits +// Complexity = FAST, weighted = true, periodic = false using Weighted_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, false>; + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, false>; using Point = Weighted_alpha_complex_3d::Point_3; -using Weighted_point = Weighted_alpha_complex_3d::Triangulation_3::Weighted_point; -using Vector_of_weighted_points = std::vector<Weighted_point>; -using Vector_of_weights = std::vector<Weighted_alpha_complex_3d::Alpha_shape_3::FT>; +using Weighted_point = Weighted_alpha_complex_3d::Weighted_point_3; int main(int argc, char **argv) { - if (argc != 1) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; - std::cerr << "Usage: " << (argv[0] - 1) << " \n"; - exit(-1); // ----- >> - } - // ---------------------------------------------------------------------------- // Init of a list of points and weights from a small molecule // ---------------------------------------------------------------------------- - Vector_of_weighted_points weighted_points; + std::vector<Weighted_point> 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.)); diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index 00a47d5c..19445637 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -26,10 +26,6 @@ #include <boost/version.hpp> #include <boost/variant.hpp> -#if BOOST_VERSION >= 105400 -#include <boost/container/static_vector.hpp> -#endif - #include <gudhi/Debug_utils.h> #include <gudhi/Alpha_complex_options.h> @@ -50,6 +46,8 @@ #include <CGAL/iterator.h> #include <CGAL/version.h> +#include <boost/container/static_vector.hpp> + #include <iostream> #include <vector> #include <unordered_map> @@ -60,7 +58,7 @@ #if CGAL_VERSION_NR < 1041101000 // Make compilation fail - required for external projects - https://gitlab.inria.fr/GUDHI/gudhi-devel/issues/10 -static_assert(false, "Alpha_complex_3d is only available for CGAL >= 4.11"); +# error Alpha_complex_3d is only available for CGAL >= 4.11 #endif namespace Gudhi { @@ -74,62 +72,22 @@ thread_local // Value_from_iterator returns the filtration value from an iterator on alpha shapes values // -// FAST SAFE EXACT -// not weighted and *iterator Specific case due to CGAL CGAL::to_double(iterator->exact()) -// not periodic issue # 3153 -// -// otherwise *iterator CGAL::to_double(*iterator) CGAL::to_double(iterator->exact()) +// FAST SAFE EXACT +// CGAL::to_double(*iterator) CGAL::to_double(*iterator) CGAL::to_double(iterator->exact()) -template <complexity Complexity, bool Weighted_or_periodic> +template <complexity Complexity> struct Value_from_iterator { template <typename Iterator> static double perform(Iterator it) { - // Default behaviour is to return the value pointed by the given iterator - return *it; - } -}; - -template <> -struct Value_from_iterator<complexity::SAFE, true> { - template <typename Iterator> - static double perform(Iterator it) { - // In SAFE mode, we are with Epick with EXACT value set to CGAL::Tag_true. + // Default behaviour return CGAL::to_double(*it); } }; template <> -struct Value_from_iterator<complexity::SAFE, false> { +struct Value_from_iterator<complexity::EXACT> { template <typename Iterator> static double perform(Iterator it) { - // In SAFE mode, we are with Epeck with EXACT value set to CGAL::Tag_true. - // Specific case due to CGAL issue https://github.com/CGAL/cgal/issues/3153 - auto approx = it->approx(); - double r; - if (CGAL::fit_in_double(approx, r)) return r; - - // If it's precise enough, then OK. - if (CGAL::has_smaller_relative_precision(approx, RELATIVE_PRECISION_OF_TO_DOUBLE)) return CGAL::to_double(approx); - - it->exact(); - return CGAL::to_double(it->approx()); - } -}; - -template <> -struct Value_from_iterator<complexity::EXACT, true> { - template <typename Iterator> - static double perform(Iterator it) { - // In EXACT mode, we are with Epeck or Epick with EXACT value set to CGAL::Tag_true. - return CGAL::to_double(it->exact()); - } -}; - -template <> -struct Value_from_iterator<complexity::EXACT, false> { - template <typename Iterator> - static double perform(Iterator it) { - // In EXACT mode, we are with Epeck or Epick with EXACT value set to CGAL::Tag_true. return CGAL::to_double(it->exact()); } }; @@ -145,8 +103,8 @@ struct Value_from_iterator<complexity::EXACT, false> { * Shapes</a> 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. * - * \tparam Complexity shall be `Gudhi::alpha_complex::complexity`. Default value is - * `Gudhi::alpha_complex::complexity::FAST`. + * \tparam Complexity shall be `Gudhi::alpha_complex::complexity` type. Default value is + * `Gudhi::alpha_complex::complexity::SAFE`. * * \tparam Weighted Boolean used to set/unset the weighted version of Alpha_complex_3d. Default value is false. * @@ -169,22 +127,22 @@ struct Value_from_iterator<complexity::EXACT, false> { * 3d Delaunay complex. * */ -template <complexity Complexity = complexity::FAST, bool Weighted = false, bool Periodic = false> +template <complexity Complexity = complexity::SAFE, bool Weighted = false, bool Periodic = false> class Alpha_complex_3d { // Epick = Exact_predicates_inexact_constructions_kernel // Epeck = Exact_predicates_exact_constructions_kernel - // ExactAlphaComparisonTag = exact version of CGAL Alpha_shape_3 and of its objects (Alpha_shape_vertex_base_3 and + // Exact_alpha_comparison_tag = exact version of CGAL Alpha_shape_3 and of its objects (Alpha_shape_vertex_base_3 and // Alpha_shape_cell_base_3). Not available if weighted or periodic. - // Can be CGAL::Tag_false or CGAL::Tag_true + // Can be CGAL::Tag_false or CGAL::Tag_true. Default is False. // cf. https://doc.cgal.org/latest/Alpha_shapes_3/classCGAL_1_1Alpha__shape__3.html // + // We could use Epick + CGAL::Tag_true for not weighted nor periodic, but during benchmark, we found a bug + // https://github.com/CGAL/cgal/issues/3460 + // This is the reason we only use Epick + CGAL::Tag_false, or Epeck // - // FAST SAFE EXACT - // not weighted and Epick + CGAL::Tag_false Epick + CGAL::Tag_true Epick + CGAL::Tag_true - // not periodic - // - // otherwise Epick + CGAL::Tag_false Epeck Epeck - using Predicates = typename std::conditional<((!Weighted && !Periodic) || (Complexity == complexity::FAST)), + // FAST SAFE EXACT + // Epick + CGAL::Tag_false Epeck Epeck + using Predicates = typename std::conditional<(Complexity == complexity::FAST), CGAL::Exact_predicates_inexact_constructions_kernel, CGAL::Exact_predicates_exact_constructions_kernel>::type; @@ -192,14 +150,11 @@ class Alpha_complex_3d { template <typename Predicates, bool Weighted_version, bool Periodic_version> struct Kernel_3 {}; - template <typename Predicates> - struct Kernel_3<Predicates, false, false> { - using Kernel = Predicates; - }; - template <typename Predicates> - struct Kernel_3<Predicates, true, false> { + template <typename Predicates, bool Is_periodic> + struct Kernel_3<Predicates, Is_periodic, false> { using Kernel = Predicates; }; + template <typename Predicates> struct Kernel_3<Predicates, false, true> { using Kernel = CGAL::Periodic_3_Delaunay_triangulation_traits_3<Predicates>; @@ -211,15 +166,13 @@ class Alpha_complex_3d { using Kernel = typename Kernel_3<Predicates, Weighted, Periodic>::Kernel; - using Exact_tag = typename std::conditional<(Complexity == complexity::FAST), CGAL::Tag_false, CGAL::Tag_true>::type; - using TdsVb = typename std::conditional<Periodic, CGAL::Periodic_3_triangulation_ds_vertex_base_3<>, CGAL::Triangulation_ds_vertex_base_3<>>::type; using Tvb = typename std::conditional<Weighted, CGAL::Regular_triangulation_vertex_base_3<Kernel, TdsVb>, CGAL::Triangulation_vertex_base_3<Kernel, TdsVb>>::type; - using Vb = CGAL::Alpha_shape_vertex_base_3<Kernel, Tvb, Exact_tag>; + using Vb = CGAL::Alpha_shape_vertex_base_3<Kernel, Tvb>; using TdsCb = typename std::conditional<Periodic, CGAL::Periodic_3_triangulation_ds_cell_base_3<>, CGAL::Triangulation_ds_cell_base_3<>>::type; @@ -227,64 +180,101 @@ class Alpha_complex_3d { using Tcb = typename std::conditional<Weighted, CGAL::Regular_triangulation_cell_base_3<Kernel, TdsCb>, CGAL::Triangulation_cell_base_3<Kernel, TdsCb>>::type; - using Cb = CGAL::Alpha_shape_cell_base_3<Kernel, Tcb, Exact_tag>; + using Cb = CGAL::Alpha_shape_cell_base_3<Kernel, Tcb>; using Tds = CGAL::Triangulation_data_structure_3<Vb, Cb>; // The other way to do a conditional type. Here there 4 possibilities, cannot use std::conditional template <typename Kernel, typename Tds, bool Weighted_version, bool Periodic_version> - struct Triangulation {}; + struct Triangulation_3 {}; template <typename Kernel, typename Tds> - struct Triangulation<Kernel, Tds, false, false> { - using Triangulation_3 = CGAL::Delaunay_triangulation_3<Kernel, Tds>; + struct Triangulation_3<Kernel, Tds, false, false> { + using Dt = CGAL::Delaunay_triangulation_3<Kernel, Tds>; + using Weighted_point_3 = void; }; template <typename Kernel, typename Tds> - struct Triangulation<Kernel, Tds, true, false> { - using Triangulation_3 = CGAL::Regular_triangulation_3<Kernel, Tds>; + struct Triangulation_3<Kernel, Tds, true, false> { + using Dt = CGAL::Regular_triangulation_3<Kernel, Tds>; + using Weighted_point_3 = typename Dt::Weighted_point; }; template <typename Kernel, typename Tds> - struct Triangulation<Kernel, Tds, false, true> { - using Triangulation_3 = CGAL::Periodic_3_Delaunay_triangulation_3<Kernel, Tds>; + struct Triangulation_3<Kernel, Tds, false, true> { + using Dt = CGAL::Periodic_3_Delaunay_triangulation_3<Kernel, Tds>; + using Weighted_point_3 = void; }; template <typename Kernel, typename Tds> - struct Triangulation<Kernel, Tds, true, true> { - using Triangulation_3 = CGAL::Periodic_3_regular_triangulation_3<Kernel, Tds>; + struct Triangulation_3<Kernel, Tds, true, true> { + using Dt = CGAL::Periodic_3_regular_triangulation_3<Kernel, Tds>; + using Weighted_point_3 = typename Dt::Weighted_point; }; - public: - using Triangulation_3 = typename Triangulation<Kernel, Tds, Weighted, Periodic>::Triangulation_3; - - using Alpha_shape_3 = CGAL::Alpha_shape_3<Triangulation_3, Exact_tag>; + /** \brief Is either Delaunay_triangulation_3 (Weighted = false and Periodic = false), + * Regular_triangulation_3 (Weighted = true and Periodic = false), + * Periodic_3_Delaunay_triangulation_3 (Weighted = false and Periodic = true) + * or Periodic_3_regular_triangulation_3 (Weighted = true and Periodic = true). + * + * This type is required by `Gudhi::alpha_complex::Alpha_complex_3d::Alpha_shape_3`. + * */ + using Dt = typename Triangulation_3<Kernel, Tds, Weighted, Periodic>::Dt; +public: + /** \brief The <a href="https://doc.cgal.org/latest/Alpha_shapes_3/classCGAL_1_1Alpha__shape__3.html">CGAL 3D Alpha + * Shapes</a> type. + * + * The `Gudhi::alpha_complex::Alpha_complex_3d` is a wrapper on top of this class to ease the standard, weighted + * and/or periodic build of the Alpha complex 3d.*/ + using Alpha_shape_3 = CGAL::Alpha_shape_3<Dt>; + + /** \brief The alpha values type. + * 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: +\code{.cpp} +using Alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, false>; + +// x0 = 1., y0 = -1.1, z0 = -1.. +Alpha_complex_3d::Point_3 p0(1., -1.1, -1.); +\endcode + * */ using Point_3 = typename Kernel::Point_3; - private: - using Alpha_value_type = typename Alpha_shape_3::FT; + /** \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<Gudhi::alpha_complex::complexity::SAFE, true, false>; + +// 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.); +\endcode + * + * Note: This type is defined to void if Alpha complex is not weighted. + * + * */ + using Weighted_point_3 = typename Triangulation_3<Kernel, Tds, Weighted, Periodic>::Weighted_point_3; + +private: using Dispatch = - CGAL::Dispatch_output_iterator<CGAL::cpp11::tuple<CGAL::Object, Alpha_value_type>, + CGAL::Dispatch_output_iterator<CGAL::cpp11::tuple<CGAL::Object, FT>, CGAL::cpp11::tuple<std::back_insert_iterator<std::vector<CGAL::Object>>, - std::back_insert_iterator<std::vector<Alpha_value_type>>>>; + std::back_insert_iterator<std::vector<FT>>>>; using Cell_handle = typename Alpha_shape_3::Cell_handle; using Facet = typename Alpha_shape_3::Facet; using Edge = typename Alpha_shape_3::Edge; using Alpha_vertex_handle = typename Alpha_shape_3::Vertex_handle; -#if BOOST_VERSION >= 105400 using Vertex_list = boost::container::static_vector<Alpha_vertex_handle, 4>; -#else - using Vertex_list = std::vector<Alpha_vertex_handle>; -#endif 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 - * `Alpha_complex_3d::Triangulation_3::Weighted_point`. + * `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::Triangulation_3::Weighted_point`. + * `Alpha_complex_3d::Point_3` or a `Alpha_complex_3d::Weighted_point_3`. */ template <typename InputPointRange> Alpha_complex_3d(const InputPointRange& points) { @@ -298,15 +288,15 @@ class Alpha_complex_3d { * * @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] weights Range of weights on points. Weights shall be in `Alpha_complex_3d::Alpha_shape_3::FT` + * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::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`. * The type WeightRange must be a range for which std::begin and - * std::end return an input iterator on a `Alpha_complex_3d::Alpha_shape_3::FT`. + * std::end return an input iterator on a double. */ template <typename InputPointRange, typename WeightRange> Alpha_complex_3d(const InputPointRange& points, WeightRange weights) { @@ -315,7 +305,6 @@ class Alpha_complex_3d { GUDHI_CHECK((weights.size() == points.size()), std::invalid_argument("Points number in range different from weights range number")); - using Weighted_point_3 = typename Triangulation_3::Weighted_point; std::vector<Weighted_point_3> weighted_points_3; std::size_t index = 0; @@ -334,7 +323,7 @@ class Alpha_complex_3d { * @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 - * `Alpha_complex_3d::Triangulation_3::Weighted_point`. + * `Alpha_complex_3d::Weighted_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. @@ -345,14 +334,14 @@ class Alpha_complex_3d { * @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::Triangulation_3::Weighted_point`. + * `Alpha_complex_3d::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. */ template <typename InputPointRange> - Alpha_complex_3d(const InputPointRange& points, Alpha_value_type x_min, Alpha_value_type y_min, - Alpha_value_type z_min, Alpha_value_type x_max, Alpha_value_type y_max, Alpha_value_type z_max) { + Alpha_complex_3d(const InputPointRange& points, FT x_min, FT y_min, + FT z_min, FT x_max, FT y_max, FT z_max) { static_assert(Periodic, "This constructor is not available for non-periodic versions of Alpha_complex_3d"); // Checking if the cuboid is the same in x,y and z direction. If not, CGAL will not process it. GUDHI_CHECK( @@ -360,7 +349,7 @@ class Alpha_complex_3d { std::invalid_argument("The size of the cuboid in every directions is not the same.")); // Define the periodic cube - Triangulation_3 pdt(typename Kernel::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max)); + Dt pdt(typename Kernel::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max)); // Heuristic for inserting large point sets (if pts is reasonably large) pdt.insert(std::begin(points), std::end(points), true); // As pdt won't be modified anymore switch to 1-sheeted cover if possible @@ -381,8 +370,8 @@ class Alpha_complex_3d { * @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] weights Range of weights on points. Weights shall be in `Alpha_complex_3d::Alpha_shape_3::FT` + * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::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. * @param[in] z_min Iso-oriented cuboid z_min. @@ -395,12 +384,12 @@ class Alpha_complex_3d { * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a `Alpha_complex_3d::Point_3`. * The type WeightRange must be a range for which std::begin and - * std::end return an input iterator on a `Alpha_complex_3d::Alpha_shape_3::FT`. - * The type of x_min, y_min, z_min, x_max, y_max and z_max is `Alpha_complex_3d::Alpha_shape_3::FT`. + * 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. */ template <typename InputPointRange, typename WeightRange> - Alpha_complex_3d(const InputPointRange& points, WeightRange weights, Alpha_value_type x_min, Alpha_value_type y_min, - Alpha_value_type z_min, Alpha_value_type x_max, Alpha_value_type y_max, Alpha_value_type z_max) { + Alpha_complex_3d(const InputPointRange& points, WeightRange weights, FT x_min, FT y_min, + FT z_min, FT x_max, FT y_max, FT z_max) { static_assert(Weighted, "This constructor is not available for non-weighted versions of Alpha_complex_3d"); static_assert(Periodic, "This constructor is not available for non-periodic versions of Alpha_complex_3d"); GUDHI_CHECK((weights.size() == points.size()), @@ -410,7 +399,6 @@ class Alpha_complex_3d { (x_max - x_min == y_max - y_min) && (x_max - x_min == z_max - z_min) && (z_max - z_min == y_max - y_min), std::invalid_argument("The size of the cuboid in every directions is not the same.")); - using Weighted_point_3 = typename Triangulation_3::Weighted_point; std::vector<Weighted_point_3> weighted_points_3; std::size_t index = 0; @@ -418,7 +406,7 @@ class Alpha_complex_3d { #ifdef GUDHI_DEBUG // Defined in GUDHI_DEBUG to avoid unused variable warning for GUDHI_CHECK - Alpha_value_type maximal_possible_weight = 0.015625 * (x_max - x_min) * (x_max - x_min); + FT maximal_possible_weight = 0.015625 * (x_max - x_min) * (x_max - x_min); #endif while ((index < weights.size()) && (index < points.size())) { @@ -431,7 +419,7 @@ class Alpha_complex_3d { } // Define the periodic cube - Triangulation_3 pdt(typename Kernel::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max)); + Dt pdt(typename Kernel::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max)); // Heuristic for inserting large point sets (if pts is reasonably large) pdt.insert(std::begin(weighted_points_3), std::end(weighted_points_3), true); // As pdt won't be modified anymore switch to 1-sheeted cover if possible @@ -451,13 +439,12 @@ class Alpha_complex_3d { * \tparam SimplicialComplexForAlpha3d must meet `SimplicialComplexForAlpha3d` concept. * * @param[in] complex SimplicialComplexForAlpha3d to be created. - * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. + * @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. * * @return true if creation succeeds, false otherwise. * - * @pre The simplicial complex must be empty (no vertices) - * - * Initialization can be launched once. + * @pre The simplicial complex must be empty (no vertices). * */ template <typename SimplicialComplexForAlpha3d, @@ -481,9 +468,9 @@ class Alpha_complex_3d { std::size_t count_cells = 0; #endif // DEBUG_TRACES std::vector<CGAL::Object> objects; - std::vector<Alpha_value_type> alpha_values; + std::vector<FT> alpha_values; - Dispatch dispatcher = CGAL::dispatch_output<CGAL::Object, Alpha_value_type>(std::back_inserter(objects), + Dispatch dispatcher = CGAL::dispatch_output<CGAL::Object, FT>(std::back_inserter(objects), std::back_inserter(alpha_values)); alpha_shape_3_ptr_->filtration_with_alpha_values(dispatcher); @@ -492,7 +479,7 @@ class Alpha_complex_3d { #endif // DEBUG_TRACES Alpha_shape_simplex_tree_map map_cgal_simplex_tree; - using Alpha_value_iterator = typename std::vector<Alpha_value_type>::const_iterator; + using Alpha_value_iterator = typename std::vector<FT>::const_iterator; Alpha_value_iterator alpha_value_iterator = alpha_values.begin(); for (auto object_iterator : objects) { Vertex_list vertex_list; @@ -559,7 +546,7 @@ class Alpha_complex_3d { } } // Construction of the simplex_tree - Filtration_value filtr = Value_from_iterator<Complexity, (Weighted || Periodic)>::perform(alpha_value_iterator); + Filtration_value filtr = Value_from_iterator<Complexity>::perform(alpha_value_iterator); #ifdef DEBUG_TRACES std::cout << "filtration = " << filtr << std::endl; 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 9e071195..ec905d5b 100644 --- a/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp @@ -23,7 +23,6 @@ #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE "alpha_complex_3d" #include <boost/test/unit_test.hpp> -#include <boost/mpl/list.hpp> #include <cmath> // float comparison #include <limits> @@ -49,41 +48,27 @@ using Safe_alpha_complex_3d = using Exact_alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, false>; -using Fast_weighted_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, false>; -using Safe_weighted_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, false>; -using Exact_weighted_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, false>; - -using Fast_periodic_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, false, true>; -using Safe_periodic_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, true>; -using Exact_periodic_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, true>; +template <typename Point> +std::vector<Point> get_points() { + std::vector<Point> points; + points.push_back(Point(0.0, 0.0, 0.0)); + points.push_back(Point(0.0, 0.0, 0.2)); + points.push_back(Point(0.2, 0.0, 0.2)); + points.push_back(Point(0.6, 0.6, 0.0)); + points.push_back(Point(0.8, 0.8, 0.2)); + points.push_back(Point(0.2, 0.8, 0.6)); + + return points; +} -using Fast_weighted_periodic_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, true>; -using Safe_weighted_periodic_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, true>; -using Exact_weighted_periodic_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, true>; BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { // ----------------- // Fast version // ----------------- std::cout << "Fast alpha complex 3d" << std::endl; - std::vector<Fast_alpha_complex_3d::Point_3> points; - points.push_back(Fast_alpha_complex_3d::Point_3(0.0, 0.0, 0.0)); - points.push_back(Fast_alpha_complex_3d::Point_3(0.0, 0.0, 0.2)); - points.push_back(Fast_alpha_complex_3d::Point_3(0.2, 0.0, 0.2)); - points.push_back(Fast_alpha_complex_3d::Point_3(0.6, 0.6, 0.0)); - points.push_back(Fast_alpha_complex_3d::Point_3(0.8, 0.8, 0.2)); - points.push_back(Fast_alpha_complex_3d::Point_3(0.2, 0.8, 0.6)); - Fast_alpha_complex_3d alpha_complex(points); + Fast_alpha_complex_3d alpha_complex(get_points<Fast_alpha_complex_3d::Point_3>()); Gudhi::Simplex_tree<> stree; alpha_complex.create_complex(stree); @@ -93,7 +78,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { // ----------------- std::cout << "Exact alpha complex 3d" << std::endl; - Exact_alpha_complex_3d exact_alpha_complex(points); + Exact_alpha_complex_3d exact_alpha_complex(get_points<Exact_alpha_complex_3d::Point_3>()); Gudhi::Simplex_tree<> exact_stree; exact_alpha_complex.create_complex(exact_stree); @@ -101,13 +86,13 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { // --------------------- // Compare both versions // --------------------- - std::cout << "Exact Alpha complex 3d is of dimension " << exact_stree.dimension() << " - Non exact is " + std::cout << "Exact Alpha complex 3d is of dimension " << exact_stree.dimension() << " - Fast is " << stree.dimension() << std::endl; BOOST_CHECK(exact_stree.dimension() == stree.dimension()); - std::cout << "Exact Alpha complex 3d num_simplices " << exact_stree.num_simplices() << " - Non exact is " + std::cout << "Exact Alpha complex 3d num_simplices " << exact_stree.num_simplices() << " - Fast is " << stree.num_simplices() << std::endl; BOOST_CHECK(exact_stree.num_simplices() == stree.num_simplices()); - std::cout << "Exact Alpha complex 3d num_vertices " << exact_stree.num_vertices() << " - Non exact is " + std::cout << "Exact Alpha complex 3d num_vertices " << exact_stree.num_vertices() << " - Fast is " << stree.num_vertices() << std::endl; BOOST_CHECK(exact_stree.num_vertices() == stree.num_vertices()); @@ -115,19 +100,18 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { while (sh != stree.filtration_simplex_range().end()) { std::vector<int> simplex; std::vector<int> exact_simplex; - std::cout << "Non-exact ( "; + std::cout << "Fast ( "; for (auto vertex : stree.simplex_vertex_range(*sh)) { simplex.push_back(vertex); std::cout << vertex << " "; } - std::cout << ") -> " - << "[" << stree.filtration(*sh) << "] "; - std::cout << std::endl; + std::cout << ") -> [" << stree.filtration(*sh) << "] "; // Find it in the exact structure auto sh_exact = exact_stree.find(simplex); BOOST_CHECK(sh_exact != exact_stree.null_simplex()); + std::cout << " versus [" << exact_stree.filtration(sh_exact) << "] " << std::endl; // Exact and non-exact version is not exactly the same due to float comparison GUDHI_TEST_FLOAT_EQUALITY_CHECK(exact_stree.filtration(sh_exact), stree.filtration(*sh)); @@ -138,7 +122,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { // ----------------- std::cout << "Safe alpha complex 3d" << std::endl; - Safe_alpha_complex_3d safe_alpha_complex(points); + Safe_alpha_complex_3d safe_alpha_complex(get_points<Safe_alpha_complex_3d::Point_3>()); Gudhi::Simplex_tree<> safe_stree; safe_alpha_complex.create_complex(safe_stree); @@ -146,13 +130,13 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { // --------------------- // Compare both versions // --------------------- - std::cout << "Exact Alpha complex 3d is of dimension " << safe_stree.dimension() << " - Non exact is " + std::cout << "Safe Alpha complex 3d is of dimension " << safe_stree.dimension() << " - Fast is " << stree.dimension() << std::endl; BOOST_CHECK(safe_stree.dimension() == stree.dimension()); - std::cout << "Exact Alpha complex 3d num_simplices " << safe_stree.num_simplices() << " - Non exact is " + std::cout << "Safe Alpha complex 3d num_simplices " << safe_stree.num_simplices() << " - Fast is " << stree.num_simplices() << std::endl; BOOST_CHECK(safe_stree.num_simplices() == stree.num_simplices()); - std::cout << "Exact Alpha complex 3d num_vertices " << safe_stree.num_vertices() << " - Non exact is " + std::cout << "Safe Alpha complex 3d num_vertices " << safe_stree.num_vertices() << " - Fast is " << stree.num_vertices() << std::endl; BOOST_CHECK(safe_stree.num_vertices() == stree.num_vertices()); @@ -160,453 +144,21 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { while (safe_sh != stree.filtration_simplex_range().end()) { std::vector<int> simplex; std::vector<int> exact_simplex; -#ifdef DEBUG_TRACES - std::cout << "Non-exact ( "; -#endif + std::cout << "Fast ( "; for (auto vertex : stree.simplex_vertex_range(*safe_sh)) { simplex.push_back(vertex); -#ifdef DEBUG_TRACES std::cout << vertex << " "; -#endif } -#ifdef DEBUG_TRACES - std::cout << ") -> " - << "[" << stree.filtration(*safe_sh) << "] "; - std::cout << std::endl; -#endif + std::cout << ") -> [" << stree.filtration(*safe_sh) << "] "; // Find it in the exact structure auto sh_exact = safe_stree.find(simplex); BOOST_CHECK(sh_exact != safe_stree.null_simplex()); + std::cout << " versus [" << safe_stree.filtration(sh_exact) << "] " << std::endl; // Exact and non-exact version is not exactly the same due to float comparison - GUDHI_TEST_FLOAT_EQUALITY_CHECK(safe_stree.filtration(sh_exact), stree.filtration(*safe_sh)); + GUDHI_TEST_FLOAT_EQUALITY_CHECK(safe_stree.filtration(sh_exact), stree.filtration(*safe_sh), 1e-15); ++safe_sh; } } - -typedef boost::mpl::list<Fast_weighted_alpha_complex_3d, Safe_weighted_alpha_complex_3d, - Exact_weighted_alpha_complex_3d> - weighted_variants_type_list; - -#ifdef GUDHI_DEBUG -BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted_throw, Weighted_alpha_complex_3d, weighted_variants_type_list) { - using Point_3 = typename Weighted_alpha_complex_3d::Point_3; - std::vector<Point_3> 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)); - - // weights size is different from w_points size to make weighted Alpha_complex_3d throw in debug mode - std::vector<double> weights = {0.01, 0.005, 0.006, 0.01, 0.009, 0.001}; - - std::cout << "Check exception throw in debug mode" << std::endl; - BOOST_CHECK_THROW(Weighted_alpha_complex_3d wac(w_points, weights), std::invalid_argument); -} -#endif - -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<Point_3> 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)); - - // weights size is different from w_points size to make weighted Alpha_complex_3d throw in debug mode - std::vector<double> weights = {0.01, 0.005, 0.006, 0.01, 0.009, 0.001}; - - Weighted_alpha_complex_3d alpha_complex_p_a_w(w_points, weights); - Gudhi::Simplex_tree<> stree; - alpha_complex_p_a_w.create_complex(stree); - - std::cout << "Weighted alpha complex 3d from weighted points" << std::endl; - using Weighted_point_3 = typename Weighted_alpha_complex_3d::Triangulation_3::Weighted_point; - - std::vector<Weighted_point_3> weighted_points; - - for (std::size_t i = 0; i < w_points.size(); i++) { - weighted_points.push_back(Weighted_point_3(w_points[i], weights[i])); - } - Weighted_alpha_complex_3d alpha_complex_w_p(weighted_points); - - Gudhi::Simplex_tree<> stree_bis; - alpha_complex_w_p.create_complex(stree_bis); - - // --------------------- - // Compare both versions - // --------------------- - std::cout << "Weighted alpha complex 3d is of dimension " << stree_bis.dimension() << " - versus " - << stree.dimension() << std::endl; - BOOST_CHECK(stree_bis.dimension() == stree.dimension()); - std::cout << "Weighted alpha complex 3d num_simplices " << stree_bis.num_simplices() << " - versus " - << stree.num_simplices() << std::endl; - BOOST_CHECK(stree_bis.num_simplices() == stree.num_simplices()); - std::cout << "Weighted alpha complex 3d num_vertices " << stree_bis.num_vertices() << " - versus " - << stree.num_vertices() << std::endl; - BOOST_CHECK(stree_bis.num_vertices() == stree.num_vertices()); - - auto sh = stree.filtration_simplex_range().begin(); - while (sh != stree.filtration_simplex_range().end()) { - std::vector<int> simplex; - std::vector<int> exact_simplex; -#ifdef DEBUG_TRACES - std::cout << " ( "; -#endif - for (auto vertex : stree.simplex_vertex_range(*sh)) { - simplex.push_back(vertex); -#ifdef DEBUG_TRACES - std::cout << vertex << " "; -#endif - } -#ifdef DEBUG_TRACES - std::cout << ") -> " - << "[" << stree.filtration(*sh) << "] "; - std::cout << std::endl; -#endif - - // Find it in the exact structure - auto sh_exact = stree_bis.find(simplex); - BOOST_CHECK(sh_exact != stree_bis.null_simplex()); - - // Exact and non-exact version is not exactly the same due to float comparison - GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree_bis.filtration(sh_exact), stree.filtration(*sh)); - - ++sh; - } -} - -#ifdef GUDHI_DEBUG -typedef boost::mpl::list<Fast_periodic_alpha_complex_3d, Safe_periodic_alpha_complex_3d, - Exact_periodic_alpha_complex_3d> - periodic_variants_type_list; - -BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_periodic_throw, Periodic_alpha_complex_3d, periodic_variants_type_list) { - std::cout << "Periodic alpha complex 3d exception throw" << std::endl; - using Point_3 = typename Periodic_alpha_complex_3d::Point_3; - std::vector<Point_3> p_points; - - // Not important, this is not what we want to check - p_points.push_back(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 - BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 0.9, 1., 1.), - std::invalid_argument); - BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 0.9, 1.), - std::invalid_argument); - BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 1., 0.9), - std::invalid_argument); - BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1.1, 1., 1.), - std::invalid_argument); - BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 1.1, 1.), - std::invalid_argument); - BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 1., 1.1), - std::invalid_argument); -} -#endif - -BOOST_AUTO_TEST_CASE(Alpha_complex_periodic) { - // --------------------- - // Fast periodic version - // --------------------- - std::cout << "Fast periodic alpha complex 3d" << std::endl; - - using Creator = CGAL::Creator_uniform_3<double, Fast_periodic_alpha_complex_3d::Point_3>; - CGAL::Random random(7); - CGAL::Random_points_in_cube_3<Fast_periodic_alpha_complex_3d::Point_3, Creator> in_cube(1, random); - std::vector<Fast_periodic_alpha_complex_3d::Point_3> p_points; - - for (int i = 0; i < 50; i++) { - Fast_periodic_alpha_complex_3d::Point_3 p = *in_cube++; - p_points.push_back(p); - } - - Fast_periodic_alpha_complex_3d periodic_alpha_complex(p_points, -1., -1., -1., 1., 1., 1.); - - Gudhi::Simplex_tree<> stree; - periodic_alpha_complex.create_complex(stree); - - // ---------------------- - // Exact periodic version - // ---------------------- - std::cout << "Exact periodic alpha complex 3d" << std::endl; - - std::vector<Exact_periodic_alpha_complex_3d::Point_3> 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])); - } - - Exact_periodic_alpha_complex_3d exact_alpha_complex(e_p_points, -1., -1., -1., 1., 1., 1.); - - Gudhi::Simplex_tree<> exact_stree; - exact_alpha_complex.create_complex(exact_stree); - - // --------------------- - // Compare both versions - // --------------------- - std::cout << "Exact periodic alpha complex 3d is of dimension " << exact_stree.dimension() << " - Non exact is " - << stree.dimension() << std::endl; - BOOST_CHECK(exact_stree.dimension() == stree.dimension()); - std::cout << "Exact periodic alpha complex 3d num_simplices " << exact_stree.num_simplices() << " - Non exact is " - << stree.num_simplices() << std::endl; - BOOST_CHECK(exact_stree.num_simplices() == stree.num_simplices()); - std::cout << "Exact periodic alpha complex 3d num_vertices " << exact_stree.num_vertices() << " - Non exact is " - << stree.num_vertices() << std::endl; - BOOST_CHECK(exact_stree.num_vertices() == stree.num_vertices()); - - // We cannot compare as objects from dispatcher on the alpha shape is not deterministic. - // cf. https://github.com/CGAL/cgal/issues/3346 - auto sh = stree.filtration_simplex_range().begin(); - auto sh_exact = exact_stree.filtration_simplex_range().begin(); - - while (sh != stree.filtration_simplex_range().end() || sh_exact != exact_stree.filtration_simplex_range().end()) { - GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), exact_stree.filtration(*sh_exact), 1e-14); - - std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end()); - std::vector<int> exact_vh(exact_stree.simplex_vertex_range(*sh_exact).begin(), - exact_stree.simplex_vertex_range(*sh_exact).end()); - - BOOST_CHECK(vh.size() == exact_vh.size()); - ++sh; - ++sh_exact; - } - - BOOST_CHECK(sh == stree.filtration_simplex_range().end()); - BOOST_CHECK(sh_exact == exact_stree.filtration_simplex_range().end()); - - // ---------------------- - // Safe periodic version - // ---------------------- - std::cout << "Safe periodic alpha complex 3d" << std::endl; - - std::vector<Safe_periodic_alpha_complex_3d::Point_3> 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])); - } - - Safe_periodic_alpha_complex_3d safe_alpha_complex(s_p_points, -1., -1., -1., 1., 1., 1.); - - Gudhi::Simplex_tree<> safe_stree; - safe_alpha_complex.create_complex(safe_stree); - - // --------------------- - // Compare both versions - // --------------------- - // We cannot compare as objects from dispatcher on the alpha shape is not deterministic. - // cf. https://github.com/CGAL/cgal/issues/3346 - sh = stree.filtration_simplex_range().begin(); - auto sh_safe = safe_stree.filtration_simplex_range().begin(); - - while (sh != stree.filtration_simplex_range().end() || sh_safe != safe_stree.filtration_simplex_range().end()) { - GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), safe_stree.filtration(*sh_safe), 1e-14); - - std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end()); - std::vector<int> safe_vh(safe_stree.simplex_vertex_range(*sh_safe).begin(), - safe_stree.simplex_vertex_range(*sh_safe).end()); - - BOOST_CHECK(vh.size() == safe_vh.size()); - ++sh; - ++sh_safe; - } - - BOOST_CHECK(sh == stree.filtration_simplex_range().end()); - BOOST_CHECK(sh_safe == safe_stree.filtration_simplex_range().end()); -} - -typedef boost::mpl::list<Fast_weighted_periodic_alpha_complex_3d, Exact_weighted_periodic_alpha_complex_3d, - Safe_weighted_periodic_alpha_complex_3d> - wp_variants_type_list; - -#ifdef GUDHI_DEBUG -BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted_periodic_throw, Weighted_periodic_alpha_complex_3d, - wp_variants_type_list) { - std::cout << "Weighted periodic alpha complex 3d exception throw" << std::endl; - - using Creator = CGAL::Creator_uniform_3<double, Weighted_periodic_alpha_complex_3d::Point_3>; - CGAL::Random random(7); - CGAL::Random_points_in_cube_3<Weighted_periodic_alpha_complex_3d::Point_3, Creator> in_cube(1, random); - std::vector<Weighted_periodic_alpha_complex_3d::Point_3> wp_points; - - for (int i = 0; i < 50; i++) { - Weighted_periodic_alpha_complex_3d::Point_3 p = *in_cube++; - wp_points.push_back(p); - } - std::vector<double> p_weights; - // Weights must be in range ]0, 1/64 = 0.015625[ - for (std::size_t i = 0; i < wp_points.size(); ++i) { - p_weights.push_back(random.get_double(0., 0.01)); - } - - std::cout << "Cuboid is not iso exception" << std::endl; - // Check it throws an exception when the cuboid is not iso - BOOST_CHECK_THROW( - Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 0.9, 1., 1.), - std::invalid_argument); - BOOST_CHECK_THROW( - Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 0.9, 1.), - std::invalid_argument); - BOOST_CHECK_THROW( - Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 1., 0.9), - std::invalid_argument); - BOOST_CHECK_THROW( - Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1.1, 1., 1.), - std::invalid_argument); - BOOST_CHECK_THROW( - Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 1.1, 1.), - std::invalid_argument); - BOOST_CHECK_THROW( - Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 1., 1.1), - std::invalid_argument); - - std::cout << "0 <= point.weight() < 1/64 * domain_size * domain_size exception" << std::endl; - // Weights must be in range ]0, 1/64 = 0.015625[ - double temp = p_weights[25]; - p_weights[25] = 1.0; - BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.), - std::invalid_argument); - // Weights must be in range ]0, 1/64 = 0.015625[ - p_weights[25] = temp; - temp = p_weights[14]; - p_weights[14] = -1e-10; - BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.), - std::invalid_argument); - p_weights[14] = temp; - - std::cout << "wp_points and p_weights size exception" << std::endl; - // Weights and points must have the same size - // + 1 - p_weights.push_back(1e-10); - BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.), - std::invalid_argument); - // - 1 - p_weights.pop_back(); - p_weights.pop_back(); - BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.), - std::invalid_argument); -} -#endif - -BOOST_AUTO_TEST_CASE(Alpha_complex_weighted_periodic) { - // --------------------- - // Fast weighted periodic version - // --------------------- - std::cout << "Fast weighted periodic alpha complex 3d" << std::endl; - - using Creator = CGAL::Creator_uniform_3<double, Fast_weighted_periodic_alpha_complex_3d::Point_3>; - CGAL::Random random(7); - CGAL::Random_points_in_cube_3<Fast_weighted_periodic_alpha_complex_3d::Point_3, Creator> in_cube(1, random); - std::vector<Fast_weighted_periodic_alpha_complex_3d::Point_3> p_points; - - for (int i = 0; i < 50; i++) { - Fast_weighted_periodic_alpha_complex_3d::Point_3 p = *in_cube++; - p_points.push_back(p); - } - std::vector<double> p_weights; - // Weights must be in range ]0, 1/64 = 0.015625[ - for (std::size_t i = 0; i < p_points.size(); ++i) { - p_weights.push_back(random.get_double(0., 0.01)); - } - - Fast_weighted_periodic_alpha_complex_3d periodic_alpha_complex(p_points, p_weights, -1., -1., -1., 1., 1., 1.); - - Gudhi::Simplex_tree<> stree; - periodic_alpha_complex.create_complex(stree); - - // ---------------------- - // Exact weighted periodic version - // ---------------------- - std::cout << "Exact weighted periodic alpha complex 3d" << std::endl; - - std::vector<Exact_weighted_periodic_alpha_complex_3d::Point_3> 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])); - } - - Exact_weighted_periodic_alpha_complex_3d exact_alpha_complex(e_p_points, p_weights, -1., -1., -1., 1., 1., 1.); - - Gudhi::Simplex_tree<> exact_stree; - exact_alpha_complex.create_complex(exact_stree); - - // --------------------- - // Compare both versions - // --------------------- - std::cout << "Exact weighted periodic alpha complex 3d is of dimension " << exact_stree.dimension() - << " - Non exact is " << stree.dimension() << std::endl; - BOOST_CHECK(exact_stree.dimension() == stree.dimension()); - std::cout << "Exact weighted periodic alpha complex 3d num_simplices " << exact_stree.num_simplices() - << " - Non exact is " << stree.num_simplices() << std::endl; - BOOST_CHECK(exact_stree.num_simplices() == stree.num_simplices()); - std::cout << "Exact weighted periodic alpha complex 3d num_vertices " << exact_stree.num_vertices() - << " - Non exact is " << stree.num_vertices() << std::endl; - BOOST_CHECK(exact_stree.num_vertices() == stree.num_vertices()); - - // We cannot compare as objects from dispatcher on the alpha shape is not deterministic. - // cf. https://github.com/CGAL/cgal/issues/3346 - auto sh = stree.filtration_simplex_range().begin(); - auto sh_exact = exact_stree.filtration_simplex_range().begin(); - - while (sh != stree.filtration_simplex_range().end() || sh_exact != exact_stree.filtration_simplex_range().end()) { - GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), exact_stree.filtration(*sh_exact), 1e-14); - - std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end()); - std::vector<int> exact_vh(exact_stree.simplex_vertex_range(*sh_exact).begin(), - exact_stree.simplex_vertex_range(*sh_exact).end()); - - BOOST_CHECK(vh.size() == exact_vh.size()); - ++sh; - ++sh_exact; - } - - BOOST_CHECK(sh == stree.filtration_simplex_range().end()); - BOOST_CHECK(sh_exact == exact_stree.filtration_simplex_range().end()); - - // ---------------------- - // Safe weighted periodic version - // ---------------------- - std::cout << "Safe weighted periodic alpha complex 3d" << std::endl; - - std::vector<Safe_weighted_periodic_alpha_complex_3d::Point_3> 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])); - } - - Safe_weighted_periodic_alpha_complex_3d safe_alpha_complex(s_p_points, p_weights, -1., -1., -1., 1., 1., 1.); - - Gudhi::Simplex_tree<> safe_stree; - safe_alpha_complex.create_complex(safe_stree); - - // --------------------- - // Compare both versions - // --------------------- - // We cannot compare as objects from dispatcher on the alpha shape is not deterministic. - // cf. https://github.com/CGAL/cgal/issues/3346 - sh = stree.filtration_simplex_range().begin(); - auto sh_safe = safe_stree.filtration_simplex_range().begin(); - - while (sh != stree.filtration_simplex_range().end() || sh_safe != safe_stree.filtration_simplex_range().end()) { - GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), safe_stree.filtration(*sh_safe), 1e-14); - - std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end()); - std::vector<int> safe_vh(safe_stree.simplex_vertex_range(*sh_safe).begin(), - safe_stree.simplex_vertex_range(*sh_safe).end()); - - BOOST_CHECK(vh.size() == safe_vh.size()); - ++sh; - ++sh_safe; - } - - BOOST_CHECK(sh == stree.filtration_simplex_range().end()); - BOOST_CHECK(sh_safe == safe_stree.filtration_simplex_range().end()); -} diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 380380f4..7c6bf9aa 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -19,10 +19,22 @@ endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_executable ( Alpha_complex_3d_test_unit Alpha_complex_3d_unit_test.cpp ) target_link_libraries(Alpha_complex_3d_test_unit ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_executable ( Weighted_alpha_complex_3d_test_unit Weighted_alpha_complex_3d_unit_test.cpp ) + target_link_libraries(Weighted_alpha_complex_3d_test_unit ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_executable ( Periodic_alpha_complex_3d_test_unit Periodic_alpha_complex_3d_unit_test.cpp ) + target_link_libraries(Periodic_alpha_complex_3d_test_unit ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_executable ( Weighted_periodic_alpha_complex_3d_test_unit Weighted_periodic_alpha_complex_3d_unit_test.cpp ) + target_link_libraries(Weighted_periodic_alpha_complex_3d_test_unit ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) if (TBB_FOUND) target_link_libraries(Alpha_complex_3d_test_unit ${TBB_LIBRARIES}) + target_link_libraries(Weighted_alpha_complex_3d_test_unit ${TBB_LIBRARIES}) + target_link_libraries(Periodic_alpha_complex_3d_test_unit ${TBB_LIBRARIES}) + target_link_libraries(Weighted_periodic_alpha_complex_3d_test_unit ${TBB_LIBRARIES}) endif() gudhi_add_coverage_test(Alpha_complex_3d_test_unit) + gudhi_add_coverage_test(Weighted_alpha_complex_3d_test_unit) + gudhi_add_coverage_test(Periodic_alpha_complex_3d_test_unit) + gudhi_add_coverage_test(Weighted_periodic_alpha_complex_3d_test_unit) endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) 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 new file mode 100644 index 00000000..ed4cbff0 --- /dev/null +++ b/src/Alpha_complex/test/Periodic_alpha_complex_3d_unit_test.cpp @@ -0,0 +1,190 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 Inria + * + * This program is free software: 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "alpha_complex_3d" +#include <boost/test/unit_test.hpp> +#include <boost/mpl/list.hpp> + +#include <cmath> // float comparison +#include <limits> +#include <string> +#include <vector> +#include <random> +#include <cstddef> // for std::size_t + +#include <gudhi/Alpha_complex_3d.h> +#include <gudhi/graph_simplicial_complex.h> +#include <gudhi/Simplex_tree.h> +#include <gudhi/Unitary_tests_utils.h> +// to construct Alpha_complex from a OFF file of points +#include <gudhi/Points_3D_off_io.h> + +#include <CGAL/Random.h> +#include <CGAL/point_generators_3.h> + +using Fast_periodic_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, false, true>; +using Safe_periodic_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, true>; +using Exact_periodic_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, true>; + +#ifdef GUDHI_DEBUG +typedef boost::mpl::list<Fast_periodic_alpha_complex_3d, Safe_periodic_alpha_complex_3d, + Exact_periodic_alpha_complex_3d> + periodic_variants_type_list; + +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_periodic_throw, Periodic_alpha_complex_3d, periodic_variants_type_list) { + std::cout << "Periodic alpha complex 3d exception throw" << std::endl; + using Point_3 = typename Periodic_alpha_complex_3d::Point_3; + std::vector<Point_3> p_points; + + // Not important, this is not what we want to check + p_points.push_back(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 + BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 0.9, 1., 1.), + std::invalid_argument); + BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 0.9, 1.), + std::invalid_argument); + BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 1., 0.9), + std::invalid_argument); + BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1.1, 1., 1.), + std::invalid_argument); + BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 1.1, 1.), + std::invalid_argument); + BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 1., 1.1), + std::invalid_argument); +} +#endif + +BOOST_AUTO_TEST_CASE(Alpha_complex_periodic) { + // --------------------- + // Fast periodic version + // --------------------- + std::cout << "Fast periodic alpha complex 3d" << std::endl; + + using Creator = CGAL::Creator_uniform_3<double, Fast_periodic_alpha_complex_3d::Point_3>; + CGAL::Random random(7); + CGAL::Random_points_in_cube_3<Fast_periodic_alpha_complex_3d::Point_3, Creator> in_cube(1, random); + std::vector<Fast_periodic_alpha_complex_3d::Point_3> p_points; + + for (int i = 0; i < 50; i++) { + Fast_periodic_alpha_complex_3d::Point_3 p = *in_cube++; + p_points.push_back(p); + } + + Fast_periodic_alpha_complex_3d periodic_alpha_complex(p_points, -1., -1., -1., 1., 1., 1.); + + Gudhi::Simplex_tree<> stree; + periodic_alpha_complex.create_complex(stree); + + // ---------------------- + // Exact periodic version + // ---------------------- + std::cout << "Exact periodic alpha complex 3d" << std::endl; + + std::vector<Exact_periodic_alpha_complex_3d::Point_3> 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])); + } + + Exact_periodic_alpha_complex_3d exact_alpha_complex(e_p_points, -1., -1., -1., 1., 1., 1.); + + Gudhi::Simplex_tree<> exact_stree; + exact_alpha_complex.create_complex(exact_stree); + + // --------------------- + // Compare both versions + // --------------------- + std::cout << "Exact periodic alpha complex 3d is of dimension " << exact_stree.dimension() << " - Non exact is " + << stree.dimension() << std::endl; + BOOST_CHECK(exact_stree.dimension() == stree.dimension()); + std::cout << "Exact periodic alpha complex 3d num_simplices " << exact_stree.num_simplices() << " - Non exact is " + << stree.num_simplices() << std::endl; + BOOST_CHECK(exact_stree.num_simplices() == stree.num_simplices()); + std::cout << "Exact periodic alpha complex 3d num_vertices " << exact_stree.num_vertices() << " - Non exact is " + << stree.num_vertices() << std::endl; + BOOST_CHECK(exact_stree.num_vertices() == stree.num_vertices()); + + // We cannot compare as objects from dispatcher on the alpha shape is not deterministic. + // cf. https://github.com/CGAL/cgal/issues/3346 + auto sh = stree.filtration_simplex_range().begin(); + auto sh_exact = exact_stree.filtration_simplex_range().begin(); + + while (sh != stree.filtration_simplex_range().end() || sh_exact != exact_stree.filtration_simplex_range().end()) { + GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), exact_stree.filtration(*sh_exact), 1e-14); + + std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end()); + std::vector<int> exact_vh(exact_stree.simplex_vertex_range(*sh_exact).begin(), + exact_stree.simplex_vertex_range(*sh_exact).end()); + + BOOST_CHECK(vh.size() == exact_vh.size()); + ++sh; + ++sh_exact; + } + + BOOST_CHECK(sh == stree.filtration_simplex_range().end()); + BOOST_CHECK(sh_exact == exact_stree.filtration_simplex_range().end()); + + // ---------------------- + // Safe periodic version + // ---------------------- + std::cout << "Safe periodic alpha complex 3d" << std::endl; + + std::vector<Safe_periodic_alpha_complex_3d::Point_3> 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])); + } + + Safe_periodic_alpha_complex_3d safe_alpha_complex(s_p_points, -1., -1., -1., 1., 1., 1.); + + Gudhi::Simplex_tree<> safe_stree; + safe_alpha_complex.create_complex(safe_stree); + + // --------------------- + // Compare both versions + // --------------------- + // We cannot compare as objects from dispatcher on the alpha shape is not deterministic. + // cf. https://github.com/CGAL/cgal/issues/3346 + sh = stree.filtration_simplex_range().begin(); + auto sh_safe = safe_stree.filtration_simplex_range().begin(); + + while (sh != stree.filtration_simplex_range().end() || sh_safe != safe_stree.filtration_simplex_range().end()) { + GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), safe_stree.filtration(*sh_safe), 1e-14); + + std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end()); + std::vector<int> safe_vh(safe_stree.simplex_vertex_range(*sh_safe).begin(), + safe_stree.simplex_vertex_range(*sh_safe).end()); + + BOOST_CHECK(vh.size() == safe_vh.size()); + ++sh; + ++sh_safe; + } + + BOOST_CHECK(sh == stree.filtration_simplex_range().end()); + BOOST_CHECK(sh_safe == safe_stree.filtration_simplex_range().end()); +} 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 new file mode 100644 index 00000000..c16b3718 --- /dev/null +++ b/src/Alpha_complex/test/Weighted_alpha_complex_3d_unit_test.cpp @@ -0,0 +1,147 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 Inria + * + * This program is free software: 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "alpha_complex_3d" +#include <boost/test/unit_test.hpp> +#include <boost/mpl/list.hpp> + +#include <cmath> // float comparison +#include <limits> +#include <string> +#include <vector> +#include <random> +#include <cstddef> // for std::size_t + +#include <gudhi/Alpha_complex_3d.h> +#include <gudhi/graph_simplicial_complex.h> +#include <gudhi/Simplex_tree.h> +#include <gudhi/Unitary_tests_utils.h> +// to construct Alpha_complex from a OFF file of points +#include <gudhi/Points_3D_off_io.h> + +#include <CGAL/Random.h> +#include <CGAL/point_generators_3.h> + +using Fast_weighted_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, false>; +using Safe_weighted_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, false>; +using Exact_weighted_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, false>; + +typedef boost::mpl::list<Fast_weighted_alpha_complex_3d, Safe_weighted_alpha_complex_3d, + Exact_weighted_alpha_complex_3d> + weighted_variants_type_list; + +#ifdef GUDHI_DEBUG +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted_throw, Weighted_alpha_complex_3d, weighted_variants_type_list) { + using Point_3 = typename Weighted_alpha_complex_3d::Point_3; + std::vector<Point_3> 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)); + + // weights size is different from w_points size to make weighted Alpha_complex_3d throw in debug mode + std::vector<double> weights = {0.01, 0.005, 0.006, 0.01, 0.009, 0.001}; + + std::cout << "Check exception throw in debug mode" << std::endl; + BOOST_CHECK_THROW(Weighted_alpha_complex_3d wac(w_points, weights), std::invalid_argument); +} +#endif + +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<Point_3> 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)); + + // weights size is different from w_points size to make weighted Alpha_complex_3d throw in debug mode + std::vector<double> weights = {0.01, 0.005, 0.006, 0.01, 0.009, 0.001}; + + Weighted_alpha_complex_3d alpha_complex_p_a_w(w_points, weights); + Gudhi::Simplex_tree<> stree; + alpha_complex_p_a_w.create_complex(stree); + + std::cout << "Weighted alpha complex 3d from weighted points" << std::endl; + using Weighted_point_3 = typename Weighted_alpha_complex_3d::Weighted_point_3; + + std::vector<Weighted_point_3> weighted_points; + + for (std::size_t i = 0; i < w_points.size(); i++) { + weighted_points.push_back(Weighted_point_3(w_points[i], weights[i])); + } + Weighted_alpha_complex_3d alpha_complex_w_p(weighted_points); + + Gudhi::Simplex_tree<> stree_bis; + alpha_complex_w_p.create_complex(stree_bis); + + // --------------------- + // Compare both versions + // --------------------- + std::cout << "Weighted alpha complex 3d is of dimension " << stree_bis.dimension() << " - versus " + << stree.dimension() << std::endl; + BOOST_CHECK(stree_bis.dimension() == stree.dimension()); + std::cout << "Weighted alpha complex 3d num_simplices " << stree_bis.num_simplices() << " - versus " + << stree.num_simplices() << std::endl; + BOOST_CHECK(stree_bis.num_simplices() == stree.num_simplices()); + std::cout << "Weighted alpha complex 3d num_vertices " << stree_bis.num_vertices() << " - versus " + << stree.num_vertices() << std::endl; + BOOST_CHECK(stree_bis.num_vertices() == stree.num_vertices()); + + auto sh = stree.filtration_simplex_range().begin(); + while (sh != stree.filtration_simplex_range().end()) { + std::vector<int> simplex; + std::vector<int> exact_simplex; +#ifdef DEBUG_TRACES + std::cout << " ( "; +#endif + for (auto vertex : stree.simplex_vertex_range(*sh)) { + simplex.push_back(vertex); +#ifdef DEBUG_TRACES + std::cout << vertex << " "; +#endif + } +#ifdef DEBUG_TRACES + std::cout << ") -> " + << "[" << stree.filtration(*sh) << "] "; + std::cout << std::endl; +#endif + + // Find it in the exact structure + auto sh_exact = stree_bis.find(simplex); + BOOST_CHECK(sh_exact != stree_bis.null_simplex()); + + // Exact and non-exact version is not exactly the same due to float comparison + GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree_bis.filtration(sh_exact), stree.filtration(*sh)); + + ++sh; + } +} 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 new file mode 100644 index 00000000..e8ac83e5 --- /dev/null +++ b/src/Alpha_complex/test/Weighted_periodic_alpha_complex_3d_unit_test.cpp @@ -0,0 +1,239 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 Inria + * + * This program is free software: 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "alpha_complex_3d" +#include <boost/test/unit_test.hpp> +#include <boost/mpl/list.hpp> + +#include <cmath> // float comparison +#include <limits> +#include <string> +#include <vector> +#include <random> +#include <cstddef> // for std::size_t + +#include <gudhi/Alpha_complex_3d.h> +#include <gudhi/graph_simplicial_complex.h> +#include <gudhi/Simplex_tree.h> +#include <gudhi/Unitary_tests_utils.h> +// to construct Alpha_complex from a OFF file of points +#include <gudhi/Points_3D_off_io.h> + +#include <CGAL/Random.h> +#include <CGAL/point_generators_3.h> + +using Fast_weighted_periodic_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, true>; +using Safe_weighted_periodic_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, true>; +using Exact_weighted_periodic_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, true>; + + +typedef boost::mpl::list<Fast_weighted_periodic_alpha_complex_3d, Exact_weighted_periodic_alpha_complex_3d, + Safe_weighted_periodic_alpha_complex_3d> + wp_variants_type_list; + +#ifdef GUDHI_DEBUG +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted_periodic_throw, Weighted_periodic_alpha_complex_3d, + wp_variants_type_list) { + std::cout << "Weighted periodic alpha complex 3d exception throw" << std::endl; + + using Creator = CGAL::Creator_uniform_3<double, typename Weighted_periodic_alpha_complex_3d::Point_3>; + CGAL::Random random(7); + CGAL::Random_points_in_cube_3<typename Weighted_periodic_alpha_complex_3d::Point_3, Creator> in_cube(1, random); + std::vector<typename Weighted_periodic_alpha_complex_3d::Point_3> wp_points; + + for (int i = 0; i < 50; i++) { + typename Weighted_periodic_alpha_complex_3d::Point_3 p = *in_cube++; + wp_points.push_back(p); + } + std::vector<double> p_weights; + // Weights must be in range ]0, 1/64 = 0.015625[ + for (std::size_t i = 0; i < wp_points.size(); ++i) { + p_weights.push_back(random.get_double(0., 0.01)); + } + + std::cout << "Cuboid is not iso exception" << std::endl; + // Check it throws an exception when the cuboid is not iso + BOOST_CHECK_THROW( + Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 0.9, 1., 1.), + std::invalid_argument); + BOOST_CHECK_THROW( + Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 0.9, 1.), + std::invalid_argument); + BOOST_CHECK_THROW( + Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 1., 0.9), + std::invalid_argument); + BOOST_CHECK_THROW( + Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1.1, 1., 1.), + std::invalid_argument); + BOOST_CHECK_THROW( + Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 1.1, 1.), + std::invalid_argument); + BOOST_CHECK_THROW( + Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 1., 1.1), + std::invalid_argument); + + std::cout << "0 <= point.weight() < 1/64 * domain_size * domain_size exception" << std::endl; + // Weights must be in range ]0, 1/64 = 0.015625[ + double temp = p_weights[25]; + p_weights[25] = 1.0; + BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.), + std::invalid_argument); + // Weights must be in range ]0, 1/64 = 0.015625[ + p_weights[25] = temp; + temp = p_weights[14]; + p_weights[14] = -1e-10; + BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.), + std::invalid_argument); + p_weights[14] = temp; + + std::cout << "wp_points and p_weights size exception" << std::endl; + // Weights and points must have the same size + // + 1 + p_weights.push_back(1e-10); + BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.), + std::invalid_argument); + // - 1 + p_weights.pop_back(); + p_weights.pop_back(); + BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.), + std::invalid_argument); +} +#endif + +BOOST_AUTO_TEST_CASE(Alpha_complex_weighted_periodic) { + // --------------------- + // Fast weighted periodic version + // --------------------- + std::cout << "Fast weighted periodic alpha complex 3d" << std::endl; + + using Creator = CGAL::Creator_uniform_3<double, Fast_weighted_periodic_alpha_complex_3d::Point_3>; + CGAL::Random random(7); + CGAL::Random_points_in_cube_3<Fast_weighted_periodic_alpha_complex_3d::Point_3, Creator> in_cube(1, random); + std::vector<Fast_weighted_periodic_alpha_complex_3d::Point_3> p_points; + + for (int i = 0; i < 50; i++) { + Fast_weighted_periodic_alpha_complex_3d::Point_3 p = *in_cube++; + p_points.push_back(p); + } + std::vector<double> p_weights; + // Weights must be in range ]0, 1/64 = 0.015625[ + for (std::size_t i = 0; i < p_points.size(); ++i) { + p_weights.push_back(random.get_double(0., 0.01)); + } + + Fast_weighted_periodic_alpha_complex_3d periodic_alpha_complex(p_points, p_weights, -1., -1., -1., 1., 1., 1.); + + Gudhi::Simplex_tree<> stree; + periodic_alpha_complex.create_complex(stree); + + // ---------------------- + // Exact weighted periodic version + // ---------------------- + std::cout << "Exact weighted periodic alpha complex 3d" << std::endl; + + std::vector<Exact_weighted_periodic_alpha_complex_3d::Point_3> 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])); + } + + Exact_weighted_periodic_alpha_complex_3d exact_alpha_complex(e_p_points, p_weights, -1., -1., -1., 1., 1., 1.); + + Gudhi::Simplex_tree<> exact_stree; + exact_alpha_complex.create_complex(exact_stree); + + // --------------------- + // Compare both versions + // --------------------- + std::cout << "Exact weighted periodic alpha complex 3d is of dimension " << exact_stree.dimension() + << " - Non exact is " << stree.dimension() << std::endl; + BOOST_CHECK(exact_stree.dimension() == stree.dimension()); + std::cout << "Exact weighted periodic alpha complex 3d num_simplices " << exact_stree.num_simplices() + << " - Non exact is " << stree.num_simplices() << std::endl; + BOOST_CHECK(exact_stree.num_simplices() == stree.num_simplices()); + std::cout << "Exact weighted periodic alpha complex 3d num_vertices " << exact_stree.num_vertices() + << " - Non exact is " << stree.num_vertices() << std::endl; + BOOST_CHECK(exact_stree.num_vertices() == stree.num_vertices()); + + // We cannot compare as objects from dispatcher on the alpha shape is not deterministic. + // cf. https://github.com/CGAL/cgal/issues/3346 + auto sh = stree.filtration_simplex_range().begin(); + auto sh_exact = exact_stree.filtration_simplex_range().begin(); + + while (sh != stree.filtration_simplex_range().end() || sh_exact != exact_stree.filtration_simplex_range().end()) { + GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), exact_stree.filtration(*sh_exact), 1e-14); + + std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end()); + std::vector<int> exact_vh(exact_stree.simplex_vertex_range(*sh_exact).begin(), + exact_stree.simplex_vertex_range(*sh_exact).end()); + + BOOST_CHECK(vh.size() == exact_vh.size()); + ++sh; + ++sh_exact; + } + + BOOST_CHECK(sh == stree.filtration_simplex_range().end()); + BOOST_CHECK(sh_exact == exact_stree.filtration_simplex_range().end()); + + // ---------------------- + // Safe weighted periodic version + // ---------------------- + std::cout << "Safe weighted periodic alpha complex 3d" << std::endl; + + std::vector<Safe_weighted_periodic_alpha_complex_3d::Point_3> 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])); + } + + Safe_weighted_periodic_alpha_complex_3d safe_alpha_complex(s_p_points, p_weights, -1., -1., -1., 1., 1., 1.); + + Gudhi::Simplex_tree<> safe_stree; + safe_alpha_complex.create_complex(safe_stree); + + // --------------------- + // Compare both versions + // --------------------- + // We cannot compare as objects from dispatcher on the alpha shape is not deterministic. + // cf. https://github.com/CGAL/cgal/issues/3346 + sh = stree.filtration_simplex_range().begin(); + auto sh_safe = safe_stree.filtration_simplex_range().begin(); + + while (sh != stree.filtration_simplex_range().end() || sh_safe != safe_stree.filtration_simplex_range().end()) { + GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), safe_stree.filtration(*sh_safe), 1e-14); + + std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end()); + std::vector<int> safe_vh(safe_stree.simplex_vertex_range(*sh_safe).begin(), + safe_stree.simplex_vertex_range(*sh_safe).end()); + + BOOST_CHECK(vh.size() == safe_vh.size()); + ++sh; + ++sh_safe; + } + + BOOST_CHECK(sh == stree.filtration_simplex_range().end()); + BOOST_CHECK(sh_safe == safe_stree.filtration_simplex_range().end()); +} |