diff options
Diffstat (limited to 'src/Alpha_complex')
-rw-r--r-- | src/Alpha_complex/doc/Intro_alpha_complex.h | 24 | ||||
-rw-r--r-- | src/Alpha_complex/include/gudhi/Alpha_complex.h | 75 | ||||
-rw-r--r-- | src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 11 | ||||
-rw-r--r-- | src/Alpha_complex/test/Alpha_complex_dim3_unit_test.cpp | 117 | ||||
-rw-r--r-- | src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 94 | ||||
-rw-r--r-- | src/Alpha_complex/test/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp | 2 | ||||
-rw-r--r-- | src/Alpha_complex/utilities/alpha_complex_persistence.cpp | 2 | ||||
-rw-r--r-- | src/Alpha_complex/utilities/alphacomplex.md | 4 |
9 files changed, 201 insertions, 134 deletions
diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index c068b268..41e5e16d 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -83,7 +83,7 @@ Table of Contents * * Then, it is asked to display information about the simplicial complex. * - * \include Alpha_complex/Alpha_complex_from_points.cpp + * \include Alpha_complex_from_points.cpp * * When launching: * @@ -92,7 +92,7 @@ Table of Contents * * the program output is: * - * \include Alpha_complex/alphaoffreader_for_doc_60.txt + * \include alphaoffreader_for_doc_60.txt * * \section createcomplexalgorithm Create complex algorithm * @@ -107,6 +107,7 @@ Table of Contents * \subsection filtrationcomputation Filtration value computation algorithm * <br> * \f$ + * \begin{array}{l} * \textbf{for } \text{i : dimension } \rightarrow 0 \textbf{ do}\\ * \quad \textbf{for all } \sigma \text{ of dimension i}\\ * \quad\quad \textbf{if } \text{filtration(} \sigma ) \text{ is NaN} \textbf{ then}\\ @@ -127,6 +128,7 @@ Table of Contents * \textbf{end for}\\ * \text{make_filtration_non_decreasing()}\\ * \text{prune_above_filtration()}\\ + * \end{array} * \f$ * * \subsubsection dimension2 Dimension 2 @@ -152,6 +154,8 @@ Table of Contents * not quite define a proper filtration (i.e. non-decreasing with respect to inclusion). * We fix that up by calling `SimplicialComplexForAlpha::make_filtration_non_decreasing()`. * + * \note This is not the case in `exact` version, this is the reason why it is not called in this case. + * * \subsubsection pruneabove Prune above given filtration value * * The simplex tree is pruned from the given maximum \f$ \alpha^2 \f$ value (cf. @@ -162,16 +166,16 @@ Table of Contents * <b>Requires:</b> \ref eigen ≥ 3.1.0 and \ref cgal ≥ 5.1.0. * * A weighted version for Alpha complex is available (cf. Alpha_complex). It is like a usual Alpha complex, but based - * on a <a href="https://doc.cgal.org/latest/Triangulation/index.html#title20">CGAL regular triangulation</a> instead + * on a <a href="https://doc.cgal.org/latest/Triangulation/index.html#TriangulationSecRT">CGAL regular triangulation</a> instead * of Delaunay. * * This example builds the CGAL 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 + * it. This example is taken from <a href="https://doc.cgal.org/latest/Alpha_shapes_3/index.html#AlphaShape_3DExampleforWeightedAlphaShapes">CGAL 3d * weighted alpha shapes</a>. * * Then, it is asked to display information about the alpha complex. * - * \include Alpha_complex/Weighted_alpha_complex_from_points.cpp + * \include Weighted_alpha_complex_from_points.cpp * * When launching: * @@ -180,7 +184,7 @@ Table of Contents * * the program output is: * - * \include Alpha_complex/weightedalpha3dfrompoints_for_doc.txt + * \include weightedalpha3dfrompoints_for_doc.txt * * * \section offexample Example from OFF file @@ -190,7 +194,7 @@ Table of Contents * * Then, it is asked to display information about the alpha complex. * - * \include Alpha_complex/Alpha_complex_from_off.cpp + * \include Alpha_complex_from_off.cpp * * When launching: * @@ -199,7 +203,7 @@ Table of Contents * * the program output is: * - * \include Alpha_complex/alphaoffreader_for_doc_32.txt + * \include alphaoffreader_for_doc_32.txt * * * \section weighted3dexample 3d specific version @@ -210,12 +214,12 @@ Table of Contents * 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 + * it. This example is taken from <a href="https://doc.cgal.org/latest/Alpha_shapes_3/index.html#AlphaShape_3DExampleforWeightedAlphaShapes">CGAL 3d * weighted alpha shapes</a>. * * Then, it is asked to display information about the alpha complex. * - * \include Alpha_complex/Weighted_alpha_complex_3d_from_points.cpp + * \include Weighted_alpha_complex_3d_from_points.cpp * * The results will be the same as in \ref weightedversion . * diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index b315fa99..a7372f19 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -17,9 +17,9 @@ // to construct Alpha_complex from a OFF file of points #include <gudhi/Points_off_io.h> -#include <stdlib.h> -#include <math.h> // isnan, fmax +#include <cmath> // isnan, fmax #include <memory> // for std::unique_ptr +#include <cstddef> // for std::size_t #include <CGAL/Delaunay_triangulation.h> #include <CGAL/Regular_triangulation.h> // aka. Weighted Delaunay triangulation @@ -44,6 +44,7 @@ #include <utility> // std::pair #include <stdexcept> #include <numeric> // for std::iota +#include <algorithm> // for std::sort // Make compilation fail - required for external projects - https://github.com/GUDHI/gudhi-devel/issues/10 #if CGAL_VERSION_NR < 1041101000 @@ -68,7 +69,7 @@ template<typename D> struct Is_Epeck_D<CGAL::Epeck_d<D>> { static const bool val * \ingroup alpha_complex * * \details - * The data structure is constructing a CGAL Delaunay triangulation (for more informations on CGAL Delaunay + * The data structure is constructing a CGAL Delaunay triangulation (for more information on CGAL Delaunay * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) from a * range of points or from an OFF file (cf. Points_off_reader). * @@ -100,13 +101,17 @@ template<typename D> struct Is_Epeck_D<CGAL::Epeck_d<D>> { static const bool val */ template<class Kernel = CGAL::Epeck_d<CGAL::Dynamic_dimension_tag>, bool Weighted = false> class Alpha_complex { + private: + // Vertex_handle internal type (required by triangulation_ and vertices_). + using Internal_vertex_handle = std::ptrdiff_t; + public: /** \brief Geometric traits class that provides the geometric types and predicates needed by the triangulations.*/ using Geom_traits = std::conditional_t<Weighted, CGAL::Regular_triangulation_traits_adapter<Kernel>, Kernel>; // Add an int in TDS to save point index in the structure using TDS = CGAL::Triangulation_data_structure<typename Geom_traits::Dimension, - CGAL::Triangulation_vertex<Geom_traits, std::ptrdiff_t>, + CGAL::Triangulation_vertex<Geom_traits, Internal_vertex_handle>, CGAL::Triangulation_full_cell<Geom_traits> >; /** \brief A (Weighted or not) Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ @@ -131,9 +136,6 @@ class Alpha_complex { // Vertex_iterator type from CGAL. using CGAL_vertex_iterator = typename Triangulation::Vertex_iterator; - // size_type type from CGAL. - using size_type = typename Triangulation::size_type; - // Structure to switch from simplex tree vertex handle to CGAL vertex iterator. using Vector_vertex_iterator = std::vector< CGAL_vertex_iterator >; @@ -145,6 +147,10 @@ class Alpha_complex { std::unique_ptr<Triangulation> triangulation_; /** \brief Kernel for triangulation_ functions access.*/ A_kernel_d kernel_; + /** \brief Vertices to be inserted first by the create_complex method to avoid quadratic complexity. + * It isn't just [0, n) if some points have multiplicity (only one copy appears in the complex). + */ + std::vector<Internal_vertex_handle> vertices_; /** \brief Cache for geometric constructions: circumcenter and squared radius of a simplex.*/ std::vector<Sphere> cache_, old_cache_; @@ -213,6 +219,15 @@ class Alpha_complex { Alpha_complex (Alpha_complex&& other) = delete; Alpha_complex& operator= (Alpha_complex&& other) = delete; + /** \brief Returns the number of finite vertices in the triangulation. + */ + std::size_t num_vertices() const { + if (triangulation_ == nullptr) + return 0; + else + return triangulation_->number_of_vertices(); + } + /** \brief get_point returns the point corresponding to the vertex given as parameter. * * @param[in] vertex Vertex handle of the point to retrieve. @@ -247,11 +262,11 @@ class Alpha_complex { std::vector<Point_d> point_cloud(first, last); // Creates a vector {0, 1, ..., N-1} - std::vector<std::ptrdiff_t> indices(boost::counting_iterator<std::ptrdiff_t>(0), - boost::counting_iterator<std::ptrdiff_t>(point_cloud.size())); + std::vector<Internal_vertex_handle> indices(boost::counting_iterator<Internal_vertex_handle>(0), + boost::counting_iterator<Internal_vertex_handle>(point_cloud.size())); using Point_property_map = boost::iterator_property_map<typename std::vector<Point_d>::iterator, - CGAL::Identity_property_map<std::ptrdiff_t>>; + CGAL::Identity_property_map<Internal_vertex_handle>>; using Search_traits_d = CGAL::Spatial_sort_traits_adapter_d<Geom_traits, Point_property_map>; CGAL::spatial_sort(indices.begin(), indices.end(), Search_traits_d(std::begin(point_cloud))); @@ -269,6 +284,9 @@ class Alpha_complex { // structure to retrieve CGAL points from vertex handle - one vertex handle per point. // Needs to be constructed before as vertex handles arrives in no particular order. vertex_handle_to_iterator_.resize(point_cloud.size()); + // List of sorted unique vertices in the triangulation. We take advantage of the existing loop to construct it + // Vertices list avoids quadratic complexity with the Simplex_tree. We should not fill it up with Toplex_map e.g. + vertices_.reserve(triangulation_->number_of_vertices()); // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { if (!triangulation_->is_infinite(*vit)) { @@ -276,8 +294,10 @@ class Alpha_complex { std::clog << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES vertex_handle_to_iterator_[vit->data()] = vit; + vertices_.push_back(vit->data()); } } + std::sort(vertices_.begin(), vertices_.end()); // -------------------------------------------------------------------------------------------- } } @@ -373,13 +393,22 @@ class Alpha_complex { // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list - if (triangulation_->number_of_vertices() > 0) { + if (num_vertices() > 0) { + std::vector<Vertex_handle> one_vertex(1); + for (auto vertex : vertices_) { +#ifdef DEBUG_TRACES + std::clog << "SimplicialComplex insertion " << vertex << std::endl; +#endif // DEBUG_TRACES + one_vertex[0] = vertex; + complex.insert_simplex_and_subfaces(one_vertex, std::numeric_limits<double>::quiet_NaN()); + } + for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { Vector_vertex vertexVector; #ifdef DEBUG_TRACES - std::clog << "Simplex_tree insertion "; + std::clog << "SimplicialComplex insertion "; #endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { if (*vit != nullptr) { @@ -435,8 +464,10 @@ class Alpha_complex { // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- - // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension - complex.make_filtration_non_decreasing(); + if (!exact) + // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension + // Only in not exact version, cf. https://github.com/GUDHI/gudhi-devel/issues/57 + complex.make_filtration_non_decreasing(); // Remove all simplices that have a filtration value greater than max_alpha_square complex.prune_above_filtration(max_alpha_square); // -------------------------------------------------------------------------------------------- @@ -449,10 +480,10 @@ class Alpha_complex { void propagate_alpha_filtration(SimplicialComplexForAlpha& complex, Simplex_handle f_simplex) { // From SimplicialComplexForAlpha type required to assign filtration values. using Filtration_value = typename SimplicialComplexForAlpha::Filtration_value; - using Vertex_handle = typename SimplicialComplexForAlpha::Vertex_handle; // ### Foreach Tau face of Sigma - for (auto f_boundary : complex.boundary_simplex_range(f_simplex)) { + for (auto face_opposite_vertex : complex.boundary_opposite_vertex_simplex_range(f_simplex)) { + auto f_boundary = face_opposite_vertex.first; #ifdef DEBUG_TRACES std::clog << " | --------------------------------------------------\n"; std::clog << " | Tau "; @@ -473,18 +504,10 @@ class Alpha_complex { #endif // DEBUG_TRACES // ### Else } else { - // Find which vertex of f_simplex is missing in f_boundary. We could actually write a variant of boundary_simplex_range that gives pairs (f_boundary, vertex). We rely on the fact that simplex_vertex_range is sorted. - auto longlist = complex.simplex_vertex_range(f_simplex); - auto shortlist = complex.simplex_vertex_range(f_boundary); - auto longiter = std::begin(longlist); - auto shortiter = std::begin(shortlist); - auto enditer = std::end(shortlist); - while(shortiter != enditer && *longiter == *shortiter) { ++longiter; ++shortiter; } - Vertex_handle extra = *longiter; auto const& cache=get_cache(complex, f_boundary); - bool is_gab = kernel_.is_gabriel(cache, get_point_(extra)); + bool is_gab = kernel_.is_gabriel(cache, get_point_(face_opposite_vertex.second)); #ifdef DEBUG_TRACES - std::clog << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << extra << std::endl; + std::clog << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << face_opposite_vertex.second << std::endl; #endif // DEBUG_TRACES // ### If Tau is not Gabriel of Sigma if (false == is_gab) { diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index 4e5fc933..562ef139 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -12,7 +12,6 @@ #ifndef ALPHA_COMPLEX_3D_H_ #define ALPHA_COMPLEX_3D_H_ -#include <boost/version.hpp> #include <boost/variant.hpp> #include <boost/range/size.hpp> #include <boost/range/combine.hpp> @@ -58,8 +57,6 @@ namespace Gudhi { namespace alpha_complex { -thread_local double RELATIVE_PRECISION_OF_TO_DOUBLE = 0.00001; - // Value_from_iterator returns the filtration value from an iterator on alpha shapes values // // FAST SAFE EXACT @@ -101,7 +98,7 @@ struct Value_from_iterator<complexity::EXACT> { * \tparam Periodic Boolean used to set/unset the periodic version of Alpha_complex_3d. Default value is false. * * For the weighted version, weights values are explained on CGAL - * <a href="https://doc.cgal.org/latest/Alpha_shapes_3/index.html#title0">Alpha shapes 3d</a> and + * <a href="https://doc.cgal.org/latest/Alpha_shapes_3/index.html#Alpha_shapes_3Definitions">Alpha shapes 3d</a> and * <a href="https://doc.cgal.org/latest/Triangulation_3/index.html#Triangulation3secclassRegulartriangulation">Regular * triangulation</a> documentation. * @@ -554,8 +551,10 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_ std::clog << "cells \t\t" << count_cells << std::endl; #endif // DEBUG_TRACES // -------------------------------------------------------------------------------------------- - // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension - complex.make_filtration_non_decreasing(); + if (Complexity == complexity::FAST) + // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension + // Only in FAST version, cf. https://github.com/GUDHI/gudhi-devel/issues/57 + complex.make_filtration_non_decreasing(); // Remove all simplices that have a filtration value greater than max_alpha_square complex.prune_above_filtration(max_alpha_square); // -------------------------------------------------------------------------------------------- diff --git a/src/Alpha_complex/test/Alpha_complex_dim3_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_dim3_unit_test.cpp new file mode 100644 index 00000000..e7c261f1 --- /dev/null +++ b/src/Alpha_complex/test/Alpha_complex_dim3_unit_test.cpp @@ -0,0 +1,117 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "alpha_complex_dim3" +#include <boost/test/unit_test.hpp> +#include <boost/mpl/list.hpp> + +#include <CGAL/Epick_d.h> +#include <CGAL/Epeck_d.h> + +#include <stdexcept> // std::out_of_range +#include <string> +#include <vector> + +#include <gudhi/Alpha_complex.h> +#include <gudhi/Simplex_tree.h> + +// Use dynamic_dimension_tag for the user to be able to set dimension +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::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<Exact_kernel_d, Exact_kernel_s, Inexact_kernel_d, Inexact_kernel_s> list_of_kernel_variants; + +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_OFF_file, TestedKernel, list_of_kernel_variants) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-complex from a OFF file + // + // ---------------------------------------------------------------------------- + std::string off_file_name("alphacomplexdoc.off"); + double max_alpha_square_value = 60.0; + std::clog << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; + + Gudhi::alpha_complex::Alpha_complex<TestedKernel> alpha_complex_from_file(off_file_name); + + Gudhi::Simplex_tree<> simplex_tree_60; + BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_60, max_alpha_square_value)); + + std::clog << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == 7); + + std::clog << "simplex_tree_60.dimension()=" << simplex_tree_60.dimension() << std::endl; + BOOST_CHECK(simplex_tree_60.dimension() == 2); + + std::clog << "simplex_tree_60.num_vertices()=" << simplex_tree_60.num_vertices() << std::endl; + BOOST_CHECK(simplex_tree_60.num_vertices() == 7); + + std::clog << "simplex_tree_60.num_simplices()=" << simplex_tree_60.num_simplices() << std::endl; + BOOST_CHECK(simplex_tree_60.num_simplices() == 25); + + max_alpha_square_value = 59.0; + std::clog << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; + + Gudhi::Simplex_tree<> simplex_tree_59; + BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_59, max_alpha_square_value)); + + std::clog << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == 7); + + std::clog << "simplex_tree_59.dimension()=" << simplex_tree_59.dimension() << std::endl; + BOOST_CHECK(simplex_tree_59.dimension() == 2); + + std::clog << "simplex_tree_59.num_vertices()=" << simplex_tree_59.num_vertices() << std::endl; + BOOST_CHECK(simplex_tree_59.num_vertices() == 7); + + std::clog << "simplex_tree_59.num_simplices()=" << simplex_tree_59.num_simplices() << std::endl; + BOOST_CHECK(simplex_tree_59.num_simplices() == 23); +} + + +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_empty_points, TestedKernel, list_of_kernel_variants) { + std::clog << "========== Alpha_complex_from_empty_points ==========" << std::endl; + + // ---------------------------------------------------------------------------- + // Init of an empty list of points + // ---------------------------------------------------------------------------- + std::vector<typename TestedKernel::Point_d> points; + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from the list of points + // ---------------------------------------------------------------------------- + Gudhi::alpha_complex::Alpha_complex<TestedKernel> alpha_complex_from_points(points); + + std::clog << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() == points.size()); + + // Test to the limit + BOOST_CHECK_THROW (alpha_complex_from_points.get_point(0), std::out_of_range); + + Gudhi::Simplex_tree<> simplex_tree; + BOOST_CHECK(!alpha_complex_from_points.create_complex(simplex_tree)); + + std::clog << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl; + BOOST_CHECK(simplex_tree.num_simplices() == 0); + + std::clog << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl; + BOOST_CHECK(simplex_tree.dimension() == -1); + + std::clog << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; + BOOST_CHECK(simplex_tree.num_vertices() == points.size()); +} diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 4b37e4bd..b474917f 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -13,75 +13,17 @@ #include <boost/test/unit_test.hpp> #include <boost/mpl/list.hpp> -#include <CGAL/Delaunay_triangulation.h> #include <CGAL/Epick_d.h> #include <CGAL/Epeck_d.h> -#include <cmath> // float comparison -#include <limits> +#include <stdexcept> // std::out_of_range #include <string> #include <vector> #include <gudhi/Alpha_complex.h> -// to construct a simplex_tree from Delaunay_triangulation -#include <gudhi/graph_simplicial_complex.h> #include <gudhi/Simplex_tree.h> #include <gudhi/Unitary_tests_utils.h> -// Use dynamic_dimension_tag for the user to be able to set dimension -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::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<Exact_kernel_d, Exact_kernel_s, Inexact_kernel_d, Inexact_kernel_s> list_of_kernel_variants; - -BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_OFF_file, TestedKernel, list_of_kernel_variants) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-complex from a OFF file - // - // ---------------------------------------------------------------------------- - std::string off_file_name("alphacomplexdoc.off"); - double max_alpha_square_value = 60.0; - std::clog << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << - max_alpha_square_value << "==========" << std::endl; - - Gudhi::alpha_complex::Alpha_complex<TestedKernel> alpha_complex_from_file(off_file_name); - - Gudhi::Simplex_tree<> simplex_tree_60; - BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_60, max_alpha_square_value)); - - std::clog << "simplex_tree_60.dimension()=" << simplex_tree_60.dimension() << std::endl; - BOOST_CHECK(simplex_tree_60.dimension() == 2); - - std::clog << "simplex_tree_60.num_vertices()=" << simplex_tree_60.num_vertices() << std::endl; - BOOST_CHECK(simplex_tree_60.num_vertices() == 7); - - std::clog << "simplex_tree_60.num_simplices()=" << simplex_tree_60.num_simplices() << std::endl; - BOOST_CHECK(simplex_tree_60.num_simplices() == 25); - - max_alpha_square_value = 59.0; - std::clog << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << - max_alpha_square_value << "==========" << std::endl; - - Gudhi::Simplex_tree<> simplex_tree_59; - BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_59, max_alpha_square_value)); - - std::clog << "simplex_tree_59.dimension()=" << simplex_tree_59.dimension() << std::endl; - BOOST_CHECK(simplex_tree_59.dimension() == 2); - - std::clog << "simplex_tree_59.num_vertices()=" << simplex_tree_59.num_vertices() << std::endl; - BOOST_CHECK(simplex_tree_59.num_vertices() == 7); - - std::clog << "simplex_tree_59.num_simplices()=" << simplex_tree_59.num_simplices() << std::endl; - BOOST_CHECK(simplex_tree_59.num_simplices() == 23); -} - // Use static dimension_tag for the user not to be able to set dimension typedef CGAL::Epeck_d< CGAL::Dimension_tag<4> > Kernel_4; typedef Kernel_4::Point_d Point_4; @@ -120,6 +62,9 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { Gudhi::Simplex_tree<> simplex_tree; BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree)); + std::clog << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() == points.size()); + // Another way to check num_simplices std::clog << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; int num_simplices = 0; @@ -227,34 +172,6 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { } -BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_empty_points, TestedKernel, list_of_kernel_variants) { - std::clog << "========== Alpha_complex_from_empty_points ==========" << std::endl; - - // ---------------------------------------------------------------------------- - // Init of an empty list of points - // ---------------------------------------------------------------------------- - std::vector<typename TestedKernel::Point_d> points; - - // ---------------------------------------------------------------------------- - // Init of an alpha complex from the list of points - // ---------------------------------------------------------------------------- - Gudhi::alpha_complex::Alpha_complex<TestedKernel> alpha_complex_from_points(points); - - // Test to the limit - BOOST_CHECK_THROW (alpha_complex_from_points.get_point(0), std::out_of_range); - - Gudhi::Simplex_tree<> simplex_tree; - BOOST_CHECK(!alpha_complex_from_points.create_complex(simplex_tree)); - - std::clog << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl; - BOOST_CHECK(simplex_tree.num_simplices() == 0); - - std::clog << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl; - BOOST_CHECK(simplex_tree.dimension() == -1); - - std::clog << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; - BOOST_CHECK(simplex_tree.num_vertices() == points.size()); -} using Inexact_kernel_2 = CGAL::Epick_d< CGAL::Dimension_tag<2> >; using Exact_kernel_2 = CGAL::Epeck_d< CGAL::Dimension_tag<2> >; @@ -291,6 +208,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_with_duplicated_points, TestedKernel std::clog << "create_complex" << std::endl; BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree)); + std::clog << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() < points.size()); + std::clog << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; BOOST_CHECK(simplex_tree.num_vertices() < points.size()); diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 0595ca92..dd2c235f 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -8,14 +8,18 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_executable ( Alpha_complex_test_unit Alpha_complex_unit_test.cpp ) target_link_libraries(Alpha_complex_test_unit ${CGAL_LIBRARY}) + add_executable ( Alpha_complex_dim3_test_unit Alpha_complex_dim3_unit_test.cpp ) + target_link_libraries(Alpha_complex_dim3_test_unit ${CGAL_LIBRARY}) add_executable ( Delaunay_complex_test_unit Delaunay_complex_unit_test.cpp ) target_link_libraries(Delaunay_complex_test_unit ${CGAL_LIBRARY}) if (TBB_FOUND) target_link_libraries(Alpha_complex_test_unit ${TBB_LIBRARIES}) + target_link_libraries(Alpha_complex_dim3_test_unit ${TBB_LIBRARIES}) target_link_libraries(Delaunay_complex_test_unit ${TBB_LIBRARIES}) endif() gudhi_add_boost_test(Alpha_complex_test_unit) + gudhi_add_boost_test(Alpha_complex_dim3_test_unit) gudhi_add_boost_test(Delaunay_complex_test_unit) endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) @@ -73,4 +77,4 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) endif() gudhi_add_boost_test(Zero_weighted_alpha_complex_test_unit) -endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0)
\ No newline at end of file +endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) diff --git a/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp b/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp index 91899040..e65d8c6f 100644 --- a/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp +++ b/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp @@ -263,7 +263,7 @@ void program_options(int argc, char *argv[], std::string &off_file_points, bool "cuboid-file,c", po::value<std::string>(&cuboid_file), "Name of file describing the periodic domain. Format is:\n min_hx min_hy min_hz\n max_hx max_hy max_hz")( "output-file,o", po::value<std::string>(&output_file_diag)->default_value(std::string()), - "Name of file in which the persistence diagram is written. Default print in std::clog")( + "Name of file in which the persistence diagram is written. Default print in standard output")( "max-alpha-square-value,r", po::value<Filtration_value>(&alpha_square_max_value) ->default_value(std::numeric_limits<Filtration_value>::infinity()), diff --git a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp index e86b34e2..29edbd8e 100644 --- a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp +++ b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp @@ -163,7 +163,7 @@ void program_options(int argc, char *argv[], std::string &off_file_points, bool "weight-file,w", po::value<std::string>(&weight_file)->default_value(std::string()), "Name of file containing a point weights. Format is one weight per line:\n W1\n ...\n Wn ")( "output-file,o", po::value<std::string>(&output_file_diag)->default_value(std::string()), - "Name of file in which the persistence diagram is written. Default print in std::clog")( + "Name of file in which the persistence diagram is written. Default print in standard output")( "max-alpha-square-value,r", po::value<Filtration_value>(&alpha_square_max_value) ->default_value(std::numeric_limits<Filtration_value>::infinity()), "Maximal alpha square value for the Alpha complex construction.")( diff --git a/src/Alpha_complex/utilities/alphacomplex.md b/src/Alpha_complex/utilities/alphacomplex.md index 0d3c6027..1e3b8fab 100644 --- a/src/Alpha_complex/utilities/alphacomplex.md +++ b/src/Alpha_complex/utilities/alphacomplex.md @@ -64,7 +64,7 @@ N.B.: * Weights values are explained on CGAL
[dD Triangulations](https://doc.cgal.org/latest/Triangulation/index.html)
and
-[Regular triangulation](https://doc.cgal.org/latest/Triangulation/index.html#title20) documentation.
+[Regular triangulation](https://doc.cgal.org/latest/Triangulation/index.html#TriangulationSecRT) documentation.
## alpha_complex_3d_persistence ##
@@ -131,6 +131,6 @@ N.B.: * `alpha_complex_3d_persistence` only accepts OFF files in dimension 3.
* Filtration values are alpha square values.
* Weights values are explained on CGAL
-[Alpha shape](https://doc.cgal.org/latest/Alpha_shapes_3/index.html#title0)
+[Alpha shape](https://doc.cgal.org/latest/Alpha_shapes_3/index.html#Alpha_shapes_3Definitions)
and
[Regular triangulation](https://doc.cgal.org/latest/Triangulation_3/index.html#Triangulation3secclassRegulartriangulation) documentation.
|