From 77b57ae69fa2042b652d91d8015c1d9533176090 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 16 Jun 2015 13:30:27 +0000 Subject: Alpha_complex renamed. Compilation and tests are OK. bimap is stored in class. bimap is now on CGAL Vertex_iterator - instead of points. is_gabriel not computed when simplex dimension is 1. is_gabriel not computed when filt(Tau) is not NaN. Delaunay_triangulation is a pointer constructed in Delaunay_triangulation_off_io.h git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@617 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4fa4a26ce47066efe22aed99734ff1dd821ad70b --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 339 ++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 src/Alpha_complex/include/gudhi/Alpha_complex.h (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h new file mode 100644 index 00000000..ca84d6d9 --- /dev/null +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -0,0 +1,339 @@ +/* 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 Saclay (France) + * + * 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 . + */ + +#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ +#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ + +// to construct a Delaunay_triangulation from a OFF file +#include + +// to construct a simplex_tree from Delaunay_triangulation +#include +#include + +#include +#include +#include // isnan, fmax + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Gudhi { + +namespace alphacomplex { + +#define Kinit(f) =k.f() + +/** \defgroup alpha_complex Alpha complex in dimension N + * +
Implementations:
+ Alpha complex in dimension N are a subset of Delaunay Triangulation in dimension N. + + + * \author Vincent Rouvreau + * \version 1.0 + * \date 2015 + * \copyright GNU General Public License v3. + * @{ + */ + +/** + * \brief Alpha complex data structure. + * + * \details Every simplex \f$[v_0, \cdots ,v_d]\f$ admits a canonical orientation + * induced by the order relation on vertices \f$ v_0 < \cdots < v_d \f$. + * + * Details may be found in \cite boissonnatmariasimplextreealgorithmica. + * + * + */ +class Alpha_complex { + private: + // From Simplex_tree + /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + typedef std::vector typeVectorVertex; + + typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; + typedef typename std::pair Simplex_result; + + // From CGAL + /** \brief Kernel for the Delaunay_triangulation-> + * Dimension can be set dynamically. + */ + typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + /** \brief Delaunay_triangulation type required to create an alpha-complex. + */ + typedef CGAL::Delaunay_triangulation Delaunay_triangulation; + + typedef typename Kernel::Compute_squared_radius_d Squared_Radius; + typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; + + /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + typedef std::vector Vector_of_CGAL_points; + + typedef Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; + + typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; + + private: + /** \brief Upper bound on the simplex tree of the simplicial complex.*/ + Gudhi::Simplex_tree<> st_; + Bimap_vertex cgal_simplextree; + Delaunay_triangulation* triangulation; + + public: + + Alpha_complex(std::string& off_file_name) + : triangulation(nullptr) { +#ifdef DEBUG_TRACES + char buffer[256]={0}; + sprintf(buffer,"%p", triangulation); + std::cout << "pointer=" << buffer << std::endl; +#endif // DEBUG_TRACES + Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(off_file_name); + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << off_file_name << std::endl; + exit(-1); // ----- >> + } + triangulation = off_reader.get_complex(); +#ifdef DEBUG_TRACES + //char buffer[256]={0}; + sprintf(buffer,"%p", triangulation); + std::cout << "pointer=" << buffer << std::endl; + std::cout << "number of vertices=" << triangulation->number_of_vertices() << std::endl; + std::cout << "number of full cells=" << triangulation->number_of_full_cells() << std::endl; + std::cout << "number of finite full cells=" << triangulation->number_of_finite_full_cells() << std::endl; +#endif // DEBUG_TRACES + init(); + } + + ~Alpha_complex() { + delete triangulation; + } + + private: + + void init() { + st_.set_dimension(triangulation->maximal_dimension()); + + // -------------------------------------------------------------------------------------------- + // bimap to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa + // Start to insert at handle = 0 - default integer value + Vertex_handle vertex_handle = Vertex_handle(); + // Loop on triangulation vertices list + for (CGAL_vertex_iterator vit = triangulation->vertices_begin(); vit != triangulation->vertices_end(); ++vit) { + cgal_simplextree.insert(Bimap_vertex::value_type(vit, vertex_handle)); + vertex_handle++; + } + // -------------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------------- + // Simplex_tree construction from loop on triangulation finite full cells list + for (auto cit = triangulation->finite_full_cells_begin(); cit != triangulation->finite_full_cells_end(); ++cit) { + typeVectorVertex vertexVector; +#ifdef DEBUG_TRACES + std::cout << "Simplex_tree insertion "; +#endif // DEBUG_TRACES + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { +#ifdef DEBUG_TRACES + std::cout << " " << cgal_simplextree.left.at(*vit); +#endif // DEBUG_TRACES + // Vector of vertex construction for simplex_tree structure + vertexVector.push_back(cgal_simplextree.left.at(*vit)); + } +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES + // Insert each simplex and its subfaces in the simplex tree - filtration is NaN + Simplex_result insert_result = st_.insert_simplex_and_subfaces(vertexVector, + std::numeric_limits::quiet_NaN()); + if (!insert_result.second) { + std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; + } + } + // -------------------------------------------------------------------------------------------- + + Filtration_value filtration_max = 0.0; + // -------------------------------------------------------------------------------------------- + // ### For i : d -> 0 + for (int decr_dim = st_.dimension(); decr_dim >= 0; decr_dim--) { + // ### Foreach Sigma of dim i + for (auto f_simplex : st_.skeleton_simplex_range(decr_dim)) { + int f_simplex_dim = st_.dimension(f_simplex); + if (decr_dim == f_simplex_dim) { + Vector_of_CGAL_points pointVector; +#ifdef DEBUG_TRACES + std::cout << "Sigma of dim " << decr_dim << " is"; +#endif // DEBUG_TRACES + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); +#ifdef DEBUG_TRACES + std::cout << " " << vertex; +#endif // DEBUG_TRACES + } +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES + // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) + if (isnan(st_.filtration(f_simplex))) { + Filtration_value alpha_complex_filtration = 0.0; + // No need to compute squared_radius on a single point - alpha is 0.0 + if (f_simplex_dim > 0) { + // squared_radius function initialization + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + + alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); + } + st_.assign_filtration(f_simplex, alpha_complex_filtration); + filtration_max = fmax(filtration_max, alpha_complex_filtration); +#ifdef DEBUG_TRACES + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; +#endif // DEBUG_TRACES + } + propagate_alpha_filtration(f_simplex, decr_dim); + } + } + } + // -------------------------------------------------------------------------------------------- + +#ifdef DEBUG_TRACES + std::cout << "filtration_max=" << filtration_max << std::endl; +#endif // DEBUG_TRACES + st_.set_filtration(filtration_max); + } + + template + void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { + // ### Foreach Tau face of Sigma + for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { +#ifdef DEBUG_TRACES + std::cout << " | --------------------------------------------------" << std::endl; + std::cout << " | Tau "; + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + std::cout << vertex << " "; + } + std::cout << "is a face of Sigma" << std::endl; + std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; +#endif // DEBUG_TRACES + // ### If filt(Tau) is not NaN + if (!isnan(st_.filtration(f_boundary))) { + // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) + Filtration_value alpha_complex_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); + st_.assign_filtration(f_boundary, alpha_complex_filtration); + // No need to check for filtration_max, alpha_complex_filtration is a min of an existing filtration value +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES + // ### Else + } else { + // No need to compute is_gabriel for dimension <= 2 + // i.e. : Sigma = (3,1) => Tau = 1 + if (decr_dim > 1) { + // insert the Tau points in a vector for is_gabriel function + Vector_of_CGAL_points pointVector; + Vertex_handle vertexForGabriel = Vertex_handle(); + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); + } + // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + if (std::find(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertex))->point()) + == pointVector.end()) { + // vertex is not found in Tau + vertexForGabriel = vertex; + // No need to continue loop + break; + } + } + // is_gabriel function initialization + Kernel k; + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); +#ifdef DEBUG_TRACES + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) + != CGAL::ON_BOUNDED_SIDE; + std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; +#endif // DEBUG_TRACES + // ### If Tau is not Gabriel of Sigma + if ((is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) + == CGAL::ON_BOUNDED_SIDE)) { + // ### filt(Tau) = filt(Sigma) + Filtration_value alpha_complex_filtration = st_.filtration(f_simplex); + st_.assign_filtration(f_boundary, alpha_complex_filtration); + // No need to check for filtration_max, alpha_complex_filtration is an existing filtration value +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = filt(Sigma) = " << st_.filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES + } + } + } + } + } + public: + + /** \brief Returns the number of vertices in the complex. */ + size_t num_vertices() { + return st_.num_vertices(); + } + + /** \brief Returns the number of simplices in the complex. + * + * Does not count the empty simplex. */ + const unsigned int& num_simplices() const { + return st_.num_simplices(); + } + + /** \brief Returns an upper bound on the dimension of the simplicial complex. */ + int dimension() { + return st_.dimension(); + } + + /** \brief Returns an upper bound of the filtration values of the simplices. */ + Filtration_value filtration() { + return st_.filtration(); + } + + friend std::ostream& operator<<(std::ostream& os, const Alpha_complex & alpha_complex) { + // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor + Gudhi::Simplex_tree<> st = alpha_complex.st_; + os << st << std::endl; + return os; + } +}; + +} // namespace alphacomplex + +} // namespace Gudhi + +#endif // SRC_ALPHA_COMPLEX_INCLUDE_GUDHI_ALPHA_COMPLEX_H_ -- cgit v1.2.3 From 56e89b6b7666dec86a70f6a30f08ef8b7960eb21 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 Jun 2015 14:21:31 +0000 Subject: Moved alphashapedoc.off in data/points Moved Delaunay triangulation OFF files read and write in src/common Delaunay triangulation OFF files read and write documentation, examples and tests git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@623 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e03902736a79436e97dbf77a88504f3faa8bd9c6 --- CMakeLists.txt | 9 +- data/points/alphashapedoc.off | 10 + src/Alpha_complex/example/CMakeLists.txt | 9 +- .../example/Delaunay_triangulation_off_rw.cpp | 79 ------ .../Simplex_tree_from_delaunay_triangulation.cpp | 27 +- src/Alpha_complex/example/alphashapedoc.off | 10 - src/Alpha_complex/include/gudhi/Alpha_complex.h | 70 +++-- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 210 -------------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 71 ++--- src/Alpha_complex/test/CMakeLists.txt | 2 +- src/Alpha_complex/test/README | 2 +- src/Alpha_complex/test/S4_100.off | 4 +- src/Alpha_complex/test/S8_10.off | 4 +- src/CMakeLists.txt | 1 + src/Doxyfile | 3 +- src/common/example/CMakeLists.txt | 26 ++ .../example/Delaunay_triangulation_off_rw.cpp | 55 ++++ .../include/gudhi/Delaunay_triangulation_off_io.h | 308 +++++++++++++++++++++ src/common/include/gudhi/Off_reader.h | 291 ++++++++++--------- src/common/test/CMakeLists.txt | 44 +++ src/common/test/README | 14 + src/common/test/dtoffrw_alphashapedoc_result.off | 15 + src/common/test/dtoffrw_alphashapedoc_result.txt | 3 + src/common/test/dtoffrw_unit_test.cpp | 91 ++++++ 24 files changed, 790 insertions(+), 568 deletions(-) create mode 100755 data/points/alphashapedoc.off delete mode 100644 src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp delete mode 100755 src/Alpha_complex/example/alphashapedoc.off delete mode 100644 src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h create mode 100644 src/common/example/CMakeLists.txt create mode 100644 src/common/example/Delaunay_triangulation_off_rw.cpp create mode 100644 src/common/include/gudhi/Delaunay_triangulation_off_io.h create mode 100644 src/common/test/CMakeLists.txt create mode 100644 src/common/test/README create mode 100644 src/common/test/dtoffrw_alphashapedoc_result.off create mode 100644 src/common/test/dtoffrw_alphashapedoc_result.txt create mode 100644 src/common/test/dtoffrw_unit_test.cpp (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index 01108db9..86b4e2b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,11 @@ if (PYTHON_PATH) message("python found in ${PYTHON_PATH}") endif() +FIND_PROGRAM( DIFF_PATH diff ) +if (DIFF_PATH) + message("diff found in ${DIFF_PATH}") +endif() + # Function to add_test cpplint on each header file of the Gudhi module function(cpplint_add_tests the_directory) if (PYTHON_PATH) @@ -77,9 +82,11 @@ else() include_directories(src/Simplex_tree/include/) include_directories(src/Skeleton_blocker/include/) + add_subdirectory(src/common/example) + add_subdirectory(src/common/test) add_subdirectory(src/Simplex_tree/test) add_subdirectory(src/Simplex_tree/example) - add_subdirectory(src/Persistent_cohomology/test) + #add_subdirectory(src/Persistent_cohomology/test) add_subdirectory(src/Persistent_cohomology/example) add_subdirectory(src/Skeleton_blocker/test) add_subdirectory(src/Skeleton_blocker/example) diff --git a/data/points/alphashapedoc.off b/data/points/alphashapedoc.off new file mode 100755 index 00000000..bb790193 --- /dev/null +++ b/data/points/alphashapedoc.off @@ -0,0 +1,10 @@ +nOFF +2 7 0 0 +1.0 1.0 +7.0 0.0 +4.0 6.0 +9.0 6.0 +0.0 14.0 +2.0 19.0 +9.0 17.0 + diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 258def49..9129fdcf 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -14,17 +14,10 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - add_definitions(-DDEBUG_TRACES) - - add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) - target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(dtoffrw_tore3D ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off 3) - + #add_definitions(-DDEBUG_TRACES) add_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_executable ( template_off template_off.cpp ) - target_link_libraries(template_off ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp deleted file mode 100644 index 405b3cb9..00000000 --- a/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* 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) 2014 INRIA Saclay (France) - * - * 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 . - */ - -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instanciation of the -// TriangulationDataStructure template parameter - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " inputFile.off dimension outputFile.off" << std::endl; - exit(-1); // ----- >> -} - -int main(int argc, char **argv) { - if (argc != 4) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - int dimension = 0; - int returnedScanValue = sscanf(argv[2], "%d", &dimension); - if ((returnedScanValue == EOF) || (dimension <= 0)) { - std::cerr << "Error: " << argv[2] << " is not correct" << std::endl; - usage(argv[0]); - } - - T dt(dimension); - std::string offFileName(argv[1]); - Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(offFileName, dt); - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << offFileName << std::endl; - exit(-1); // ----- >> - } - - std::cout << "number_of_finite_full_cells= " << dt.number_of_finite_full_cells() << std::endl; - - std::string outFileName(argv[3]); - std::string offOutputFile(outFileName); - Gudhi::alphacomplex::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); - - return 0; -} \ No newline at end of file diff --git a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp index f09e6121..1523372a 100644 --- a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -21,19 +21,13 @@ */ // to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" +#include "gudhi/Delaunay_triangulation_off_io.h" #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 -#include -#include -#include -#include - #include #include @@ -41,12 +35,6 @@ #include #include -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instanciation of the -// TriangulationDataStructure template parameter - void usage(char * const progName) { std::cerr << "Usage: " << progName << " filename.off" << std::endl; exit(-1); // ----- >> @@ -62,7 +50,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // - // Init of an alpha-complex from a OFF file + // Init of an alpha-complex from an OFF file // // ---------------------------------------------------------------------------- Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); @@ -71,7 +59,14 @@ int main(int argc, char **argv) { std::cout << "alpha_complex_from_file.filtration()=" << alpha_complex_from_file.filtration() << std::endl; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; - std::cout << alpha_complex_from_file << std::endl; - + + std::cout << "Iterator on Simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + std::cout << " " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; + for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + } return 0; } \ No newline at end of file diff --git a/src/Alpha_complex/example/alphashapedoc.off b/src/Alpha_complex/example/alphashapedoc.off deleted file mode 100755 index bb790193..00000000 --- a/src/Alpha_complex/example/alphashapedoc.off +++ /dev/null @@ -1,10 +0,0 @@ -nOFF -2 7 0 0 -1.0 1.0 -7.0 0.0 -4.0 6.0 -9.0 6.0 -0.0 14.0 -2.0 19.0 -9.0 17.0 - diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index ca84d6d9..d25c05cb 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -23,9 +23,6 @@ #ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ #define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ -// to construct a Delaunay_triangulation from a OFF file -#include - // to construct a simplex_tree from Delaunay_triangulation #include #include @@ -46,8 +43,7 @@ #include #include #include -#include -#include +#include // NaN namespace Gudhi { @@ -82,59 +78,59 @@ class Alpha_complex { private: // From Simplex_tree /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ - typedef std::vector typeVectorVertex; + typedef std::vector Vector_vertex; + /** \brief Simplex_handle type from simplex_tree.*/ typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; + /** \brief Simplex_result is the type returned from simplex_tree insert function.*/ typedef typename std::pair Simplex_result; + /** \brief Filtration_simplex_range type from simplex_tree.*/ + typedef typename Gudhi::Simplex_tree<>::Filtration_simplex_range Filtration_simplex_range; + + /** \brief Simplex_vertex_range type from simplex_tree.*/ + typedef typename Gudhi::Simplex_tree<>::Simplex_vertex_range Simplex_vertex_range; + // From CGAL - /** \brief Kernel for the Delaunay_triangulation-> - * Dimension can be set dynamically. - */ + /** \brief Kernel for the Delaunay_triangulation. Dimension can be set dynamically.*/ typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - /** \brief Delaunay_triangulation type required to create an alpha-complex. - */ + /** \brief Delaunay_triangulation type required to create an alpha-complex.*/ typedef CGAL::Delaunay_triangulation Delaunay_triangulation; typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; - /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + /** \brief Type required to compute squared radius, or side of bounded sphere on a vector of points.*/ typedef std::vector Vector_of_CGAL_points; + /** \brief Vertex_iterator type from CGAL.*/ typedef Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; + /** \brief Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; private: - /** \brief Upper bound on the simplex tree of the simplicial complex.*/ + /** \brief Alpha complex is represented internally by a simplex tree.*/ Gudhi::Simplex_tree<> st_; + /** \brief Boost bimap to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ Bimap_vertex cgal_simplextree; + /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation; public: - Alpha_complex(std::string& off_file_name) : triangulation(nullptr) { -#ifdef DEBUG_TRACES - char buffer[256]={0}; - sprintf(buffer,"%p", triangulation); - std::cout << "pointer=" << buffer << std::endl; -#endif // DEBUG_TRACES - Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(off_file_name); + Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << off_file_name << std::endl; exit(-1); // ----- >> } triangulation = off_reader.get_complex(); -#ifdef DEBUG_TRACES - //char buffer[256]={0}; - sprintf(buffer,"%p", triangulation); - std::cout << "pointer=" << buffer << std::endl; - std::cout << "number of vertices=" << triangulation->number_of_vertices() << std::endl; - std::cout << "number of full cells=" << triangulation->number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << triangulation->number_of_finite_full_cells() << std::endl; -#endif // DEBUG_TRACES + init(); + } + + Alpha_complex(Delaunay_triangulation* triangulation_ptr) + : triangulation(triangulation_ptr) { init(); } @@ -142,6 +138,21 @@ class Alpha_complex { delete triangulation; } + Filtration_simplex_range filtration_simplex_range() { + return st_.filtration_simplex_range(); + } + + Simplex_vertex_range simplex_vertex_range(Simplex_handle sh) { + return st_.simplex_vertex_range(sh); + } + + /** \brief Returns the filtration value of a simplex. + * + * Called on the null_simplex, returns INFINITY. */ + Gudhi::Simplex_tree<>::Filtration_value filtration(Simplex_handle sh) { + return st_.filtration(sh); + } + private: void init() { @@ -161,7 +172,7 @@ class Alpha_complex { // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation->finite_full_cells_begin(); cit != triangulation->finite_full_cells_end(); ++cit) { - typeVectorVertex vertexVector; + Vector_vertex vertexVector; #ifdef DEBUG_TRACES std::cout << "Simplex_tree insertion "; #endif // DEBUG_TRACES @@ -325,7 +336,6 @@ class Alpha_complex { } friend std::ostream& operator<<(std::ostream& os, const Alpha_complex & alpha_complex) { - // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor Gudhi::Simplex_tree<> st = alpha_complex.st_; os << st << std::endl; return os; diff --git a/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h deleted file mode 100644 index 8bda23b7..00000000 --- a/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ /dev/null @@ -1,210 +0,0 @@ -/* 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 Saclay (France) - * - * 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 . - */ -#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ -#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ - -#include -#include -#include -#include - -#include "gudhi/Off_reader.h" - -namespace Gudhi { - -namespace alphacomplex { - -/** - *@brief Off reader visitor with flag that can be passed to Off_reader to read a Delaunay_triangulation_complex. - */ -template -class Delaunay_triangulation_off_visitor_reader { - private: - Complex* _complex; - typedef typename Complex::Point Point; - - public: - - // Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. - Delaunay_triangulation_off_visitor_reader(Complex* _complex_ptr) - : _complex(nullptr) { } - - void init(int dim, int num_vertices, int num_faces, int num_edges) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << - num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; -#endif // DEBUG_TRACES - if (num_faces > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << - "file for Delaunay triangulation - faces are computed." << std::endl; - } - if (num_edges > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << - "file for Delaunay triangulation - edges are computed." << std::endl; - } - // Complex construction with dimension from file - _complex = new Complex(dim); - } - - void point(const std::vector& point) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::point "; - for (auto coordinate : point) { - std::cout << coordinate << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES - _complex->insert(Point(point.size(), point.begin(), point.end())); - } - - void maximal_face(const std::vector& face) { - // For Delaunay Triangulation, only points are read -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::face "; - for (auto vertex : face) { - std::cout << vertex << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES - } - - void done() { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::done" << std::endl; -#endif // DEBUG_TRACES - } - - Complex* get_complex() { - return _complex; - } -}; - -/** - *@brief Class that allows to load a Delaunay_triangulation_complex from an off file. - */ -template -class Delaunay_triangulation_off_reader { - public: - - /** - * name_file : file to read - * read_complex : complex that will receive the file content - * read_only_points : specify true if only the points must be read - */ - Delaunay_triangulation_off_reader(const std::string & name_file) : valid_(false) { - std::ifstream stream(name_file); - if (stream.is_open()) { - Delaunay_triangulation_off_visitor_reader off_visitor(_complex); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - if (valid_) { - _complex = off_visitor.get_complex(); - } - } else { - std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << - name_file << std::endl; - } - - } - - /** - * return true if reading did not meet problems. - */ - bool is_valid() const { - return valid_; - } - - Complex* get_complex() { - if (valid_) - return _complex; - return nullptr; - - } - - private: - bool valid_; - Complex* _complex; -}; - -template -class Delaunay_triangulation_off_writer { - public: - typedef typename Complex::Point Point; - - /** - * name_file : file where the off will be written - * save_complex : complex that be outputted in the file - * for now only save triangles. - */ - Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) { - std::ofstream stream(name_file); - if (stream.is_open()) { - if (complex_ptr->current_dimension() == 3) { - // OFF header - stream << "OFF" << std::endl; - // no endl on next line - don't know why... - stream << complex_ptr->number_of_vertices() << " " << complex_ptr->number_of_finite_full_cells() << " 0"; - } else { - // nOFF header - stream << "nOFF" << std::endl; - // no endl on next line - don't know why... - stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << - complex_ptr->number_of_finite_full_cells() << " 0"; - - } - - // bimap to retrieve vertex handles from points and vice versa - std::map< Point, int > points_to_vh; - // Start to insert at default handle value - int vertex_handle = int(); - - // Points list - for (auto vit = complex_ptr->vertices_begin(); vit != complex_ptr->vertices_end(); ++vit) { - for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { - stream << *Coord << " "; - } - stream << std::endl; - points_to_vh[vit->point()] = vertex_handle; - vertex_handle++; - } - - for (auto cit = complex_ptr->finite_full_cells_begin(); cit != complex_ptr->finite_full_cells_end(); ++cit) { - std::vector vertexVector; - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - stream << points_to_vh[(*vit)->point()] << " "; - } - stream << std::endl; - } - stream.close(); - } else { - std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << - name_file << std::endl; - } - } -}; - -} // namespace alphacomplex - -} // namespace Gudhi - -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 38168f10..86d4d9c3 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -25,25 +25,10 @@ #include #include // to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" +#include "gudhi/Delaunay_triangulation_off_io.h" #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 -#include -#include -#include -#include - -#include -#include - -#include -#include -#include +#include // float comparison // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; @@ -51,7 +36,7 @@ typedef CGAL::Delaunay_triangulation T; // The triangulation uses the default instantiation of the // TriangulationDataStructure template parameter -BOOST_AUTO_TEST_CASE( OFF_file ) { +BOOST_AUTO_TEST_CASE( S4_100_OFF_file ) { // ---------------------------------------------------------------------------- // // Init of an alpha-complex from a OFF file @@ -66,61 +51,37 @@ BOOST_AUTO_TEST_CASE( OFF_file ) { std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - const double FILTRATION = 0.0; - std::cout << "alpha_complex_from_file.filtration()=" << alpha_complex_from_file.filtration() << std::endl; - BOOST_CHECK(alpha_complex_from_file.filtration() == FILTRATION); - const int NUMBER_OF_VERTICES = 100; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 6779; + const int NUMBER_OF_SIMPLICES = 6879; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); } -BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { +BOOST_AUTO_TEST_CASE( S8_10_OFF_file ) { // ---------------------------------------------------------------------------- // - // Init of an alpha-complex from a Delaunay triangulation + // Init of an alpha-complex from a OFF file // // ---------------------------------------------------------------------------- - T dt; std::string off_file_name("S8_10.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); - std::cout << "off_reader.is_valid()=" << off_reader.is_valid() << std::endl; - BOOST_CHECK(off_reader.is_valid()); - - const int NUMBER_OF_VERTICES = 10; - std::cout << "dt.number_of_vertices()=" << dt.number_of_vertices() << std::endl; - BOOST_CHECK(dt.number_of_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_FULL_CELLS = 30; - std::cout << "dt.number_of_full_cells()=" << dt.number_of_full_cells() << std::endl; - BOOST_CHECK(dt.number_of_full_cells() == NUMBER_OF_FULL_CELLS); - - const int NUMBER_OF_FINITE_FULL_CELLS = 6; - std::cout << "dt.number_of_finite_full_cells()=" << dt.number_of_finite_full_cells() << std::endl; - BOOST_CHECK(dt.number_of_finite_full_cells() == NUMBER_OF_FINITE_FULL_CELLS); - - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_dt(dt); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 8; - std::cout << "alpha_complex_from_dt.dimension()=" << alpha_complex_from_dt.dimension() << std::endl; - BOOST_CHECK(alpha_complex_from_dt.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_complex_from_dt.filtration()=" << alpha_complex_from_dt.filtration() << std::endl; - BOOST_CHECK(alpha_complex_from_dt.filtration() == FILTRATION); + std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - std::cout << "alpha_complex_from_dt.num_vertices()=" << alpha_complex_from_dt.num_vertices() << std::endl; - BOOST_CHECK(alpha_complex_from_dt.num_vertices() == NUMBER_OF_VERTICES); + const int NUMBER_OF_VERTICES = 10; + std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 997; - std::cout << "alpha_complex_from_dt.num_simplices()=" << alpha_complex_from_dt.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_dt.num_simplices() == NUMBER_OF_SIMPLICES); -} + const int NUMBER_OF_SIMPLICES = 1007; + std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); +} diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 72e8390a..4fe69ce5 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -15,7 +15,7 @@ if(CGAL_FOUND) include( ${EIGEN3_USE_FILE} ) include_directories (BEFORE "../../include") - add_definitions(-DDEBUG_TRACES) + #add_definitions(-DDEBUG_TRACES) add_executable ( AlphaComplexUnitTest Alpha_complex_unit_test.cpp ) target_link_libraries(AlphaComplexUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) add_test(AlphaComplexUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUnitTest) diff --git a/src/Alpha_complex/test/README b/src/Alpha_complex/test/README index 244a2b84..45b87d91 100644 --- a/src/Alpha_complex/test/README +++ b/src/Alpha_complex/test/README @@ -7,6 +7,6 @@ make To launch with details: *********************** -./AlphaShapesUnitTest --report_level=detailed --log_level=all +./AlphaComplexUnitTest --report_level=detailed --log_level=all ==> echo $? returns 0 in case of success (non-zero otherwise) diff --git a/src/Alpha_complex/test/S4_100.off b/src/Alpha_complex/test/S4_100.off index 0a5dc58c..cd017e12 100644 --- a/src/Alpha_complex/test/S4_100.off +++ b/src/Alpha_complex/test/S4_100.off @@ -1,5 +1,5 @@ -OFF -100 0 0 +nOFF +4 100 0 0 0.562921 -0.735261 -0.256472 0.277007 -0.803733 -0.0527915 -0.315125 0.501918 -0.24946 -0.354982 -0.410773 -0.801887 diff --git a/src/Alpha_complex/test/S8_10.off b/src/Alpha_complex/test/S8_10.off index 1d67e10f..4e147c44 100644 --- a/src/Alpha_complex/test/S8_10.off +++ b/src/Alpha_complex/test/S8_10.off @@ -1,5 +1,5 @@ -OFF -10 0 0 +nOFF +8 10 0 0 0.440036 -0.574754 -0.200485 0.216537 -0.501251 -0.0329236 -0.196529 0.313023 -0.129367 -0.184089 -0.213021 -0.415848 0.783529 -0.0438025 0.317256 0.120749 0.132429 0.683748 -0.124536 -0.166133 -0.540695 -0.0887576 0.390234 -0.139031 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e0d5ff28..e2271efd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,7 @@ else() LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) include_directories(include/) + add_subdirectory(example/common) add_subdirectory(example/Simplex_tree) add_subdirectory(example/Persistent_cohomology) add_subdirectory(example/Skeleton_blocker) diff --git a/src/Doxyfile b/src/Doxyfile index 62412627..9d4bc9c8 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -811,7 +811,8 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = +EXAMPLE_PATH = common/example \ + common/test # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt new file mode 100644 index 00000000..ae30da54 --- /dev/null +++ b/src/common/example/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIDelaunayTriangulationOffFileReadWrite) + +# need CGAL 4.6 +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + + add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) + target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(dtoffrw ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/alphashapedoc.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) + + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () +endif() diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp new file mode 100644 index 00000000..d1aa7988 --- /dev/null +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -0,0 +1,55 @@ +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" + +#include +#include + +#include +#include +#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; +typedef CGAL::Delaunay_triangulation T; +// The triangulation uses the default instantiation of the +// TriangulationDataStructure template parameter + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " inputFile.off outputFile.off" << std::endl; + exit(-1); // ----- >> +} + +int main(int argc, char **argv) { + if (argc != 3) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + std::string offInputFile(argv[1]); + // Read the OFF file (input file name given as parameter) and triangulates points + Gudhi::Delaunay_triangulation_off_reader off_reader(offInputFile); + // Check the read operation was correct + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << offInputFile << std::endl; + exit(-1); // ----- >> + } + + // Retrieve the triangulation + T* triangulation = off_reader.get_complex(); + // Operations on triangulation + std::cout << "Number of vertices= " << triangulation->number_of_vertices() << std::endl; + std::cout << "Number of finite full cells= " << triangulation->number_of_finite_full_cells() << std::endl; + + std::string outFileName(argv[2]); + std::string offOutputFile(outFileName); + // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces + Gudhi::Delaunay_triangulation_off_writer off_writer(offOutputFile, triangulation); + + // Check the write operation was correct + if (!off_writer.is_valid()) { + std::cerr << "Unable to write file " << offOutputFile << std::endl; + exit(-1); // ----- >> + } + + return 0; +} \ No newline at end of file diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h new file mode 100644 index 00000000..de5fa2af --- /dev/null +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -0,0 +1,308 @@ +/* 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 Saclay (France) + * + * 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 . + */ +#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ +#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ + +#include +#include +#include +#include + +#include "gudhi/Off_reader.h" + +namespace Gudhi { + +/** \brief OFF file visitor implementation according to Off_reader in order to construct a CGAL Delaunay triangulation. + * + * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page + * http://doc.cgal.org/latest/Triangulation/ + */ +template +class Delaunay_triangulation_off_visitor_reader { + private: + Complex* _complex; + typedef typename Complex::Point Point; + + public: + + // TODO(VR) : Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. + + /** \brief Delaunay_triangulation_off_visitor_reader constructor + * + * @param[in] _complex_ptr pointer on a Delaunay triangulation. + */ + Delaunay_triangulation_off_visitor_reader(Complex* _complex_ptr) + : _complex(nullptr) { } + + /** \brief Off_reader visitor init implementation. + * + * The init parameters are set from OFF file header. + * Dimension value is required in order to construct Delaunay triangulation. + * + * @param[in] dim space dimension of vertices. + * @param[in] num_vertices number of vertices in the OFF file (not used). + * @param[in] num_faces number of faces in the OFF file (not used). + * @param[in] num_edges number of edges in the OFF file (not used). + */ + void init(int dim, int num_vertices, int num_faces, int num_edges) { +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; +#endif // DEBUG_TRACES + if (num_faces > 0) { + std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << + "file for Delaunay triangulation - faces are computed." << std::endl; + } + if (num_edges > 0) { + std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << + "file for Delaunay triangulation - edges are computed." << std::endl; + } + // Complex construction with dimension from file + _complex = new Complex(dim); + } + + /** \brief Off_reader visitor point implementation. + * + * The point function is called on each vertex line from OFF file. + * This function inserts the vertex in the Delaunay triangulation. + * + * @param[in] point vector of vertex coordinates. + */ + void point(const std::vector& point) { +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::point "; + for (auto coordinate : point) { + std::cout << coordinate << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + _complex->insert(Point(point.size(), point.begin(), point.end())); + } + + // Off_reader visitor maximal_face implementation - not used + void maximal_face(const std::vector& face) { + // For Delaunay Triangulation, only points are read + } + + // Off_reader visitor done implementation - not used + void done() { + // Nothing to be done on end of OFF file read + } + + /** \brief Returns the constructed Delaunay triangulation. + * + * @return A pointer on the Delaunay triangulation. + * + * @warning The returned pointer can be nullptr. + */ + Complex* get_complex() const { + return _complex; + } +}; + +/** \brief OFF file reader implementation in order to construct a Delaunay triangulation. + * + * This class is using the Delaunay_triangulation_off_visitor_reader to visit the OFF file according to Off_reader. + * + * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page + * http://doc.cgal.org/latest/Triangulation/ + * + * \section Example + * + * This example loads points from an OFF file and builds the Delaunay triangulation. + * Then, it is asked to display the number of vertices and finites full cells from the Delaunay triangulation. + * + * \include Delaunay_triangulation_off_rw.cpp + * + * When launching: + * + * \code $> ./dtoffrw ../../data/points/alphashapedoc.off triangulated.off + * \endcode + * + * the program output is: + * + * \include dtoffrw_alphashapedoc_result.txt + */ +template +class Delaunay_triangulation_off_reader { + public: + + /** \brief Reads the OFF file and constructs the Delaunay triangulation from the points + * that are in the OFF file. + * + * @param[in] name_file OFF file to read. + * + * @warning Check with is_valid() function to see if read operation was successful. + */ + Delaunay_triangulation_off_reader(const std::string & name_file) + : valid_(false) { + std::ifstream stream(name_file); + if (stream.is_open()) { + Delaunay_triangulation_off_visitor_reader off_visitor(_complex); + Off_reader off_reader(stream); + valid_ = off_reader.read(off_visitor); + if (valid_) { + _complex = off_visitor.get_complex(); + if (_complex == nullptr) { + std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader off_visitor returns an empty pointer" << std::endl; + valid_ = false; + } + } + } else { + std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << + name_file << std::endl; + } + + } + + /** \brief Returns if the OFF file read operation was successful or not. + * + * @return OFF file read status. + */ + bool is_valid() const { + return valid_; + } + + /** \brief Returns the constructed Delaunay triangulation. + * + * @return A pointer on the Delaunay triangulation. + * + * @warning The returned pointer can be nullptr. + */ + Complex* get_complex() const { + if (valid_) + return _complex; + return nullptr; + + } + + private: + /** \brief OFF file read status.*/ + bool valid_; + /** \brief A pointer on the Delaunay triangulation.*/ + Complex* _complex; +}; + +/** \brief OFF file writer from a Delaunay triangulation. + * + * This class constructs the OFF file header according to http://www.geomview.org/docs/html/OFF.html + * + * The header is followed by the list of points coordinates (Delaunay triangulation vertices) + * + * And finally is followed by the list of faces (Delaunay triangulation finite full cells) + * + * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page + * http://doc.cgal.org/latest/Triangulation/ + * + * \section Example + * + * This example loads points from an OFF file and builds the Delaunay triangulation. + * Then, the Delaunay triangulation is saved in a new file including the triangulation as a list of faces. + * + * \include Delaunay_triangulation_off_rw.cpp + * + * When launching: + * + * \code $> ./dtoffrw ../../data/points/alphashapedoc.off triangulated.off + * \endcode + * + * The result will be an OFF file of dimension 2 with the 7 points from alphashapedoc.off followed by the 6 + * triangulations of dimension 3 (the first value on each faces): + * \include dtoffrw_alphashapedoc_result.off + */ +template +class Delaunay_triangulation_off_writer { + public: + typedef typename Complex::Point Point; + + /** \brief Writes the OFF file from the Delaunay triangulation + * + * @param[in] name_file OFF file to write. + * @param[in] complex_ptr pointer on a Delaunay triangulation. + * + * @warning Check with is_valid() function to see if write operation was successful. + */ + Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) + : valid_(false) { + std::ofstream stream(name_file); + if (stream.is_open()) { + if (complex_ptr->current_dimension() == 3) { + // OFF header + stream << "OFF" << std::endl; + // no endl on next line - don't know why... + stream << complex_ptr->number_of_vertices() << " " << complex_ptr->number_of_finite_full_cells() << " 0"; + } else { + // nOFF header + stream << "nOFF" << std::endl; + // no endl on next line - don't know why... + stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << + complex_ptr->number_of_finite_full_cells() << " 0"; + + } + + // bimap to retrieve vertex handles from points and vice versa + std::map< Point, int > points_to_vh; + // Start to insert at default handle value + int vertex_handle = int(); + + // Points list + for (auto vit = complex_ptr->vertices_begin(); vit != complex_ptr->vertices_end(); ++vit) { + for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { + stream << *Coord << " "; + } + stream << std::endl; + points_to_vh[vit->point()] = vertex_handle; + vertex_handle++; + } + + for (auto cit = complex_ptr->finite_full_cells_begin(); cit != complex_ptr->finite_full_cells_end(); ++cit) { + std::vector vertexVector; + stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + stream << points_to_vh[(*vit)->point()] << " "; + } + stream << std::endl; + } + stream.close(); + valid_ = true; + } else { + std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << + name_file << std::endl; + } + } + + /** \brief Returns if the OFF write operation was successful or not. + * + * @return OFF file write status. + */ + bool is_valid() const { + return valid_; + } + + private: + /* \brief OFF file write status. */ + bool valid_; +}; + +} // namespace Gudhi + +#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index 618d1b4d..a8abb507 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -36,163 +36,150 @@ namespace Gudhi { -/** - * Read an off file and calls a visitor methods while reading it. - * An off file must have its first/snd line in this format : - * OFF - * num_vert num_faces num_edges - * - * A noff file must have its first/snd line in this format : - * nOFF - * dim num_vert num_faces num_edges - * - * The number of edges num_edges is optional and can be left to zero. +/** \brief OFF file reader top class visitor. + * + * OFF file must be conform to format described here : + * http://www.geomview.org/docs/html/OFF.html */ -class Off_reader{ -public: - Off_reader(std::ifstream& stream):stream_(stream){ - } -// Off_reader(const std::string& name):stream_(name){ -// if(!stream_.is_open()) -// std::cerr <<"could not open file \n"; -// } - - ~Off_reader(){ - stream_.close(); - } - - /** - * read an off file and calls the following methods : - * void init(int dim,int num_vertices,int num_faces,int num_edges); //num_edges may not be set - * void point(const std::vector& point); - * void maximal_face(const std::list& face); - * void done(); - * of the visitor when reading a point or a maximal face. - */ - template - bool read(OffVisitor& off_visitor){ - bool success_read_off_preambule = read_off_preambule(off_visitor); - if(!success_read_off_preambule) { - std::cerr <<"could not read off preambule\n"; - return false; - } - - bool success_read_off_points = read_off_points(off_visitor); - if(!success_read_off_points) { - std::cerr <<"could not read off points\n"; - return false; - } - - bool success_read_off_faces = read_off_faces(off_visitor); - if(!success_read_off_faces) { - std::cerr <<"could not read off faces\n"; - return false; - } - - off_visitor.done(); - return success_read_off_preambule && success_read_off_points && success_read_off_faces; - } - -private: - std::ifstream& stream_; - - struct Off_info{ - int dim; - int num_vertices; - int num_edges; - int num_faces; - }; - - Off_info off_info_; - - template - bool read_off_preambule(OffVisitor& off_visitor){ - std::string line; - if(!goto_next_uncomment_line(line)) return false; - - bool is_off_file = (line.find("OFF") != std::string::npos); - bool is_noff_file = (line.find("nOFF") != std::string::npos); - - if(!is_off_file && !is_noff_file) { - std::cerr << line<> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)){ - std::cerr << "incorrect number of vertices/faces/edges\n"; - return false; - } - } - else - if(!(iss >> off_info_.dim >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)){ - std::cerr << "incorrect number of vertices/faces/edges\n"; - return false; - } - off_visitor.init(off_info_.dim,off_info_.num_vertices,off_info_.num_faces,off_info_.num_edges); - - return true; - } - - bool goto_next_uncomment_line(std::string& uncomment_line){ - uncomment_line.clear(); - do - std::getline(stream_, uncomment_line); - while(uncomment_line[0] == '%');// || uncomment_line.empty()); - return (uncomment_line.size()>0 && uncomment_line[0] != '%'); - } - - - template - bool read_off_points(OffVisitor& visitor){ - int num_vertices_to_read = off_info_.num_vertices; - while(num_vertices_to_read--){ - std::string line; - if(!goto_next_uncomment_line(line)) return false; - std::vector point; - std::istringstream iss(line); - point.assign(std::istream_iterator(iss),std::istream_iterator()); -// if(point.size() != off_info_.dim) return false; - visitor.point(point); - } - return true; - } - - template - bool read_off_faces(OffVisitor& visitor){ - std::string line; - while(goto_next_uncomment_line(line)){ - std::istringstream iss(line); - int num_face_vertices; - iss >> num_face_vertices; - std::vector face; - face.assign(std::istream_iterator(iss),std::istream_iterator()); - if(!face.size() == off_info_.num_vertices) return false; - visitor.maximal_face(face); - } - return true; - } +class Off_reader { + public: + + Off_reader(std::ifstream& stream) : stream_(stream) { } + + ~Off_reader() { + stream_.close(); + } + + /** \brief + * Read an OFF file and calls the following methods : + * + * void init(int dim,int num_vertices,int num_faces,int num_edges); // from file header - num_edges may not be set + * + * void point(const std::vector& point); // for each point read + * + * void maximal_face(const std::list& face); // for each face read + * + * void done(); // upon file read is finished + * + * of the visitor when reading a point or a maximal face. Edges are not taken into account. + */ + template + bool read(OffVisitor& off_visitor) { + bool success_read_off_preambule = read_off_preambule(off_visitor); + if (!success_read_off_preambule) { + std::cerr << "could not read off preambule\n"; + return false; + } + + bool success_read_off_points = read_off_points(off_visitor); + if (!success_read_off_points) { + std::cerr << "could not read off points\n"; + return false; + } + + bool success_read_off_faces = read_off_faces(off_visitor); + if (!success_read_off_faces) { + std::cerr << "could not read off faces\n"; + return false; + } + + off_visitor.done(); + return success_read_off_preambule && success_read_off_points && success_read_off_faces; + } + + private: + std::ifstream& stream_; + + struct Off_info { + int dim; + int num_vertices; + int num_edges; + int num_faces; + }; + + Off_info off_info_; + + template + bool read_off_preambule(OffVisitor& off_visitor) { + std::string line; + if (!goto_next_uncomment_line(line)) return false; + + bool is_off_file = (line.find("OFF") != std::string::npos); + bool is_noff_file = (line.find("nOFF") != std::string::npos); + + if (!is_off_file && !is_noff_file) { + std::cerr << line << std::endl; + std::cerr << "missing off header\n"; + return false; + } + + if (!goto_next_uncomment_line(line)) return false; + std::istringstream iss(line); + if ((is_off_file) && (!is_noff_file)) { + off_info_.dim = 3; + if (!(iss >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) { + std::cerr << "incorrect number of vertices/faces/edges\n"; + return false; + } + } else + if (!(iss >> off_info_.dim >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) { + std::cerr << "incorrect number of vertices/faces/edges\n"; + return false; + } + off_visitor.init(off_info_.dim, off_info_.num_vertices, off_info_.num_faces, off_info_.num_edges); + + return true; + } + + bool goto_next_uncomment_line(std::string& uncomment_line) { + uncomment_line.clear(); + do + std::getline(stream_, uncomment_line); while (uncomment_line[0] == '%'); + return (uncomment_line.size() > 0 && uncomment_line[0] != '%'); + } + + template + bool read_off_points(OffVisitor& visitor) { + int num_vertices_to_read = off_info_.num_vertices; + while (num_vertices_to_read--) { + std::string line; + if (!goto_next_uncomment_line(line)) return false; + std::vector point; + std::istringstream iss(line); + point.assign(std::istream_iterator(iss), std::istream_iterator()); + // if(point.size() != off_info_.dim) return false; + visitor.point(point); + } + return true; + } + + template + bool read_off_faces(OffVisitor& visitor) { + std::string line; + while (goto_next_uncomment_line(line)) { + std::istringstream iss(line); + int num_face_vertices; + iss >> num_face_vertices; + std::vector face; + face.assign(std::istream_iterator(iss), std::istream_iterator()); + if (!face.size() == off_info_.num_vertices) return false; + visitor.maximal_face(face); + } + return true; + } }; - template -void read_off(const std::string& name_file_off,OFFVisitor& vis){ - std::ifstream stream(name_file_off); - if(!stream.is_open()) - std::cerr <<"could not open file \n"; - else{ - Off_reader off_reader(stream); - off_reader.read(vis); - } +void read_off(const std::string& name_file_off, OFFVisitor& vis) { + std::ifstream stream(name_file_off); + if (!stream.is_open()) + std::cerr << "could not open file \n"; + else { + Off_reader off_reader(stream); + off_reader.read(vis); + } } - - } // namespace Gudhi - -#endif /* GUDHI_OFF_READER_H_ */ +#endif // GUDHI_OFF_READER_H_ diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt new file mode 100644 index 00000000..22783caf --- /dev/null +++ b/src/common/test/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIDelaunayTriangulationOffFileReadWriteUT) + +if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} --coverage") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} --coverage") +endif() + +# need CGAL 4.6 +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + + add_executable ( dtoffrw_UT dtoffrw_unit_test.cpp ) + target_link_libraries(dtoffrw_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + + # Unitary tests + add_test(dtoffrw_UT ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_UT) + + if (DIFF_PATH) + add_test(diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) + endif() + + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () +endif() + + + + + +cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/common/include/gudhi") diff --git a/src/common/test/README b/src/common/test/README new file mode 100644 index 00000000..f2a7eb5a --- /dev/null +++ b/src/common/test/README @@ -0,0 +1,14 @@ +To compile: +*********** + +cmake . +make + +To launch with details: +*********************** + +./dtoffrw_UT --report_level=detailed --log_level=all + + ==> echo $? returns 0 in case of success (non-zero otherwise) + + diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off new file mode 100644 index 00000000..13c255c6 --- /dev/null +++ b/src/common/test/dtoffrw_alphashapedoc_result.off @@ -0,0 +1,15 @@ +nOFF +2 7 6 0 +1 1 +7 0 +4 6 +9 6 +0 14 +2 19 +9 17 +3 1 2 3 +3 4 3 2 +3 5 1 3 +3 5 3 7 +3 7 3 4 +3 6 5 7 diff --git a/src/common/test/dtoffrw_alphashapedoc_result.txt b/src/common/test/dtoffrw_alphashapedoc_result.txt new file mode 100644 index 00000000..57761d14 --- /dev/null +++ b/src/common/test/dtoffrw_alphashapedoc_result.txt @@ -0,0 +1,3 @@ +Number of vertices= 7 +Number of finite full cells= 6 + diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp new file mode 100644 index 00000000..4905d845 --- /dev/null +++ b/src/common/test/dtoffrw_unit_test.cpp @@ -0,0 +1,91 @@ +/* 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 Saclay (France) + * + * 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 . + */ + +#define BOOST_TEST_MODULE DelaunayTriangulationOffFileReadWrite test + +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" + +#include +#include + +#include +#include +#include + +#include +#include +//#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; +typedef CGAL::Delaunay_triangulation T; + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation_doc_test ) +{ + // Read the OFF file (input file name given as parameter) and triangulates points + Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphashapedoc.off"); + // Check the read operation was correct + BOOST_CHECK(off_reader.is_valid()); + + // Retrieve the triangulation + T* triangulation = off_reader.get_complex(); + BOOST_CHECK(triangulation != nullptr); + // Operations on triangulation + BOOST_CHECK(triangulation->number_of_vertices() == 7); + BOOST_CHECK(triangulation->number_of_finite_full_cells() == 6); + + // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces + Gudhi::Delaunay_triangulation_off_writer off_writer("UT.off", triangulation); + + // Check the write operation was correct + BOOST_CHECK(off_writer.is_valid()); + + delete triangulation; +} + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) +{ + Gudhi::Delaunay_triangulation_off_reader off_reader("pouetpouet_tralala.off"); + // Check the read operation was correct + BOOST_CHECK(!off_reader.is_valid()); + T* triangulation = off_reader.get_complex(); + BOOST_CHECK(triangulation == nullptr); +} + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_write_test ) +{ + // Read the OFF file (input file name given as parameter) and triangulates points + Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphashapedoc.off"); + + // Retrieve the triangulation + T* triangulation = off_reader.get_complex(); + + // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces + Gudhi::Delaunay_triangulation_off_writer off_writer("/pouetpouet_tralala/pouetpouet_tralala/pouetpouet_tralala.off", triangulation); + + // Check the write operation was correct + BOOST_CHECK(!off_writer.is_valid()); + + delete triangulation; +} + -- cgit v1.2.3 From ea986c68192c7536716d139e5a5f0a30a76f0fc1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 19 Jun 2015 11:08:21 +0000 Subject: Alpha complex documetation - 1st part git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@630 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b64e860b0fb6d60e706784605f699349ea17a869 --- biblio/bibliography.bib | 16 ++ .../example/Alpha_complex_from_off.cpp | 22 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 207 +++++++++++---------- src/Alpha_complex/test/CMakeLists.txt | 8 +- src/Alpha_complex/test/alphaoffreader_for_doc.txt | 27 +++ src/Doxyfile | 5 +- src/common/test/CMakeLists.txt | 6 +- 7 files changed, 163 insertions(+), 128 deletions(-) create mode 100644 src/Alpha_complex/test/alphaoffreader_for_doc.txt (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index 3fd1c10a..859696b4 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -897,6 +897,22 @@ language={English} bibsource = {DBLP, http://dblp.uni-trier.de} } +@ARTICLE{AlphaShapesDefinition, + author = {N. Akkiraju, H. Edelsbrunner, M. Facello, P. Fu, E. P. Mucke, and C. Varela}, + title = {\href{http://pub.ist.ac.at/~edels/Papers/1995-P-06-AlphaShapesSoftware.pdf}{Alpha shapes: definition and software}}, + journal = {Proc. Internat. Comput. Geom. Software Workshop 1995}, + year = {1995}, + bibsource = {http://pub.ist.ac.at} +} + +@ARTICLE{AlphaShapesIntroduction, + author = {Kaspar Fischer}, + title = {\href{http://www.cs.uu.nl/docs/vakken/ddm/texts/Delaunay/alphashapes.pdf}{Introduction to Alpha Shapes}}, + journal = {Unknown}, + year = {Unknown}, + bibsource = {http://www.cs.uu.nl} +} + misc{buddha_stanford_scan, author = "", title = "The Stanford 3D Scanning Repository", diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index d129ebf7..0d7af117 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,25 +1,3 @@ -/* 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) 2014 INRIA Saclay (France) - * - * 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 . - */ - // to construct a Delaunay_triangulation from a OFF file #include "gudhi/Delaunay_triangulation_off_io.h" #include "gudhi/Alpha_complex.h" diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index d25c05cb..44741e3b 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -52,17 +52,37 @@ namespace alphacomplex { #define Kinit(f) =k.f() /** \defgroup alpha_complex Alpha complex in dimension N - * -
Implementations:
- Alpha complex in dimension N are a subset of Delaunay Triangulation in dimension N. - - - * \author Vincent Rouvreau - * \version 1.0 - * \date 2015 - * \copyright GNU General Public License v3. * @{ + * \author Vincent Rouvreau + * + * \section Definition + * + * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation in dimension N. + * + * The filtration value of each simplex is computed from the alpha value of the simplex if it is Gabriel or + * from the alpha value of the simplex coface that makes the simplex not Gabriel. + * + * Please refer to \cite AlphaShapesDefinition for the alpha complex definition or to + * \cite AlphaShapesIntroduction for alpha complex concept vulgarization. + * + * \section Example + * + * This example loads points from an OFF file, builds the Delaunay triangulation, and finally initialize the + * alpha complex with it. + * Then, it is asked to display information about the alpha complex. + * + * \include Alpha_complex_from_off.cpp + * + * When launching: + * + * \code $> ./alphaoffreader ../../data/points/alphashapedoc.off + * \endcode + * + * the program output is: + * + * \include alphaoffreader_for_doc.txt */ +/** @} */ // end defgroup alpha_complex /** * \brief Alpha complex data structure. @@ -74,89 +94,107 @@ namespace alphacomplex { * * */ -class Alpha_complex { +template +class Alpha_complex : public Simplex_tree<> { private: // From Simplex_tree - /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + // Type required to insert into a simplex_tree (with or without subfaces). typedef std::vector Vector_vertex; - /** \brief Simplex_handle type from simplex_tree.*/ - typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; - /** \brief Simplex_result is the type returned from simplex_tree insert function.*/ + // Simplex_result is the type returned from simplex_tree insert function. typedef typename std::pair Simplex_result; - /** \brief Filtration_simplex_range type from simplex_tree.*/ - typedef typename Gudhi::Simplex_tree<>::Filtration_simplex_range Filtration_simplex_range; - - /** \brief Simplex_vertex_range type from simplex_tree.*/ - typedef typename Gudhi::Simplex_tree<>::Simplex_vertex_range Simplex_vertex_range; - // From CGAL - /** \brief Kernel for the Delaunay_triangulation. Dimension can be set dynamically.*/ + // Kernel for the Delaunay_triangulation. Dimension can be set dynamically. typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - /** \brief Delaunay_triangulation type required to create an alpha-complex.*/ + + // Delaunay_triangulation type required to create an alpha-complex. typedef CGAL::Delaunay_triangulation Delaunay_triangulation; typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; - /** \brief Type required to compute squared radius, or side of bounded sphere on a vector of points.*/ + // Type required to compute squared radius, or side of bounded sphere on a vector of points. typedef std::vector Vector_of_CGAL_points; - /** \brief Vertex_iterator type from CGAL.*/ + // Vertex_iterator type from CGAL. typedef Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; - /** \brief Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ + // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; - + private: - /** \brief Alpha complex is represented internally by a simplex tree.*/ - Gudhi::Simplex_tree<> st_; /** \brief Boost bimap to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ Bimap_vertex cgal_simplextree; /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation; public: + /** \brief Alpha_complex constructor from an OFF file name. + * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize + * the Alpha_complex. + * + * @param[in] off_file_name OFF file [path and] name. + */ Alpha_complex(std::string& off_file_name) - : triangulation(nullptr) { + : triangulation(nullptr) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << off_file_name << std::endl; + std::cerr << "Alpha_complex - Unable to read file " << off_file_name << std::endl; exit(-1); // ----- >> } triangulation = off_reader.get_complex(); init(); } + /** \brief Alpha_complex constructor from a Delaunay triangulation. + * + * @param[in] triangulation_ptr Pointer on a Delaunay triangulation. + */ Alpha_complex(Delaunay_triangulation* triangulation_ptr) - : triangulation(triangulation_ptr) { + : triangulation(triangulation_ptr) { init(); } + /** \brief Alpha_complex destructor from a Delaunay triangulation. + * + * @warning Deletes the Delaunay triangulation. + */ ~Alpha_complex() { delete triangulation; } - Filtration_simplex_range filtration_simplex_range() { - return st_.filtration_simplex_range(); - } - - Simplex_vertex_range simplex_vertex_range(Simplex_handle sh) { - return st_.simplex_vertex_range(sh); - } - - /** \brief Returns the filtration value of a simplex. - * - * Called on the null_simplex, returns INFINITY. */ - Gudhi::Simplex_tree<>::Filtration_value filtration(Simplex_handle sh) { - return st_.filtration(sh); - } - private: - + /** \brief Initialize the Alpha_complex from the Delaunay triangulation. + * + * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more + * than 0. + * + * Initialization can be launched once. + */ void init() { - st_.set_dimension(triangulation->maximal_dimension()); + if (triangulation == nullptr) { + std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation" << std::endl; + return; // ----- >> + } + if (triangulation->number_of_vertices() < 1) { + std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices" << std::endl; + return; // ----- >> + } + if (triangulation->maximal_dimension() < 1) { + std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation" << std::endl; + return; // ----- >> + } + if (num_vertices() > 0) { + std::cerr << "Alpha_complex init - Cannot init twice" << std::endl; + return; // ----- >> + } + + set_dimension(triangulation->maximal_dimension()); // -------------------------------------------------------------------------------------------- // bimap to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa @@ -187,7 +225,7 @@ class Alpha_complex { std::cout << std::endl; #endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - Simplex_result insert_result = st_.insert_simplex_and_subfaces(vertexVector, + Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); if (!insert_result.second) { std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; @@ -198,16 +236,16 @@ class Alpha_complex { Filtration_value filtration_max = 0.0; // -------------------------------------------------------------------------------------------- // ### For i : d -> 0 - for (int decr_dim = st_.dimension(); decr_dim >= 0; decr_dim--) { + for (int decr_dim = dimension(); decr_dim >= 0; decr_dim--) { // ### Foreach Sigma of dim i - for (auto f_simplex : st_.skeleton_simplex_range(decr_dim)) { - int f_simplex_dim = st_.dimension(f_simplex); + for (auto f_simplex : skeleton_simplex_range(decr_dim)) { + int f_simplex_dim = dimension(f_simplex); if (decr_dim == f_simplex_dim) { Vector_of_CGAL_points pointVector; #ifdef DEBUG_TRACES std::cout << "Sigma of dim " << decr_dim << " is"; #endif // DEBUG_TRACES - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + for (auto vertex : simplex_vertex_range(f_simplex)) { pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); #ifdef DEBUG_TRACES std::cout << " " << vertex; @@ -217,20 +255,20 @@ class Alpha_complex { std::cout << std::endl; #endif // DEBUG_TRACES // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (isnan(st_.filtration(f_simplex))) { + if (isnan(filtration(f_simplex))) { Filtration_value alpha_complex_filtration = 0.0; // No need to compute squared_radius on a single point - alpha is 0.0 if (f_simplex_dim > 0) { // squared_radius function initialization Kernel k; Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - + alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } - st_.assign_filtration(f_simplex, alpha_complex_filtration); + assign_filtration(f_simplex, alpha_complex_filtration); filtration_max = fmax(filtration_max, alpha_complex_filtration); #ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl; #endif // DEBUG_TRACES } propagate_alpha_filtration(f_simplex, decr_dim); @@ -242,30 +280,30 @@ class Alpha_complex { #ifdef DEBUG_TRACES std::cout << "filtration_max=" << filtration_max << std::endl; #endif // DEBUG_TRACES - st_.set_filtration(filtration_max); + set_filtration(filtration_max); } template void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { // ### Foreach Tau face of Sigma - for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { + for (auto f_boundary : boundary_simplex_range(f_simplex)) { #ifdef DEBUG_TRACES std::cout << " | --------------------------------------------------" << std::endl; std::cout << " | Tau "; - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + for (auto vertex : simplex_vertex_range(f_boundary)) { std::cout << vertex << " "; } std::cout << "is a face of Sigma" << std::endl; - std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; + std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl; #endif // DEBUG_TRACES // ### If filt(Tau) is not NaN - if (!isnan(st_.filtration(f_boundary))) { + if (!isnan(filtration(f_boundary))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) - Filtration_value alpha_complex_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); - st_.assign_filtration(f_boundary, alpha_complex_filtration); + Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); + assign_filtration(f_boundary, alpha_complex_filtration); // No need to check for filtration_max, alpha_complex_filtration is a min of an existing filtration value #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl; #endif // DEBUG_TRACES // ### Else } else { @@ -275,11 +313,11 @@ class Alpha_complex { // insert the Tau points in a vector for is_gabriel function Vector_of_CGAL_points pointVector; Vertex_handle vertexForGabriel = Vertex_handle(); - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + for (auto vertex : simplex_vertex_range(f_boundary)) { pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); } // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + for (auto vertex : simplex_vertex_range(f_simplex)) { if (std::find(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertex))->point()) == pointVector.end()) { // vertex is not found in Tau @@ -300,46 +338,17 @@ class Alpha_complex { if ((is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) == CGAL::ON_BOUNDED_SIDE)) { // ### filt(Tau) = filt(Sigma) - Filtration_value alpha_complex_filtration = st_.filtration(f_simplex); - st_.assign_filtration(f_boundary, alpha_complex_filtration); + Filtration_value alpha_complex_filtration = filtration(f_simplex); + assign_filtration(f_boundary, alpha_complex_filtration); // No need to check for filtration_max, alpha_complex_filtration is an existing filtration value #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = filt(Sigma) = " << st_.filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl; #endif // DEBUG_TRACES } } } } } - public: - - /** \brief Returns the number of vertices in the complex. */ - size_t num_vertices() { - return st_.num_vertices(); - } - - /** \brief Returns the number of simplices in the complex. - * - * Does not count the empty simplex. */ - const unsigned int& num_simplices() const { - return st_.num_simplices(); - } - - /** \brief Returns an upper bound on the dimension of the simplicial complex. */ - int dimension() { - return st_.dimension(); - } - - /** \brief Returns an upper bound of the filtration values of the simplices. */ - Filtration_value filtration() { - return st_.filtration(); - } - - friend std::ostream& operator<<(std::ostream& os, const Alpha_complex & alpha_complex) { - Gudhi::Simplex_tree<> st = alpha_complex.st_; - os << st << std::endl; - return os; - } }; } // namespace alphacomplex diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 0bd55433..79300790 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -16,9 +16,11 @@ if(CGAL_FOUND) include_directories (BEFORE "../../include") #add_definitions(-DDEBUG_TRACES) - add_executable ( AlphaComplexUnitTest Alpha_complex_unit_test.cpp ) - target_link_libraries(AlphaComplexUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - add_test(AlphaComplexUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUnitTest) + add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp ) + target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_test(AlphaComplexUT ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUT + # XML format for Jenkins xUnit plugin + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/AlphaComplexUT.xml --log_level=test_suite --report_level=no) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha complex feature.") diff --git a/src/Alpha_complex/test/alphaoffreader_for_doc.txt b/src/Alpha_complex/test/alphaoffreader_for_doc.txt new file mode 100644 index 00000000..1153f097 --- /dev/null +++ b/src/Alpha_complex/test/alphaoffreader_for_doc.txt @@ -0,0 +1,27 @@ +Alpha complex is of dimension 2 - 25 simplices - 7 vertices. +Iterator on alpha complex simplices in the filtration order, with [filtration value]: + ( 1 ) -> [0] + ( 2 ) -> [0] + ( 3 ) -> [0] + ( 4 ) -> [0] + ( 5 ) -> [0] + ( 6 ) -> [0] + ( 7 ) -> [0] + ( 4 3 ) -> [6.25] + ( 6 5 ) -> [7.25] + ( 3 1 ) -> [8.5] + ( 2 1 ) -> [9.25] + ( 4 2 ) -> [10] + ( 3 2 ) -> [11.25] + ( 4 3 2 ) -> [12.5] + ( 3 2 1 ) -> [12.9959] + ( 7 6 ) -> [13.25] + ( 5 3 ) -> [20] + ( 7 5 ) -> [22.7367] + ( 7 6 5 ) -> [22.7367] + ( 7 4 ) -> [30.25] + ( 7 3 ) -> [36.5] + ( 7 4 3 ) -> [36.5] + ( 7 5 3 ) -> [37.2449] + ( 5 1 ) -> [59.7107] + ( 5 3 1 ) -> [59.7107] diff --git a/src/Doxyfile b/src/Doxyfile index 9d4bc9c8..49ec4768 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -812,8 +812,9 @@ EXCLUDE_SYMBOLS = # command). EXAMPLE_PATH = common/example \ - common/test - + common/test \ + Alpha_complex/example \ + Alpha_complex/test \ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index e4ac6c7b..1b4dd6e0 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -23,10 +23,12 @@ if(CGAL_FOUND) target_link_libraries(dtoffrw_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) # Unitary tests - add_test(dtoffrw_UT ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_UT) + add_test(dtoffrw_UT ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_UT + # XML format for Jenkins xUnit plugin + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/dtoffrw_UT.xml --log_level=test_suite --report_level=no) if (DIFF_PATH) - add_test(diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) + add_test(dtoffrw_diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) endif() else() -- cgit v1.2.3 From 01b0bf84f780b9998a48f0dbe338319da1c6d6f2 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 23 Jun 2015 13:50:46 +0000 Subject: Alpha complex documentation - 2nd part git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@633 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 023b5aaa57593a4e8e77cf12f388559b638f0eb1 --- data/points/alphacomplexdoc.off | 10 + data/points/alphashapedoc.off | 10 - src/Alpha_complex/doc/alpha_complex_doc.ipe | 438 ++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc.png | Bin 0 -> 46226 bytes src/Alpha_complex/doc/alpha_complex_doc_135.ipe | 514 +++++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 0 -> 94098 bytes .../doc/alpha_complex_doc_alpha_shape.ipe | 493 ++++++++++++++++++++ .../doc/alpha_complex_doc_alpha_shape.png | Bin 0 -> 70425 bytes src/Alpha_complex/include/gudhi/Alpha_complex.h | 90 +++- src/Doxyfile | 3 +- 10 files changed, 1531 insertions(+), 27 deletions(-) create mode 100755 data/points/alphacomplexdoc.off delete mode 100755 data/points/alphashapedoc.off create mode 100644 src/Alpha_complex/doc/alpha_complex_doc.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc.png create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.png create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/data/points/alphacomplexdoc.off b/data/points/alphacomplexdoc.off new file mode 100755 index 00000000..bb790193 --- /dev/null +++ b/data/points/alphacomplexdoc.off @@ -0,0 +1,10 @@ +nOFF +2 7 0 0 +1.0 1.0 +7.0 0.0 +4.0 6.0 +9.0 6.0 +0.0 14.0 +2.0 19.0 +9.0 17.0 + diff --git a/data/points/alphashapedoc.off b/data/points/alphashapedoc.off deleted file mode 100755 index bb790193..00000000 --- a/data/points/alphashapedoc.off +++ /dev/null @@ -1,10 +0,0 @@ -nOFF -2 7 0 0 -1.0 1.0 -7.0 0.0 -4.0 6.0 -9.0 6.0 -0.0 14.0 -2.0 19.0 -9.0 17.0 - diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe new file mode 100644 index 00000000..6257b2f4 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -0,0 +1,438 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +Delaunay triangulation +1 +2 +3 +4 +5 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +1 +2 +3 +3 +2 +3 +3 +4 +4 +4 +4 +5 +5 +5 +5 +7 +7 +7 +7 +7 +7 +6 +7 +6 + +4 0 0 4 320 704 e + + +322.919 706.788 m +317.189 701.058 l +317.189 701.203 l + + +317.551 706.934 m +322.629 701.058 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +220 670 l + + +230 680 m +230 670 l + + +220 660 m +220 650 l + + +230 660 m +230 650 l + + +260 680 m +260 670 l + + +260 660 m +260 650 l + + +300 680 m +300 670 l + + +300 680 m +290 670 l + + +290 660 m +290 650 l + + +300 660 m +300 650 l + + +330 680 m +330 670 l + + +350 680 m +350 670 l + + +350 660 m +350 650 l + + +320 700 m +240 690 l + + +320 700 m +270 690 l + + +320 700 m +310 690 l + + +320 700 m +330 690 l + + +320 700 m +350 690 l + + +320 700 m +380 690 l + + +320 700 m +400 690 l + + +240 620 m +220 600 l + + +240 620 m +220 640 l + +Simplex tree structure + +280 630 m +170 630 l + + +280 610 m +170 610 l + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png new file mode 100644 index 00000000..ff51ea9a Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe new file mode 100644 index 00000000..df55639a --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe @@ -0,0 +1,514 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +Cell [5,3,1] +1 +2 +3 +4 +5 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + + +77.2727 0 0 77.2727 243.636 591.818 e + + + +243.428 591.569 m +186.061 643.28 l + +$\alpha_{531}$ + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[3,1] is Gabriel $\rightarrow$ $\alpha_{31}$ is not$\\$ +modified (NaN) + +1 +2 +3 +4 +5 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{31}$ + +290 530 m +320 580 l + + +29.1548 0 0 29.1548 305 555 e + + + +304.883 555.015 m +334.509 555.015 l + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[1,5] is not Gabriel $\rightarrow$ $\alpha_{15} = \alpha_{135}$ +1 +2 +3 +4 +5 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{15}$ + +290 530 m +280 660 l + + +65.192 0 0 65.192 285 595 e + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +1 +2 +3 +4 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{35}$ +5 + +406.093 497.775 m +446.094 418.092 l + + +44.5799 0 0 44.5799 425.934 457.774 e + + + +425.854 457.774 m +470.795 457.774 l + +[3,5] is Gabriel $\rightarrow$ $\alpha_{35}$ is not modified (NaN) + + +205.028 596.091 m +110.946 544.02 l + + +280.768 588.99 m +280.768 547.57 l + + +341.123 594.316 m +413.904 554.079 l + +For all faces of [5,3,1] +N.B. : is Gabriel on a single point has no sense. +Dimension =2 - $\sigma$ = [5,3,1] + + +247.333 430.892 m +311.764 430.892 l + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png new file mode 100644 index 00000000..edf61368 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc_135.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe new file mode 100644 index 00000000..192ea772 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe @@ -0,0 +1,493 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Alpha shape +1 +2 +3 +4 +5 +6 +7 +1 +2 +3 +3 +2 +3 +3 +4 +4 +4 +4 +5 +5 +5 +5 +7 +7 +7 +7 +7 +7 +6 +7 +6 + +4 0 0 4 320 704 e + + +322.919 706.788 m +317.189 701.058 l +317.189 701.203 l + + +317.551 706.934 m +322.629 701.058 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +220 670 l + + +230 680 m +230 670 l + + +220 660 m +220 650 l + + +230 660 m +230 650 l + + +260 680 m +260 670 l + + +260 660 m +260 650 l + + +300 680 m +300 670 l + + +300 680 m +290 670 l + + +290 660 m +290 650 l + + +300 660 m +300 650 l + + +330 680 m +330 670 l + + +350 680 m +350 670 l + + +350 660 m +350 650 l + + +320 700 m +240 690 l + + +320 700 m +270 690 l + + +320 700 m +310 690 l + + +320 700 m +330 690 l + + +320 700 m +350 690 l + + +320 700 m +380 690 l + + +320 700 m +400 690 l + +Alpha complex structure + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +60 710 m +40 660 l + + +40 660 m +130 690 l + + +130 690 m +60 710 l + + +40 660 m +80 580 l + + +80 580 m +130 580 l +130 580 l + + +130 580 m +110 520 l + + +110 520 m +50 530 l +50 530 l +50 530 l + + +50 530 m +80 580 l + + +80 580 m +110 520 l +110 520 l + + +130 580 m +130 690 l + + + +108.275 743.531 m +166.45 743.531 l + +$\alpha$ +filtration value $> \alpha$ are greyed + +280 660 m +300 680 l + + +280 660 m +300 640 l + + +370 660 m +350 680 l + + +370 660 m +350 640 l + + +290 670 m +360 670 l + + +290 650 m +360 650 l + +equivalent + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png new file mode 100644 index 00000000..516de126 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png differ diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 44741e3b..191ff853 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -51,47 +51,105 @@ namespace alphacomplex { #define Kinit(f) =k.f() -/** \defgroup alpha_complex Alpha complex in dimension N - * @{ +/** \tableofcontents + * \defgroup alpha_complex Alpha complex + * * \author Vincent Rouvreau - * - * \section Definition * - * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation in dimension N. + * @{ + * + * \section definition Definition + * + * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation. * * The filtration value of each simplex is computed from the alpha value of the simplex if it is Gabriel or * from the alpha value of the simplex coface that makes the simplex not Gabriel. * - * Please refer to \cite AlphaShapesDefinition for the alpha complex definition or to - * \cite AlphaShapesIntroduction for alpha complex concept vulgarization. + * Please refer to \cite AlphaShapesDefinition for a more complete alpha complex definition. * - * \section Example + * Alpha complex are interesting because it looks like an \ref alpha-shape "Alpha shape" as described in + * \cite AlphaShapesIntroduction (an alpha complex concept vulgarization). + * + * \section example Example + * + * This example loads points from an OFF file, builds the Delaunay triangulation from the points, and finally + * initialize the alpha complex with it. * - * This example loads points from an OFF file, builds the Delaunay triangulation, and finally initialize the - * alpha complex with it. * Then, it is asked to display information about the alpha complex. * * \include Alpha_complex_from_off.cpp * * When launching: * - * \code $> ./alphaoffreader ../../data/points/alphashapedoc.off + * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off * \endcode * * the program output is: * * \include alphaoffreader_for_doc.txt + * + * \section algorithm Algorithm + * + * Data structure + * + * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. + * (The filtration value is set to NaN, which stands for unknown value): + * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" + * + * Filtration value computation algorithm + * + * \f{algorithm}{ + * \caption{Filtration value computation algorithm}\label{alpha} + * \begin{algorithmic} + * \For{i : dimension $\rightarrow$ 1} + * \ForAll{$\sigma$ of dimension i} + * \If {filtration($\sigma$) is NaN} + * \State filtration($\sigma$) = $\alpha(\sigma)$ + * \EndIf + * \ForAll{$\tau$ face of $\sigma$} \Comment{propagate alpha filtration value} + * \If {filtration($\tau$) is not NaN} + * \State filtration($\tau$) = min (filtration($\tau$), filtration($\sigma$)) + * \Else + * \If {$\tau$ is not Gabriel for $\sigma$} + * \State filtration($\tau$) = filtration($\sigma$) + * \EndIf + * \EndIf + * \EndFor + * \EndFor + * \EndFor + * \end{algorithmic} + * \f} + * + * From the example above, it means the algorithm will look into each triangulation ([1,2,3], [2,3,4], [1,3,5], ...), + * will compute the filtration value of the triangulation, and then will propagate the filtration value as described + * here : + * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" + * Then, the algorithm will look into each edge ([1,2], [2,3], [1,3], ...), + * will compute the filtration value of the edge (in this case, propagation will have no effect). + * + * Finally, the algorithm will look into each vertex ([1], [2], [3], [4], [5], [6] and [7]), + * will set the filtration value (0 in case of a vertex - propagation will have no effect). + * + * \section alpha-shape Alpha shape + * + * In the example above, the alpha shape of \f$\alpha_{74} < \alpha < \alpha_{73}\f$ is the alpha complex where the + * \f$\alpha_{74} <\f$ filtration value \f$< \alpha_{73}\f$ as described in \cite AlphaShapesIntroduction + * + * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" + * \copyright GNU General Public License v3. + * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim */ /** @} */ // end defgroup alpha_complex /** * \brief Alpha complex data structure. * - * \details Every simplex \f$[v_0, \cdots ,v_d]\f$ admits a canonical orientation - * induced by the order relation on vertices \f$ v_0 < \cdots < v_d \f$. - * - * Details may be found in \cite boissonnatmariasimplextreealgorithmica. - * + * \details + * The data structure can be constructed from a CGAL Delaunay triangulation (for more informations on CGAL Delaunay + * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) or from + * an OFF file (cf. Delaunay_triangulation_off_reader). + * + * Please refer to \ref alpha_complex for examples. * */ template Date: Tue, 23 Jun 2015 15:15:18 +0000 Subject: Separate main alpha documentation from class documentation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@635 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c1a775a032fc5e5ee6da473b91d07cfc3f1930c6 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 119 ++++++++++++++++++++++++ src/Alpha_complex/include/gudhi/Alpha_complex.h | 90 ------------------ 2 files changed, 119 insertions(+), 90 deletions(-) create mode 100644 src/Alpha_complex/doc/Intro_alpha_complex.h (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h new file mode 100644 index 00000000..34af2b98 --- /dev/null +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -0,0 +1,119 @@ +/* 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 Saclay (France) + * + * 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 . + */ + +// needs namespace for Doxygen to link on classes +namespace Gudhi { +// needs namespace for Doxygen to link on classes +namespace alphacomplex { + +/** \defgroup alpha_complex Alpha complex + * + * \author Vincent Rouvreau + * + * @{ + * + * \section definition Definition + * + * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation. + * + * The filtration value of each simplex is computed from the alpha value of the simplex if it is Gabriel or + * from the alpha value of the simplex coface that makes the simplex not Gabriel. + * + * Please refer to \cite AlphaShapesDefinition for a more complete alpha complex definition. + * + * Alpha complex are interesting because it looks like an \ref alpha-shape "Alpha shape" as described in + * \cite AlphaShapesIntroduction (an alpha complex concept vulgarization). + * + * \section example Example + * + * This example loads points from an OFF file, builds the Delaunay triangulation from the points, and finally + * initialize the alpha complex with it. + * + * Then, it is asked to display information about the alpha complex. + * + * \include Alpha_complex_from_off.cpp + * + * When launching: + * + * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off + * \endcode + * + * the program output is: + * + * \include alphaoffreader_for_doc.txt + * + * \section algorithm Algorithm + * + * Data structure + * + * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. + * (The filtration value is set to NaN, which stands for unknown value): + * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" + * + * Filtration value computation algorithm + * + * \f{algorithm}{ + * \caption{Filtration value computation algorithm}\label{alpha} + * \begin{algorithmic} + * \For{i : dimension $\rightarrow$ 1} + * \ForAll{$\sigma$ of dimension i} + * \If {filtration($\sigma$) is NaN} + * \State filtration($\sigma$) = $\alpha(\sigma)$ + * \EndIf + * \ForAll{$\tau$ face of $\sigma$} \Comment{propagate alpha filtration value} + * \If {filtration($\tau$) is not NaN} + * \State filtration($\tau$) = min (filtration($\tau$), filtration($\sigma$)) + * \Else + * \If {$\tau$ is not Gabriel for $\sigma$} + * \State filtration($\tau$) = filtration($\sigma$) + * \EndIf + * \EndIf + * \EndFor + * \EndFor + * \EndFor + * \end{algorithmic} + * \f} + * + * From the example above, it means the algorithm will look into each triangulation ([1,2,3], [2,3,4], [1,3,5], ...), + * will compute the filtration value of the triangulation, and then will propagate the filtration value as described + * here : + * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" + * Then, the algorithm will look into each edge ([1,2], [2,3], [1,3], ...), + * will compute the filtration value of the edge (in this case, propagation will have no effect). + * + * Finally, the algorithm will look into each vertex ([1], [2], [3], [4], [5], [6] and [7]), + * will set the filtration value (0 in case of a vertex - propagation will have no effect). + * + * \section alpha-shape Alpha shape + * + * In the example above, the alpha shape of \f$\alpha_{74} < \alpha < \alpha_{73}\f$ is the alpha complex where the + * \f$\alpha_{74} <\f$ filtration value \f$< \alpha_{73}\f$ as described in \cite AlphaShapesIntroduction + * + * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" + * \copyright GNU General Public License v3. + * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim + */ +/** @} */ // end defgroup alpha_complex + +} // namespace alphacomplex + +} // namespace Gudhi diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 191ff853..97c30abb 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -51,96 +51,6 @@ namespace alphacomplex { #define Kinit(f) =k.f() -/** \tableofcontents - * \defgroup alpha_complex Alpha complex - * - * \author Vincent Rouvreau - * - * @{ - * - * \section definition Definition - * - * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation. - * - * The filtration value of each simplex is computed from the alpha value of the simplex if it is Gabriel or - * from the alpha value of the simplex coface that makes the simplex not Gabriel. - * - * Please refer to \cite AlphaShapesDefinition for a more complete alpha complex definition. - * - * Alpha complex are interesting because it looks like an \ref alpha-shape "Alpha shape" as described in - * \cite AlphaShapesIntroduction (an alpha complex concept vulgarization). - * - * \section example Example - * - * This example loads points from an OFF file, builds the Delaunay triangulation from the points, and finally - * initialize the alpha complex with it. - * - * Then, it is asked to display information about the alpha complex. - * - * \include Alpha_complex_from_off.cpp - * - * When launching: - * - * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off - * \endcode - * - * the program output is: - * - * \include alphaoffreader_for_doc.txt - * - * \section algorithm Algorithm - * - * Data structure - * - * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. - * (The filtration value is set to NaN, which stands for unknown value): - * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" - * - * Filtration value computation algorithm - * - * \f{algorithm}{ - * \caption{Filtration value computation algorithm}\label{alpha} - * \begin{algorithmic} - * \For{i : dimension $\rightarrow$ 1} - * \ForAll{$\sigma$ of dimension i} - * \If {filtration($\sigma$) is NaN} - * \State filtration($\sigma$) = $\alpha(\sigma)$ - * \EndIf - * \ForAll{$\tau$ face of $\sigma$} \Comment{propagate alpha filtration value} - * \If {filtration($\tau$) is not NaN} - * \State filtration($\tau$) = min (filtration($\tau$), filtration($\sigma$)) - * \Else - * \If {$\tau$ is not Gabriel for $\sigma$} - * \State filtration($\tau$) = filtration($\sigma$) - * \EndIf - * \EndIf - * \EndFor - * \EndFor - * \EndFor - * \end{algorithmic} - * \f} - * - * From the example above, it means the algorithm will look into each triangulation ([1,2,3], [2,3,4], [1,3,5], ...), - * will compute the filtration value of the triangulation, and then will propagate the filtration value as described - * here : - * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" - * Then, the algorithm will look into each edge ([1,2], [2,3], [1,3], ...), - * will compute the filtration value of the edge (in this case, propagation will have no effect). - * - * Finally, the algorithm will look into each vertex ([1], [2], [3], [4], [5], [6] and [7]), - * will set the filtration value (0 in case of a vertex - propagation will have no effect). - * - * \section alpha-shape Alpha shape - * - * In the example above, the alpha shape of \f$\alpha_{74} < \alpha < \alpha_{73}\f$ is the alpha complex where the - * \f$\alpha_{74} <\f$ filtration value \f$< \alpha_{73}\f$ as described in \cite AlphaShapesIntroduction - * - * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" - * \copyright GNU General Public License v3. - * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim - */ -/** @} */ // end defgroup alpha_complex - /** * \brief Alpha complex data structure. * -- cgit v1.2.3 From 85059e058ea651d5d9e849c8462cbe5f01e4743b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 24 Jun 2015 15:27:19 +0000 Subject: Alpha complex construction from a list of CGAL points git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@641 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 521269f793f9c16c2305db8c97678bea2bf95092 --- .../example/Alpha_complex_from_off.cpp | 2 +- .../example/Alpha_complex_from_points.cpp | 71 +++++++++++++++ src/Alpha_complex/example/CMakeLists.txt | 3 + src/Alpha_complex/include/gudhi/Alpha_complex.h | 32 +++++-- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 100 ++++++++++++++++++--- src/common/doc/main_page.h | 4 +- 6 files changed, 192 insertions(+), 20 deletions(-) create mode 100644 src/Alpha_complex/example/Alpha_complex_from_points.cpp (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 0d7af117..ce278419 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -22,7 +22,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex<> alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp new file mode 100644 index 00000000..fc0e2460 --- /dev/null +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -0,0 +1,71 @@ +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" + +#include +#include + +#include +#include +#include + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef Kernel::Point_d Point; +typedef std::vector Vector_of_points; + +int main(int argc, char **argv) { + + // ---------------------------------------------------------------------------- + // Init of a list of points + // ---------------------------------------------------------------------------- + Vector_of_points points; + std::vector coords; + + coords.clear(); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(1.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(1.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(0.0); + coords.push_back(1.0); + coords.push_back(0.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(1.0); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from the list of points + // ---------------------------------------------------------------------------- + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Alpha complex is of dimension " << alpha_complex_from_points.dimension() << + " - " << alpha_complex_from_points.num_simplices() << " simplices - " << + alpha_complex_from_points.num_vertices() << " vertices." << std::endl; + + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + std::cout << " ( "; + for (auto vertex : alpha_complex_from_points.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << alpha_complex_from_points.filtration(f_simplex) << "] "; + std::cout << std::endl; + } + return 0; +} \ No newline at end of file diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 04c0ba58..2e64e4db 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -17,6 +17,9 @@ if(CGAL_FOUND) #add_definitions(-DDEBUG_TRACES) add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + + add_executable ( alphapoints Alpha_complex_from_points.cpp ) + target_link_libraries(alphapoints ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 97c30abb..138270ff 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -44,6 +44,7 @@ #include #include #include // NaN +#include // std::iterator namespace Gudhi { @@ -62,11 +63,6 @@ namespace alphacomplex { * Please refer to \ref alpha_complex for examples. * */ -template class Alpha_complex : public Simplex_tree<> { private: // From Simplex_tree @@ -94,6 +90,9 @@ class Alpha_complex : public Simplex_tree<> { // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; + + // size_type type from CGAL. + typedef Delaunay_triangulation::size_type size_type; private: /** \brief Boost bimap to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ @@ -108,7 +107,7 @@ class Alpha_complex : public Simplex_tree<> { * * @param[in] off_file_name OFF file [path and] name. */ - Alpha_complex(std::string& off_file_name) + Alpha_complex(const std::string& off_file_name) : triangulation(nullptr) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { @@ -128,6 +127,27 @@ class Alpha_complex : public Simplex_tree<> { init(); } + /** \brief Alpha_complex constructor from a list of points. + * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize + * the Alpha_complex. + * + * @param[in] dimension Dimension of points to be inserted. + * @param[in] size Number of points to be inserted. + * @param[in] firstPoint Iterator on the first point to be inserted. + * @param[in] last Point Iterator on the last point to be inserted. + */ + template + Alpha_complex(int dimension, size_type size, ForwardIterator firstPoint, ForwardIterator lastPoint) + : triangulation(nullptr) { + triangulation = new Delaunay_triangulation(dimension); + Delaunay_triangulation::size_type inserted = triangulation->insert(firstPoint, lastPoint); + if (inserted != size) { + std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << size<< std::endl; + exit(-1); // ----- >> + } + init(); + } + /** \brief Alpha_complex destructor from a Delaunay triangulation. * * @warning Deletes the Delaunay triangulation. diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 86d4d9c3..9530314c 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -28,15 +28,19 @@ #include "gudhi/Delaunay_triangulation_off_io.h" #include "gudhi/Alpha_complex.h" +#include +#include + #include // float comparison +#include // Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instantiation of the -// TriangulationDataStructure template parameter +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef Kernel::Point_d Point; +typedef std::vector Vector_of_points; +// The triangulation uses the default instantiation of the TriangulationDataStructure template parameter -BOOST_AUTO_TEST_CASE( S4_100_OFF_file ) { +BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { // ---------------------------------------------------------------------------- // // Init of an alpha-complex from a OFF file @@ -44,24 +48,24 @@ BOOST_AUTO_TEST_CASE( S4_100_OFF_file ) { // ---------------------------------------------------------------------------- std::string off_file_name("S4_100.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 4; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - + const int NUMBER_OF_VERTICES = 100; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - + const int NUMBER_OF_SIMPLICES = 6879; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); } -BOOST_AUTO_TEST_CASE( S8_10_OFF_file ) { +BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { // ---------------------------------------------------------------------------- // // Init of an alpha-complex from a OFF file @@ -69,19 +73,91 @@ BOOST_AUTO_TEST_CASE( S8_10_OFF_file ) { // ---------------------------------------------------------------------------- std::string off_file_name("S8_10.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 8; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - + const int NUMBER_OF_VERTICES = 10; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - + const int NUMBER_OF_SIMPLICES = 1007; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); +} + +bool are_almost_the_same(float a, float b) { + return std::fabs(a - b) < std::numeric_limits::epsilon(); +} + +BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { + + // ---------------------------------------------------------------------------- + // Init of a list of points + // ---------------------------------------------------------------------------- + Vector_of_points points; + std::vector coords; + + coords.clear(); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(1.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(1.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(0.0); + coords.push_back(1.0); + coords.push_back(0.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(1.0); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from the list of points + // ---------------------------------------------------------------------------- + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + + std::cout << "========== Alpha_complex_from_points ==========" << std::endl; + + std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_points.dimension() == 3); + std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_simplices() == 15); + std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() == 4); + + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + switch (alpha_complex_from_points.dimension(f_simplex)) { + case 0: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 0.0)); + break; + case 1: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 1.0/2.0)); + break; + case 2: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 2.0/3.0)); + break; + case 3: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 3.0/4.0)); + break; + default: + BOOST_CHECK(false); // Shall not happen + break; + } + } } diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 315aa0ac..770d2216 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -48,8 +48,10 @@ CGAL is a C++ library which provides easy access to efficient and reliable geome The following example requires the Computational Geometry Algorithms Library (CGAL) and will not be built if CGAL is not installed: - Simplex_tree/simplex_tree_from_alpha_shapes_3 + - Alpha_complex/Alpha_complex_from_off + - Alpha_complex/Alpha_complex_from_points -Having CGAL version 4.4 or higher installed is recommended. The procedure to install this library according to +Having CGAL version 4.7 or higher installed is recommended. The procedure to install this library according to your operating system is detailed here http://doc.cgal.org/latest/Manual/installation.html \subsection demos Demos and examples -- cgit v1.2.3 From 909bba8b607f4279709e989c7727063df4a98016 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 4 Aug 2015 12:32:08 +0000 Subject: get_point method in alpha_complex structure and its UT git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@723 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9ad36d7617f4aade5c85e2a8fb7a0c60180aa59f --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 29 +++++++++++---- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 43 ++++++++++++++++++++++ 2 files changed, 65 insertions(+), 7 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 138270ff..16781563 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -50,8 +50,6 @@ namespace Gudhi { namespace alphacomplex { -#define Kinit(f) =k.f() - /** * \brief Alpha complex data structure. * @@ -99,6 +97,8 @@ class Alpha_complex : public Simplex_tree<> { Bimap_vertex cgal_simplextree; /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation; + /** \brief Kernel for triangulation functions access.*/ + Kernel kernel; public: /** \brief Alpha_complex constructor from an OFF file name. @@ -156,6 +156,22 @@ class Alpha_complex : public Simplex_tree<> { delete triangulation; } + /** \brief get_point returns the point corresponding to the vertex given as parameter. + * + * @param[in] vertex Vertex handle of the point to retrieve. + * @return The founded point. + */ + Kernel::Point_d get_point(Vertex_handle vertex) { + Kernel::Point_d point; + try { + point = cgal_simplextree.right.at(vertex)->point(); + } + catch(...) { + std::cerr << "Alpha_complex - getPoint not found on vertex " << vertex << std::endl; + } + return point; + } + private: /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * @@ -248,9 +264,8 @@ class Alpha_complex : public Simplex_tree<> { // No need to compute squared_radius on a single point - alpha is 0.0 if (f_simplex_dim > 0) { // squared_radius function initialization - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - + Squared_Radius squared_radius = kernel.compute_squared_radius_d_object(); + alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } assign_filtration(f_simplex, alpha_complex_filtration); @@ -315,8 +330,7 @@ class Alpha_complex : public Simplex_tree<> { } } // is_gabriel function initialization - Kernel k; - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + Is_Gabriel is_gabriel = kernel.side_of_bounded_sphere_d_object(); #ifdef DEBUG_TRACES bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) != CGAL::ON_BOUNDED_SIDE; @@ -337,6 +351,7 @@ class Alpha_complex : public Simplex_tree<> { } } } + }; } // namespace alphacomplex diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 9530314c..b55b5e2e 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -93,6 +93,14 @@ bool are_almost_the_same(float a, float b) { return std::fabs(a - b) < std::numeric_limits::epsilon(); } +bool is_point_in_list(Vector_of_points points_list, Point point) { + for (auto& point_in_list : points_list) { + if (point_in_list == point) { + return true; // point found + } + } + return false; // point not found +} BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // ---------------------------------------------------------------------------- @@ -159,5 +167,40 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { break; } } + + Point p1 = alpha_complex_from_points.get_point(1); + std::cout << "alpha_complex_from_points.get_point(1)=" << p1 << std::endl; + BOOST_CHECK(4 == p1.dimension()); + BOOST_CHECK(is_point_in_list(points, p1)); + + Point p2 = alpha_complex_from_points.get_point(2); + std::cout << "alpha_complex_from_points.get_point(2)=" << p2 << std::endl; + BOOST_CHECK(4 == p2.dimension()); + BOOST_CHECK(is_point_in_list(points, p2)); + + Point p3 = alpha_complex_from_points.get_point(3); + std::cout << "alpha_complex_from_points.get_point(3)=" << p3 << std::endl; + BOOST_CHECK(4 == p3.dimension()); + BOOST_CHECK(is_point_in_list(points, p3)); + + Point p4 = alpha_complex_from_points.get_point(4); + std::cout << "alpha_complex_from_points.get_point(4)=" << p4 << std::endl; + BOOST_CHECK(4 == p4.dimension()); + BOOST_CHECK(is_point_in_list(points, p4)); + + Point p5 = alpha_complex_from_points.get_point(5); + std::cout << "alpha_complex_from_points.get_point(5)=" << p5 << std::endl; + BOOST_CHECK(0 == p5.dimension()); + BOOST_CHECK(!is_point_in_list(points, p5)); + + Point p0 = alpha_complex_from_points.get_point(0); + std::cout << "alpha_complex_from_points.get_point(0)=" << p0 << std::endl; + BOOST_CHECK(0 == p0.dimension()); + BOOST_CHECK(!is_point_in_list(points, p0)); + + Point p1234 = alpha_complex_from_points.get_point(1234); + std::cout << "alpha_complex_from_points.get_point(1234)=" << p1234.dimension() << std::endl; + BOOST_CHECK(0 == p1234.dimension()); + BOOST_CHECK(!is_point_in_list(points, p1234)); } -- cgit v1.2.3 From d6c4c80e50d558034958f8fab0289d4cfb1a31b8 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 5 Aug 2015 15:03:29 +0000 Subject: Debug traces in DEBUG mode Alpha complex from delaunay triangulation in static dimension git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@725 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9dda5a16874ae009c24be39c5a9c9d4124a29063 --- .../example/Alpha_complex_from_off.cpp | 3 +- .../example/Alpha_complex_from_points.cpp | 2 +- src/Alpha_complex/example/CMakeLists.txt | 5 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 85 +++++++++++++--------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 27 ++++--- src/Alpha_complex/test/CMakeLists.txt | 5 +- src/Persistent_cohomology/example/CMakeLists.txt | 7 +- 7 files changed, 81 insertions(+), 53 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index ce278419..a17155de 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -22,7 +22,8 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index fc0e2460..33680a40 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -49,7 +49,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 2e64e4db..04fc34af 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -13,8 +13,11 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() - #add_definitions(-DDEBUG_TRACES) add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 16781563..5834e3df 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -43,8 +43,8 @@ #include #include #include -#include // NaN -#include // std::iterator +#include // NaN +#include // std::iterator namespace Gudhi { @@ -61,6 +61,7 @@ namespace alphacomplex { * Please refer to \ref alpha_complex for examples. * */ +template class Alpha_complex : public Simplex_tree<> { private: // From Simplex_tree @@ -72,35 +73,43 @@ class Alpha_complex : public Simplex_tree<> { // From CGAL // Kernel for the Delaunay_triangulation. Dimension can be set dynamically. - typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + //typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; // Delaunay_triangulation type required to create an alpha-complex. - typedef CGAL::Delaunay_triangulation Delaunay_triangulation; + typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; + typedef typename Kernel::Point_d Point_d; + // Type required to compute squared radius, or side of bounded sphere on a vector of points. - typedef std::vector Vector_of_CGAL_points; + typedef typename std::vector Vector_of_CGAL_points; // Vertex_iterator type from CGAL. - typedef Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; + typedef typename Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; - // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. - typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; - // size_type type from CGAL. - typedef Delaunay_triangulation::size_type size_type; + typedef typename Delaunay_triangulation::size_type size_type; + + // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. + //typedef typename boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; + //typedef typename Bimap_vertex::value_type value_type; + typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; + typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; private: - /** \brief Boost bimap to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ - Bimap_vertex cgal_simplextree; + /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ + Map_vertex_iterator_to_handle vertex_iterator_to_handle; + /** \brief Map to switch from simplex tree vertex handle to CGAL vertex iterator.*/ + Map_vertex_handle_to_iterator vertex_handle_to_iterator; /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation; /** \brief Kernel for triangulation functions access.*/ Kernel kernel; public: + /** \brief Alpha_complex constructor from an OFF file name. * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize * the Alpha_complex. @@ -140,9 +149,9 @@ class Alpha_complex : public Simplex_tree<> { Alpha_complex(int dimension, size_type size, ForwardIterator firstPoint, ForwardIterator lastPoint) : triangulation(nullptr) { triangulation = new Delaunay_triangulation(dimension); - Delaunay_triangulation::size_type inserted = triangulation->insert(firstPoint, lastPoint); + size_type inserted = triangulation->insert(firstPoint, lastPoint); if (inserted != size) { - std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << size<< std::endl; + std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << size << std::endl; exit(-1); // ----- >> } init(); @@ -161,18 +170,20 @@ class Alpha_complex : public Simplex_tree<> { * @param[in] vertex Vertex handle of the point to retrieve. * @return The founded point. */ - Kernel::Point_d get_point(Vertex_handle vertex) { - Kernel::Point_d point; + Point_d get_point(Vertex_handle vertex) { + Point_d point; try { - point = cgal_simplextree.right.at(vertex)->point(); - } - catch(...) { + if (vertex_handle_to_iterator[vertex] != nullptr) { + point = vertex_handle_to_iterator[vertex]->point(); + } + } catch (...) { std::cerr << "Alpha_complex - getPoint not found on vertex " << vertex << std::endl; } return point; } - + private: + /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more @@ -197,7 +208,7 @@ class Alpha_complex : public Simplex_tree<> { std::cerr << "Alpha_complex init - Cannot init twice" << std::endl; return; // ----- >> } - + set_dimension(triangulation->maximal_dimension()); // -------------------------------------------------------------------------------------------- @@ -206,7 +217,11 @@ class Alpha_complex : public Simplex_tree<> { Vertex_handle vertex_handle = Vertex_handle(); // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation->vertices_begin(); vit != triangulation->vertices_end(); ++vit) { - cgal_simplextree.insert(Bimap_vertex::value_type(vit, vertex_handle)); +#ifdef DEBUG_TRACES + std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; +#endif // DEBUG_TRACES + vertex_iterator_to_handle[vit] = vertex_handle; + vertex_handle_to_iterator[vertex_handle] = vit; vertex_handle++; } // -------------------------------------------------------------------------------------------- @@ -219,18 +234,20 @@ class Alpha_complex : public Simplex_tree<> { std::cout << "Simplex_tree insertion "; #endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + if (*vit != nullptr) { #ifdef DEBUG_TRACES - std::cout << " " << cgal_simplextree.left.at(*vit); + std::cout << " " << vertex_iterator_to_handle[*vit]; #endif // DEBUG_TRACES - // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(cgal_simplextree.left.at(*vit)); + // Vector of vertex construction for simplex_tree structure + vertexVector.push_back(vertex_iterator_to_handle[*vit]); + } } #ifdef DEBUG_TRACES std::cout << std::endl; #endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, - std::numeric_limits::quiet_NaN()); + std::numeric_limits::quiet_NaN()); if (!insert_result.second) { std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; } @@ -250,7 +267,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << "Sigma of dim " << decr_dim << " is"; #endif // DEBUG_TRACES for (auto vertex : simplex_vertex_range(f_simplex)) { - pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); + pointVector.push_back(get_point(vertex)); #ifdef DEBUG_TRACES std::cout << " " << vertex; #endif // DEBUG_TRACES @@ -265,7 +282,7 @@ class Alpha_complex : public Simplex_tree<> { if (f_simplex_dim > 0) { // squared_radius function initialization Squared_Radius squared_radius = kernel.compute_squared_radius_d_object(); - + alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } assign_filtration(f_simplex, alpha_complex_filtration); @@ -317,12 +334,11 @@ class Alpha_complex : public Simplex_tree<> { Vector_of_CGAL_points pointVector; Vertex_handle vertexForGabriel = Vertex_handle(); for (auto vertex : simplex_vertex_range(f_boundary)) { - pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); + pointVector.push_back(get_point(vertex)); } // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function for (auto vertex : simplex_vertex_range(f_simplex)) { - if (std::find(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertex))->point()) - == pointVector.end()) { + if (std::find(pointVector.begin(), pointVector.end(), get_point(vertex)) == pointVector.end()) { // vertex is not found in Tau vertexForGabriel = vertex; // No need to continue loop @@ -331,14 +347,13 @@ class Alpha_complex : public Simplex_tree<> { } // is_gabriel function initialization Is_Gabriel is_gabriel = kernel.side_of_bounded_sphere_d_object(); -#ifdef DEBUG_TRACES - bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), get_point(vertexForGabriel)) != CGAL::ON_BOUNDED_SIDE; +#ifdef DEBUG_TRACES std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; #endif // DEBUG_TRACES // ### If Tau is not Gabriel of Sigma - if ((is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) - == CGAL::ON_BOUNDED_SIDE)) { + if (false == is_gab) { // ### filt(Tau) = filt(Sigma) Filtration_value alpha_complex_filtration = filtration(f_simplex); assign_filtration(f_boundary, alpha_complex_filtration); diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index b55b5e2e..4202c9e9 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -35,11 +35,9 @@ #include // Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; -typedef Kernel::Point_d Point; -typedef std::vector Vector_of_points; +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d; // The triangulation uses the default instantiation of the TriangulationDataStructure template parameter - +/* BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { // ---------------------------------------------------------------------------- // @@ -49,7 +47,7 @@ BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { std::string off_file_name("S4_100.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 4; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -74,7 +72,7 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { std::string off_file_name("S8_10.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 8; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -88,11 +86,17 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); } - +*/ bool are_almost_the_same(float a, float b) { return std::fabs(a - b) < std::numeric_limits::epsilon(); } +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Kernel_s; +typedef Kernel_s::Point_d Point; +typedef std::vector Vector_of_points; + + bool is_point_in_list(Vector_of_points points_list, Point point) { for (auto& point_in_list : points_list) { if (point_in_list == point) { @@ -101,6 +105,7 @@ bool is_point_in_list(Vector_of_points points_list, Point point) { } return false; // point not found } + BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // ---------------------------------------------------------------------------- @@ -109,6 +114,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { Vector_of_points points; std::vector coords; + points.clear(); coords.clear(); coords.push_back(0.0); coords.push_back(0.0); @@ -137,12 +143,12 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); std::cout << "========== Alpha_complex_from_points ==========" << std::endl; std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; - BOOST_CHECK(alpha_complex_from_points.dimension() == 3); + BOOST_CHECK(alpha_complex_from_points.dimension() == 4); std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_points.num_simplices() == 15); std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; @@ -190,17 +196,14 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { Point p5 = alpha_complex_from_points.get_point(5); std::cout << "alpha_complex_from_points.get_point(5)=" << p5 << std::endl; - BOOST_CHECK(0 == p5.dimension()); BOOST_CHECK(!is_point_in_list(points, p5)); Point p0 = alpha_complex_from_points.get_point(0); std::cout << "alpha_complex_from_points.get_point(0)=" << p0 << std::endl; - BOOST_CHECK(0 == p0.dimension()); BOOST_CHECK(!is_point_in_list(points, p0)); Point p1234 = alpha_complex_from_points.get_point(1234); std::cout << "alpha_complex_from_points.get_point(1234)=" << p1234.dimension() << std::endl; - BOOST_CHECK(0 == p1234.dimension()); BOOST_CHECK(!is_point_in_list(points, p1234)); } diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 79300790..87b05a3a 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -14,8 +14,11 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) include_directories (BEFORE "../../include") + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() - #add_definitions(-DDEBUG_TRACES) add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp ) target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) add_test(AlphaComplexUT ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUT diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index 9487cce6..3276989d 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -28,8 +28,11 @@ if (NOT MSVC) target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) if(CGAL_FOUND) - # uncomment to display debug traces - # add_definitions(-DDEBUG_TRACES) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() + add_executable(alpha_shapes_persistence alpha_shapes_persistence.cpp) target_link_libraries(alpha_shapes_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) add_test(alpha_shapes_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) -- cgit v1.2.3 From 9d0238eb065cd1a6b25ec2916d7a1a3cc52adcd6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 17 Aug 2015 10:04:23 +0000 Subject: Alpha complex fix for only inserting when alpha is less than git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@736 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0bc6560fa08b72d823681d36c49e80f0437d99f1 --- .../example/Alpha_complex_from_off.cpp | 25 +- .../example/Alpha_complex_from_points.cpp | 51 ++-- src/Alpha_complex/include/gudhi/Alpha_complex.h | 272 ++++++++++++--------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 174 +++++++++---- 4 files changed, 326 insertions(+), 196 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index a17155de..3ce4c7f4 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,37 +1,40 @@ -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" - #include #include + #include +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" + void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off" << std::endl; - exit(-1); // ----- >> + std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value" << std::endl; + std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0" << std::endl; + exit(-1); // ----- >> } int main(int argc, char **argv) { - if (argc != 2) { + if (argc != 3) { std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; usage(argv[0]); } std::string off_file_name(argv[1]); + double alpha_square_max_value = atof(argv[2]); // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); - + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); + // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << " - " << alpha_complex_from_file.num_simplices() << " simplices - " << alpha_complex_from_file.num_vertices() << " vertices." << std::endl; - + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { std::cout << " ( "; @@ -42,4 +45,4 @@ int main(int argc, char **argv) { std::cout << std::endl; } return 0; -} \ No newline at end of file +} diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 33680a40..b160d702 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -1,55 +1,40 @@ -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" - +#include +#include #include #include -#include -#include #include +#include + +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; int main(int argc, char **argv) { - // ---------------------------------------------------------------------------- // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - std::vector coords; - - coords.clear(); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(1.0); + + std::vector coords = { 0.0, 0.0, 0.0, 1.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(1.0); - coords.push_back(0.0); + coords = { 0.0, 0.0, 1.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(0.0); - coords.push_back(1.0); - coords.push_back(0.0); - coords.push_back(0.0); + coords = { 0.0, 1.0, 0.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(1.0); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(0.0); + coords = { 1.0, 0.0, 0.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - + // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + double max_alpha_square_value = 1e10; + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end(), + max_alpha_square_value); // ---------------------------------------------------------------------------- // Display information about the alpha complex @@ -57,7 +42,7 @@ int main(int argc, char **argv) { std::cout << "Alpha complex is of dimension " << alpha_complex_from_points.dimension() << " - " << alpha_complex_from_points.num_simplices() << " simplices - " << alpha_complex_from_points.num_vertices() << " vertices." << std::endl; - + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { std::cout << " ( "; @@ -68,4 +53,4 @@ int main(int argc, char **argv) { std::cout << std::endl; } return 0; -} \ No newline at end of file +} diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 5834e3df..06e69cf3 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ -#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ +#ifndef ALPHA_COMPLEX_H_ +#define ALPHA_COMPLEX_H_ // to construct a simplex_tree from Delaunay_triangulation #include @@ -31,8 +31,6 @@ #include #include // isnan, fmax -#include - #include #include #include @@ -40,11 +38,11 @@ #include #include -#include #include #include #include // NaN -#include // std::iterator +#include +#include // std::pair namespace Gudhi { @@ -71,10 +69,6 @@ class Alpha_complex : public Simplex_tree<> { // Simplex_result is the type returned from simplex_tree insert function. typedef typename std::pair Simplex_result; - // From CGAL - // Kernel for the Delaunay_triangulation. Dimension can be set dynamically. - //typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - // Delaunay_triangulation type required to create an alpha-complex. typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; @@ -92,38 +86,38 @@ class Alpha_complex : public Simplex_tree<> { // size_type type from CGAL. typedef typename Delaunay_triangulation::size_type size_type; - // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. - //typedef typename boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; - //typedef typename Bimap_vertex::value_type value_type; + // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; private: /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ - Map_vertex_iterator_to_handle vertex_iterator_to_handle; + Map_vertex_iterator_to_handle vertex_iterator_to_handle_; /** \brief Map to switch from simplex tree vertex handle to CGAL vertex iterator.*/ - Map_vertex_handle_to_iterator vertex_handle_to_iterator; + Map_vertex_handle_to_iterator vertex_handle_to_iterator_; /** \brief Pointer on the CGAL Delaunay triangulation.*/ - Delaunay_triangulation* triangulation; - /** \brief Kernel for triangulation functions access.*/ - Kernel kernel; + Delaunay_triangulation* triangulation_; + /** \brief Kernel for triangulation_ functions access.*/ + Kernel kernel_; + /** \brief Maximum value for alpha square.*/ + Filtration_value max_alpha_square_; public: - /** \brief Alpha_complex constructor from an OFF file name. * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize * the Alpha_complex. * * @param[in] off_file_name OFF file [path and] name. */ - Alpha_complex(const std::string& off_file_name) - : triangulation(nullptr) { + Alpha_complex(const std::string& off_file_name, Filtration_value max_alpha_square) + : triangulation_(nullptr), + max_alpha_square_(max_alpha_square) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { std::cerr << "Alpha_complex - Unable to read file " << off_file_name << std::endl; - exit(-1); // ----- >> + exit(-1); // ----- >> } - triangulation = off_reader.get_complex(); + triangulation_ = off_reader.get_complex(); init(); } @@ -131,8 +125,9 @@ class Alpha_complex : public Simplex_tree<> { * * @param[in] triangulation_ptr Pointer on a Delaunay triangulation. */ - Alpha_complex(Delaunay_triangulation* triangulation_ptr) - : triangulation(triangulation_ptr) { + Alpha_complex(Delaunay_triangulation* triangulation_ptr, Filtration_value max_alpha_square) + : triangulation_(triangulation_ptr), + max_alpha_square_(max_alpha_square) { init(); } @@ -146,13 +141,15 @@ class Alpha_complex : public Simplex_tree<> { * @param[in] last Point Iterator on the last point to be inserted. */ template - Alpha_complex(int dimension, size_type size, ForwardIterator firstPoint, ForwardIterator lastPoint) - : triangulation(nullptr) { - triangulation = new Delaunay_triangulation(dimension); - size_type inserted = triangulation->insert(firstPoint, lastPoint); + Alpha_complex(int dimension, size_type size, ForwardIterator firstPoint, ForwardIterator lastPoint, + Filtration_value max_alpha_square) + : triangulation_(nullptr), + max_alpha_square_(max_alpha_square) { + triangulation_ = new Delaunay_triangulation(dimension); + size_type inserted = triangulation_->insert(firstPoint, lastPoint); if (inserted != size) { std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << size << std::endl; - exit(-1); // ----- >> + exit(-1); // ----- >> } init(); } @@ -162,7 +159,7 @@ class Alpha_complex : public Simplex_tree<> { * @warning Deletes the Delaunay triangulation. */ ~Alpha_complex() { - delete triangulation; + delete triangulation_; } /** \brief get_point returns the point corresponding to the vertex given as parameter. @@ -173,17 +170,16 @@ class Alpha_complex : public Simplex_tree<> { Point_d get_point(Vertex_handle vertex) { Point_d point; try { - if (vertex_handle_to_iterator[vertex] != nullptr) { - point = vertex_handle_to_iterator[vertex]->point(); + if (vertex_handle_to_iterator_[vertex] != nullptr) { + point = vertex_handle_to_iterator_[vertex]->point(); } - } catch (...) { + } catch (...) { std::cerr << "Alpha_complex - getPoint not found on vertex " << vertex << std::endl; } return point; } private: - /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more @@ -192,108 +188,136 @@ class Alpha_complex : public Simplex_tree<> { * Initialization can be launched once. */ void init() { - if (triangulation == nullptr) { + if (triangulation_ == nullptr) { std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation" << std::endl; - return; // ----- >> + return; // ----- >> } - if (triangulation->number_of_vertices() < 1) { + if (triangulation_->number_of_vertices() < 1) { std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices" << std::endl; - return; // ----- >> + return; // ----- >> } - if (triangulation->maximal_dimension() < 1) { + if (triangulation_->maximal_dimension() < 1) { std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation" << std::endl; - return; // ----- >> + return; // ----- >> } if (num_vertices() > 0) { std::cerr << "Alpha_complex init - Cannot init twice" << std::endl; - return; // ----- >> + return; // ----- >> } - set_dimension(triangulation->maximal_dimension()); + set_dimension(triangulation_->maximal_dimension()); // -------------------------------------------------------------------------------------------- - // bimap to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa + // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa // Start to insert at handle = 0 - default integer value Vertex_handle vertex_handle = Vertex_handle(); // Loop on triangulation vertices list - for (CGAL_vertex_iterator vit = triangulation->vertices_begin(); vit != triangulation->vertices_end(); ++vit) { + for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { #ifdef DEBUG_TRACES std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES - vertex_iterator_to_handle[vit] = vertex_handle; - vertex_handle_to_iterator[vertex_handle] = vit; + vertex_iterator_to_handle_[vit] = vertex_handle; + vertex_handle_to_iterator_[vertex_handle] = vit; vertex_handle++; } // -------------------------------------------------------------------------------------------- + Filtration_value filtration_max = 0.0; // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list - for (auto cit = triangulation->finite_full_cells_begin(); cit != triangulation->finite_full_cells_end(); ++cit) { - Vector_vertex vertexVector; + for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { + Vector_vertex vertex_full_cell; #ifdef DEBUG_TRACES std::cout << "Simplex_tree insertion "; #endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { if (*vit != nullptr) { #ifdef DEBUG_TRACES - std::cout << " " << vertex_iterator_to_handle[*vit]; + std::cout << " " << vertex_iterator_to_handle_[*vit]; #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(vertex_iterator_to_handle[*vit]); + vertex_full_cell.push_back(vertex_iterator_to_handle_[*vit]); } } #ifdef DEBUG_TRACES std::cout << std::endl; #endif // DEBUG_TRACES - // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, - std::numeric_limits::quiet_NaN()); + + Simplex_tree<> full_cell; + full_cell.set_dimension(triangulation_->maximal_dimension()); + // Create a simplex tree containing only one of the full cells + Simplex_result insert_result = full_cell.insert_simplex_and_subfaces(vertex_full_cell); if (!insert_result.second) { std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; + exit(-1); // ----->> } - } - // -------------------------------------------------------------------------------------------- - - Filtration_value filtration_max = 0.0; - // -------------------------------------------------------------------------------------------- - // ### For i : d -> 0 - for (int decr_dim = dimension(); decr_dim >= 0; decr_dim--) { - // ### Foreach Sigma of dim i - for (auto f_simplex : skeleton_simplex_range(decr_dim)) { - int f_simplex_dim = dimension(f_simplex); - if (decr_dim == f_simplex_dim) { - Vector_of_CGAL_points pointVector; + bool skip_loop = false; + // +++ For i : d -> 0 + // This loop is skipped in case alpha²(Sigma) > max_alpha_square_ + for (int fc_decr_dim = full_cell.dimension(); (fc_decr_dim >= 0) && (!skip_loop); fc_decr_dim--) { + // +++ Foreach Sigma of dim i + // No need to skip this loop in case alpha²(Sigma) > max_alpha_square_ because of + // if (fc_decr_dim == f_simplex_dim) which means "only for a full cell" + for (auto fc_simplex : full_cell.skeleton_simplex_range(fc_decr_dim)) { + int f_simplex_dim = full_cell.dimension(fc_simplex); + if (fc_decr_dim == f_simplex_dim) { + Vector_of_CGAL_points pointVector; + Vector_vertex current_vertex; #ifdef DEBUG_TRACES - std::cout << "Sigma of dim " << decr_dim << " is"; + std::cout << "Sigma of dim " << fc_decr_dim << " is"; #endif // DEBUG_TRACES - for (auto vertex : simplex_vertex_range(f_simplex)) { - pointVector.push_back(get_point(vertex)); + for (auto vertex : full_cell.simplex_vertex_range(fc_simplex)) { + pointVector.push_back(get_point(vertex)); + current_vertex.push_back(vertex); #ifdef DEBUG_TRACES - std::cout << " " << vertex; + std::cout << " " << vertex; #endif // DEBUG_TRACES - } + } #ifdef DEBUG_TRACES - std::cout << std::endl; + std::cout << std::endl; #endif // DEBUG_TRACES - // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (isnan(filtration(f_simplex))) { - Filtration_value alpha_complex_filtration = 0.0; - // No need to compute squared_radius on a single point - alpha is 0.0 - if (f_simplex_dim > 0) { - // squared_radius function initialization - Squared_Radius squared_radius = kernel.compute_squared_radius_d_object(); - - alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); - } - assign_filtration(f_simplex, alpha_complex_filtration); - filtration_max = fmax(filtration_max, alpha_complex_filtration); + Simplex_handle sigma_handle = find(current_vertex); + // +++ If filt(Sigma) is NaN : filt(Sigma) = alpha²(Sigma) + if ((sigma_handle == null_simplex()) || isnan(filtration(sigma_handle))) { + Filtration_value alpha_complex_filtration = compute_alpha_square(pointVector.begin(), pointVector.end(), + f_simplex_dim); + if (alpha_complex_filtration <= max_alpha_square_) { + // Only insert Sigma in Simplex tree if alpha²(Sigma) <= max_alpha_square_ + if (sigma_handle == null_simplex()) { +#ifdef DEBUG_TRACES + std::cout << "Alpha_complex::init Sigma not found" << std::endl; +#endif // DEBUG_TRACES + insert_result = insert_simplex(current_vertex, std::numeric_limits::quiet_NaN()); + if (!insert_result.second) { + std::cerr << "Alpha_complex::init insert_simplex failed" << std::endl; + exit(-1); // ----->> + } + // Sigma is the new inserted simplex handle + sigma_handle = insert_result.first; + } #ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl; + std::cout << "Alpha_complex::init filtration = " << alpha_complex_filtration << std::endl; #endif // DEBUG_TRACES + assign_filtration(sigma_handle, alpha_complex_filtration); + filtration_max = fmax(filtration_max, alpha_complex_filtration); + } else { + // if alpha²(Sigma) > max_alpha_square_ go to the next full cell + skip_loop = true; +#ifdef DEBUG_TRACES + std::cout << "Alpha_complex::init skip loop on this full cell" << std::endl; +#endif // DEBUG_TRACES + break; + } + } // --- If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) + if (filtration(sigma_handle) <= max_alpha_square_) { + // Propagate alpha filtration value in Simplex tree if alpha²(Sigma) <= max_alpha_square_ + // in case Sigma is not found AND not inserted (alpha_complex_filtration > max_alpha_square_), + // filtration(null_simplex()) returns INFINITY => no propagation + propagate_alpha_filtration(full_cell, fc_simplex, fc_decr_dim, sigma_handle); + } } - propagate_alpha_filtration(f_simplex, decr_dim); - } - } + } // --- Foreach Sigma of dim i + } // --- For i : d -> 0 } // -------------------------------------------------------------------------------------------- @@ -303,41 +327,60 @@ class Alpha_complex : public Simplex_tree<> { set_filtration(filtration_max); } - template - void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { + template + Filtration_value compute_alpha_square(ForwardIterator firstPoint, ForwardIterator lastPoint, int f_simplex_dim) { + Filtration_value alpha_square_value = 0.0; + // No need to compute squared_radius on a single point - alpha is 0.0 + if (f_simplex_dim > 0) { + // squared_radius function initialization + Squared_Radius squared_radius = kernel_.compute_squared_radius_d_object(); + + alpha_square_value = squared_radius(firstPoint, lastPoint); + } + return alpha_square_value; + } + + void propagate_alpha_filtration(Simplex_tree& full_cell, Simplex_handle fc_simplex, int fc_decr_dim, + Simplex_handle sigma_handle) { // ### Foreach Tau face of Sigma - for (auto f_boundary : boundary_simplex_range(f_simplex)) { + for (auto f_boundary : full_cell.boundary_simplex_range(fc_simplex)) { #ifdef DEBUG_TRACES std::cout << " | --------------------------------------------------" << std::endl; std::cout << " | Tau "; - for (auto vertex : simplex_vertex_range(f_boundary)) { +#endif // DEBUG_TRACES + Vector_vertex tau_vertex; + for (auto vertex : full_cell.simplex_vertex_range(f_boundary)) { + tau_vertex.push_back(vertex); +#ifdef DEBUG_TRACES std::cout << vertex << " "; +#endif // DEBUG_TRACES } +#ifdef DEBUG_TRACES std::cout << "is a face of Sigma" << std::endl; - std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl; #endif // DEBUG_TRACES + Simplex_handle tau_handle = find(tau_vertex); // ### If filt(Tau) is not NaN - if (!isnan(filtration(f_boundary))) { + + if ((tau_handle != null_simplex()) && (!isnan(filtration(tau_handle)))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) - Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); - assign_filtration(f_boundary, alpha_complex_filtration); + Filtration_value alpha_complex_filtration = fmin(filtration(tau_handle), filtration(sigma_handle)); + assign_filtration(tau_handle, alpha_complex_filtration); // No need to check for filtration_max, alpha_complex_filtration is a min of an existing filtration value #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << alpha_complex_filtration << std::endl; #endif // DEBUG_TRACES - // ### Else } else { // No need to compute is_gabriel for dimension <= 2 // i.e. : Sigma = (3,1) => Tau = 1 - if (decr_dim > 1) { + if (fc_decr_dim > 1) { // insert the Tau points in a vector for is_gabriel function Vector_of_CGAL_points pointVector; Vertex_handle vertexForGabriel = Vertex_handle(); - for (auto vertex : simplex_vertex_range(f_boundary)) { + for (auto vertex : full_cell.simplex_vertex_range(f_boundary)) { pointVector.push_back(get_point(vertex)); } // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function - for (auto vertex : simplex_vertex_range(f_simplex)) { + for (auto vertex : simplex_vertex_range(sigma_handle)) { if (std::find(pointVector.begin(), pointVector.end(), get_point(vertex)) == pointVector.end()) { // vertex is not found in Tau vertexForGabriel = vertex; @@ -346,7 +389,7 @@ class Alpha_complex : public Simplex_tree<> { } } // is_gabriel function initialization - Is_Gabriel is_gabriel = kernel.side_of_bounded_sphere_d_object(); + Is_Gabriel is_gabriel = kernel_.side_of_bounded_sphere_d_object(); bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), get_point(vertexForGabriel)) != CGAL::ON_BOUNDED_SIDE; #ifdef DEBUG_TRACES @@ -354,23 +397,34 @@ class Alpha_complex : public Simplex_tree<> { #endif // DEBUG_TRACES // ### If Tau is not Gabriel of Sigma if (false == is_gab) { + if (tau_handle == null_simplex()) { +#ifdef DEBUG_TRACES + std::cout << " | Tau not found" << std::endl; +#endif // DEBUG_TRACES + // in case Tau is not yet created + Simplex_result insert_result = insert_simplex(tau_vertex, std::numeric_limits::quiet_NaN()); + if (!insert_result.second) { + std::cerr << "Alpha_complex::propagate_alpha_filtration insert_simplex failed" << std::endl; + exit(-1); // ----->> + } + // Sigma is the new inserted simplex handle + tau_handle = insert_result.first; + } // ### filt(Tau) = filt(Sigma) - Filtration_value alpha_complex_filtration = filtration(f_simplex); - assign_filtration(f_boundary, alpha_complex_filtration); + assign_filtration(tau_handle, filtration(sigma_handle)); // No need to check for filtration_max, alpha_complex_filtration is an existing filtration value #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(sigma_handle) << std::endl; #endif // DEBUG_TRACES } } } } } - }; -} // namespace alphacomplex +} // namespace alphacomplex -} // namespace Gudhi +} // namespace Gudhi -#endif // SRC_ALPHA_COMPLEX_INCLUDE_GUDHI_ALPHA_COMPLEX_H_ +#endif // ALPHA_COMPLEX_H_ diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index b7aceb5e..aa9500e7 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -24,15 +24,17 @@ #include #include #include -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" - #include #include -#include // float comparison +#include // float comparison #include +#include +#include + +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d; @@ -45,9 +47,11 @@ BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { // // ---------------------------------------------------------------------------- std::string off_file_name("S4_100.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + double max_alpha_square_value = 1e10; + std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); const int DIMENSION = 4; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -59,8 +63,51 @@ BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { const int NUMBER_OF_SIMPLICES = 6879; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + + // + TODO(VR) : in wait of num_simplices fix in Simplex_tree [ + int num_simplices = 0; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + num_simplices++; + } + std::cout << "num_simplices=" << num_simplices << std::endl; + BOOST_CHECK(num_simplices == NUMBER_OF_SIMPLICES); + // - TODO(VR) : in wait of num_simplices fix in Simplex_tree ] +} + +BOOST_AUTO_TEST_CASE(S4_100_OFF_file_filtered) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-complex from a OFF file + // + // ---------------------------------------------------------------------------- + std::string off_file_name("S4_100.off"); + double max_alpha_square_value = 0.999; + std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; + + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); + + const int DIMENSION = 4; + std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); + + const int NUMBER_OF_VERTICES = 13; // Versus 100, because of filtered alpha value + std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 90; // Versus 6879, because of filtered alpha value + std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; + // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + // + TODO(VR) : in wait of num_simplices fix in Simplex_tree [ + int num_simplices = 0; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + num_simplices++; + } + std::cout << "num_simplices=" << num_simplices << std::endl; + BOOST_CHECK(num_simplices == NUMBER_OF_SIMPLICES); + // - TODO(VR) : in wait of num_simplices fix in Simplex_tree ] } BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { @@ -70,9 +117,11 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { // // ---------------------------------------------------------------------------- std::string off_file_name("S8_10.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + double max_alpha_square_value = 1e10; + std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); const int DIMENSION = 8; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -84,7 +133,51 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { const int NUMBER_OF_SIMPLICES = 1007; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + + // + TODO(VR) : in wait of num_simplices fix in Simplex_tree [ + int num_simplices = 0; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + num_simplices++; + } + std::cout << "num_simplices=" << num_simplices << std::endl; + BOOST_CHECK(num_simplices == NUMBER_OF_SIMPLICES); + // - TODO(VR) : in wait of num_simplices fix in Simplex_tree ] +} + +BOOST_AUTO_TEST_CASE(S8_10_OFF_file_filtered) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-complex from a OFF file + // + // ---------------------------------------------------------------------------- + std::string off_file_name("S8_10.off"); + double max_alpha_square_value = 1.0; + std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; + + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); + + const int DIMENSION = 8; + std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); + + const int NUMBER_OF_VERTICES = 10; + std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 895; // Versus 1007, because of filtered alpha value + std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; + // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + + // + TODO(VR) : in wait of num_simplices fix in Simplex_tree [ + int num_simplices = 0; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + num_simplices++; + } + std::cout << "num_simplices=" << num_simplices << std::endl; + BOOST_CHECK(num_simplices == NUMBER_OF_SIMPLICES); + // - TODO(VR) : in wait of num_simplices fix in Simplex_tree ] } bool are_almost_the_same(float a, float b) { @@ -100,57 +193,53 @@ typedef std::vector Vector_of_points; bool is_point_in_list(Vector_of_points points_list, Point point) { for (auto& point_in_list : points_list) { if (point_in_list == point) { - return true; // point found + return true; // point found } } - return false; // point not found + return false; // point not found } BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { - // ---------------------------------------------------------------------------- // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - std::vector coords; - - points.clear(); - coords.clear(); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(1.0); + std::vector coords = { 0.0, 0.0, 0.0, 1.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(1.0); - coords.push_back(0.0); + coords = { 0.0, 0.0, 1.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(0.0); - coords.push_back(1.0); - coords.push_back(0.0); - coords.push_back(0.0); + coords = { 0.0, 1.0, 0.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(1.0); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(0.0); + coords = { 1.0, 0.0, 0.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + double max_alpha_square_value = 1e10; + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end(), + max_alpha_square_value); std::cout << "========== Alpha_complex_from_points ==========" << std::endl; + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + int num_simplices = 0; // TODO(VR) : in wait of num_simplices fix in Simplex_tree + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + num_simplices++; // TODO(VR) : in wait of num_simplices fix in Simplex_tree + std::cout << " ( "; + for (auto vertex : alpha_complex_from_points.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << alpha_complex_from_points.filtration(f_simplex) << "] "; + std::cout << std::endl; + } + std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_points.dimension() == 4); - std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_points.num_simplices() == 15); + // TODO(VR) : std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() + // << std::endl; + // TODO(VR) : BOOST_CHECK(alpha_complex_from_points.num_simplices() == 15); + BOOST_CHECK(num_simplices == 15); // TODO(VR) : in wait of num_simplices fix in Simplex_tree std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_points.num_vertices() == 4); @@ -169,11 +258,11 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 3.0/4.0)); break; default: - BOOST_CHECK(false); // Shall not happen + BOOST_CHECK(false); // Shall not happen break; } } - + Point p1 = alpha_complex_from_points.get_point(1); std::cout << "alpha_complex_from_points.get_point(1)=" << p1 << std::endl; BOOST_CHECK(4 == p1.dimension()); @@ -205,5 +294,4 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { Point p1234 = alpha_complex_from_points.get_point(1234); std::cout << "alpha_complex_from_points.get_point(1234)=" << p1234.dimension() << std::endl; BOOST_CHECK(!is_point_in_list(points, p1234)); - } -- cgit v1.2.3 From 3d47e5f4f22e82f2af246ae7d67f19307d57a053 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 18 Aug 2015 06:56:11 +0000 Subject: It is not the loop that must be skipped, but only the propagation, otherwise, points are missed. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@739 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ce88511e64685ee68630db77eddc922dcf8a016e --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 06e69cf3..71d34229 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -168,7 +168,7 @@ class Alpha_complex : public Simplex_tree<> { * @return The founded point. */ Point_d get_point(Vertex_handle vertex) { - Point_d point; + Point_d point(dimension()); try { if (vertex_handle_to_iterator_[vertex] != nullptr) { point = vertex_handle_to_iterator_[vertex]->point(); @@ -251,10 +251,8 @@ class Alpha_complex : public Simplex_tree<> { std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; exit(-1); // ----->> } - bool skip_loop = false; // +++ For i : d -> 0 - // This loop is skipped in case alpha²(Sigma) > max_alpha_square_ - for (int fc_decr_dim = full_cell.dimension(); (fc_decr_dim >= 0) && (!skip_loop); fc_decr_dim--) { + for (int fc_decr_dim = full_cell.dimension(); (fc_decr_dim >= 0); fc_decr_dim--) { // +++ Foreach Sigma of dim i // No need to skip this loop in case alpha²(Sigma) > max_alpha_square_ because of // if (fc_decr_dim == f_simplex_dim) which means "only for a full cell" @@ -277,6 +275,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << std::endl; #endif // DEBUG_TRACES Simplex_handle sigma_handle = find(current_vertex); + bool skip_propagation = false; // +++ If filt(Sigma) is NaN : filt(Sigma) = alpha²(Sigma) if ((sigma_handle == null_simplex()) || isnan(filtration(sigma_handle))) { Filtration_value alpha_complex_filtration = compute_alpha_square(pointVector.begin(), pointVector.end(), @@ -301,15 +300,14 @@ class Alpha_complex : public Simplex_tree<> { assign_filtration(sigma_handle, alpha_complex_filtration); filtration_max = fmax(filtration_max, alpha_complex_filtration); } else { - // if alpha²(Sigma) > max_alpha_square_ go to the next full cell - skip_loop = true; + // if alpha²(Sigma) > max_alpha_square_ skip propagation + skip_propagation = true; #ifdef DEBUG_TRACES - std::cout << "Alpha_complex::init skip loop on this full cell" << std::endl; + std::cout << "Alpha_complex::init skip propagation on this full cell" << std::endl; #endif // DEBUG_TRACES - break; } } // --- If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (filtration(sigma_handle) <= max_alpha_square_) { + if ((filtration(sigma_handle) <= max_alpha_square_) && !skip_propagation) { // Propagate alpha filtration value in Simplex tree if alpha²(Sigma) <= max_alpha_square_ // in case Sigma is not found AND not inserted (alpha_complex_filtration > max_alpha_square_), // filtration(null_simplex()) returns INFINITY => no propagation -- cgit v1.2.3 From 2ca2d175f0b49ff267d9a99e5a4c0a5f03e0d30c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 18 Aug 2015 12:45:13 +0000 Subject: exception throw on get_point not found git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@740 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fd2efc725a140f978d2624fe7879dc32f5566ab0 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 13 +++++-------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 20 ++++++-------------- 2 files changed, 11 insertions(+), 22 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 71d34229..213436e0 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -166,17 +166,14 @@ class Alpha_complex : public Simplex_tree<> { * * @param[in] vertex Vertex handle of the point to retrieve. * @return The founded point. + * @warning Exception std::out_of_range is thrown in case vertex is not in the map vertex_handle_to_iterator_. */ Point_d get_point(Vertex_handle vertex) { - Point_d point(dimension()); - try { - if (vertex_handle_to_iterator_[vertex] != nullptr) { - point = vertex_handle_to_iterator_[vertex]->point(); - } - } catch (...) { - std::cerr << "Alpha_complex - getPoint not found on vertex " << vertex << std::endl; + if (vertex_handle_to_iterator_[vertex] != nullptr) { + return vertex_handle_to_iterator_[vertex]->point(); + } else { + throw std::out_of_range("Vertex out of vector range"); } - return point; } private: diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index aa9500e7..c15f07e1 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -92,11 +92,11 @@ BOOST_AUTO_TEST_CASE(S4_100_OFF_file_filtered) { std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - const int NUMBER_OF_VERTICES = 13; // Versus 100, because of filtered alpha value + const int NUMBER_OF_VERTICES = 100; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 90; // Versus 6879, because of filtered alpha value + const int NUMBER_OF_SIMPLICES = 5966; // Versus 6879, because of filtered alpha value std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); @@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file_filtered) { std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 895; // Versus 1007, because of filtered alpha value + const int NUMBER_OF_SIMPLICES = 1004; // Versus 1007, because of filtered alpha value std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); @@ -283,15 +283,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { BOOST_CHECK(4 == p4.dimension()); BOOST_CHECK(is_point_in_list(points, p4)); - Point p5 = alpha_complex_from_points.get_point(5); - std::cout << "alpha_complex_from_points.get_point(5)=" << p5 << std::endl; - BOOST_CHECK(!is_point_in_list(points, p5)); - - Point p0 = alpha_complex_from_points.get_point(0); - std::cout << "alpha_complex_from_points.get_point(0)=" << p0 << std::endl; - BOOST_CHECK(!is_point_in_list(points, p0)); - - Point p1234 = alpha_complex_from_points.get_point(1234); - std::cout << "alpha_complex_from_points.get_point(1234)=" << p1234.dimension() << std::endl; - BOOST_CHECK(!is_point_in_list(points, p1234)); + BOOST_CHECK_THROW (alpha_complex_from_points.get_point(5), std::out_of_range); + BOOST_CHECK_THROW (alpha_complex_from_points.get_point(0), std::out_of_range); + BOOST_CHECK_THROW (alpha_complex_from_points.get_point(1234), std::out_of_range); } -- cgit v1.2.3 From 7955e76b2d410f373809a296de740c225456a0dd Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 24 Aug 2015 12:07:36 +0000 Subject: get_point is const git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@754 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fb4be75f9438bab94b68f551ae3bde73c980d131 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 518d1792..04fb185c 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -166,7 +166,7 @@ class Alpha_complex : public Simplex_tree<> { * @return The founded point. * @warning Exception std::out_of_range is thrown in case vertex is not in the map vertex_handle_to_iterator_. */ - Point_d get_point(Vertex_handle vertex) { + Point_d get_point(Vertex_handle vertex) const { auto found_it = vertex_handle_to_iterator_.find(vertex); if (found_it != vertex_handle_to_iterator_.end()) { return found_it->second->point(); -- cgit v1.2.3 From cb82907d03e3f875a418efc52570970c01c2677d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 31 Aug 2015 14:21:29 +0000 Subject: insert_simplex_and_subfaces no more factoriel complexity. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@764 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 34fd4f5e0221a3899ec98a0cdcbdc83fb83bf463 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 12 ++--- src/Simplex_tree/include/gudhi/Simplex_tree.h | 71 +++++++++++++++++-------- 2 files changed, 55 insertions(+), 28 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 04fb185c..d8568be0 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -219,7 +219,7 @@ class Alpha_complex : public Simplex_tree<> { } } // -------------------------------------------------------------------------------------------- - + // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { @@ -242,10 +242,6 @@ class Alpha_complex : public Simplex_tree<> { // Insert each simplex and its subfaces in the simplex tree - filtration is NaN Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); - if (!insert_result.second) { - std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; - exit(-1); // ----->> - } } // -------------------------------------------------------------------------------------------- @@ -324,8 +320,10 @@ class Alpha_complex : public Simplex_tree<> { pointVector.push_back(get_point(vertex)); } // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function + Point_d point_for_gabriel; for (auto vertex : simplex_vertex_range(f_simplex)) { - if (std::find(pointVector.begin(), pointVector.end(), get_point(vertex)) == pointVector.end()) { + point_for_gabriel = get_point(vertex); + if (std::find(pointVector.begin(), pointVector.end(), point_for_gabriel) == pointVector.end()) { // vertex is not found in Tau vertexForGabriel = vertex; // No need to continue loop @@ -334,7 +332,7 @@ class Alpha_complex : public Simplex_tree<> { } // is_gabriel function initialization Is_Gabriel is_gabriel = kernel_.side_of_bounded_sphere_d_object(); - bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), get_point(vertexForGabriel)) + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), point_for_gabriel) != CGAL::ON_BOUNDED_SIDE; #ifdef DEBUG_TRACES std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index fe2faf90..bda7e72a 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -515,33 +515,62 @@ class Simplex_tree { * @param[in] filtration the filtration value assigned to the new N-simplex. */ template - std::pair insert_simplex_and_subfaces(RandomAccessVertexRange& Nsimplex, + std::pair insert_simplex_and_subfaces(const RandomAccessVertexRange& Nsimplex, Filtration_value filtration = 0.0) { - std::pair returned; - if (Nsimplex.size() > 1) { - for (unsigned int NIndex = 0; NIndex < Nsimplex.size(); NIndex++) { - // insert N (N-1)-Simplex - RandomAccessVertexRange NsimplexMinusOne; - for (unsigned int NListIter = 0; NListIter < Nsimplex.size() - 1; NListIter++) { - // (N-1)-Simplex creation - NsimplexMinusOne.push_back(Nsimplex[(NIndex + NListIter) % Nsimplex.size()]); - } - // (N-1)-Simplex recursive call - returned = insert_simplex_and_subfaces(NsimplexMinusOne, filtration); + // Simplex copy + std::vector the_simplex(Nsimplex.begin(), Nsimplex.end()); + // must be sorted in increasing order + std::sort(the_simplex.begin(), the_simplex.end()); + std::vector> to_be_inserted; + std::vector> to_be_propagated; + return rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration); + } + + private: + std::pair rec_insert_simplex_and_subfaces(std::vector& the_simplex, + std::vector>& to_be_inserted, + std::vector>& to_be_propagated, + Filtration_value filtration = 0.0) { + std::pair insert_result; + if (the_simplex.size() > 1) { + // Get and remove last vertex + Vertex_handle last_vertex= the_simplex.back(); + the_simplex.pop_back(); + // Recursive call after last vertex removal + insert_result = rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration); + + // Concatenation of to_be_inserted and to_be_propagated + to_be_inserted.insert(to_be_inserted.end(), to_be_propagated.begin(), to_be_propagated.end()); + to_be_propagated = to_be_inserted; + + // to_be_inserted treatment + for (auto& simplex_tbi : to_be_inserted) { + simplex_tbi.push_back(last_vertex); } - // N-Simplex insert - returned = insert_simplex(Nsimplex, filtration); - if (returned.second == true) { + std::vector last_simplex(1, last_vertex); + to_be_inserted.push_back(last_simplex); + + for (auto& simplex_tbi : to_be_inserted) { + insert_result = insert_simplex(simplex_tbi, filtration); } - } else if (Nsimplex.size() == 1) { - // 1-Simplex insert - End of recursivity - returned = insert_simplex(Nsimplex, filtration); - if (returned.second == true) { + + + } else if (the_simplex.size() == 1) { + // When reaching the end of recursivity, vector of simplices shall be empty and filled on back recursive + if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)){ + std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty" << std::endl; + exit(-1); } + std::vector first_simplex(1, the_simplex.back()); + to_be_inserted.push_back(first_simplex); + + insert_result = insert_simplex(first_simplex, filtration); } else { - // Nothing to insert - empty vector + std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error" << std::endl; + exit(-1); } - return returned; + + return insert_result; } public: -- cgit v1.2.3 From 493372a01e24220d16ef0405eb7cdc4bbe96fe1c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 9 Nov 2015 15:58:16 +0000 Subject: Code review fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@895 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: aa5f6a30b847dd8a2add83fab50762338095de26 --- .../example/Alpha_complex_from_points.cpp | 2 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 35 ++++++++++------------ src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 2 +- 3 files changed, 18 insertions(+), 21 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index e2610dbd..e460f177 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -33,7 +33,7 @@ int main(int argc, char **argv) { // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- double max_alpha_square_value = 1e10; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points, max_alpha_square_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, max_alpha_square_value); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 6b47ace7..562b80c3 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -32,9 +32,6 @@ #include #include -#include -#include -#include #include #include @@ -73,6 +70,7 @@ class Alpha_complex : public Simplex_tree<> { typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; + typedef typename Kernel::Point_dimension_d Point_Dimension; typedef typename Kernel::Point_d Point_d; @@ -87,13 +85,15 @@ class Alpha_complex : public Simplex_tree<> { // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; - typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; + //typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; + typedef typename std::vector< CGAL_vertex_iterator > Vector_vertex_iterator; private: /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ Map_vertex_iterator_to_handle vertex_iterator_to_handle_; - /** \brief Map to switch from simplex tree vertex handle to CGAL vertex iterator.*/ - Map_vertex_handle_to_iterator vertex_handle_to_iterator_; + /** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator. + * Vertex handles are inserted sequentially, starting at 0.*/ + Vector_vertex_iterator vertex_handle_to_iterator_; /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation_; /** \brief Kernel for triangulation_ functions access.*/ @@ -131,8 +131,6 @@ class Alpha_complex : public Simplex_tree<> { } /** \brief Alpha_complex constructor from a list of points. - * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize - * the Alpha_complex. * * @param[in] dimension Dimension of points to be inserted. * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d @@ -141,12 +139,16 @@ class Alpha_complex : public Simplex_tree<> { * std::end return input iterators on a Kernel::Point_d. */ template - Alpha_complex(int dimension, const InputPointRange& points, + Alpha_complex(const InputPointRange& points, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(nullptr) { - triangulation_ = new Delaunay_triangulation(dimension); auto first = std::begin(points); auto last = std::end(points); + // point_dimension function initialization + Point_Dimension point_dimension = kernel_.point_dimension_d_object(); + + // Delaunay triangulation is point dimension minus one. + triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); size_type inserted = triangulation_->insert(first, last); if (inserted != (last -first)) { @@ -168,16 +170,11 @@ class Alpha_complex : public Simplex_tree<> { /** \brief get_point returns the point corresponding to the vertex given as parameter. * * @param[in] vertex Vertex handle of the point to retrieve. - * @return The founded point. - * @warning Exception std::out_of_range is thrown in case vertex is not in the map vertex_handle_to_iterator_. + * @return The point found. + * @warning Exception std::out_of_range is thrown in case vertex is not found. */ Point_d get_point(Vertex_handle vertex) const { - auto found_it = vertex_handle_to_iterator_.find(vertex); - if (found_it != vertex_handle_to_iterator_.end()) { - return found_it->second->point(); - } else { - throw std::out_of_range("Vertex out of vector range"); - } + return vertex_handle_to_iterator_.at(vertex)->point(); } private: @@ -219,7 +216,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES vertex_iterator_to_handle_.emplace(vit, vertex_handle); - vertex_handle_to_iterator_.emplace(vertex_handle, vit); + vertex_handle_to_iterator_.push_back(vit); vertex_handle++; } } diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 3aa835ec..f64a8ea9 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- double max_alpha_square_value = 1e10; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points, max_alpha_square_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, max_alpha_square_value); std::cout << "========== Alpha_complex_from_points ==========" << std::endl; -- cgit v1.2.3 From 8881190bccba9da4af0a07c701369099fd7f2277 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 12 Nov 2015 16:26:05 +0000 Subject: code review fix prune_above_filtration and remove_maximal_simplex in Simplex_tree.h make_filtration_non_decreasing and rec_make_filtration_non_decreasing in Simplex_tree.h git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@910 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a20c9da65a5a3294e42ad2dd45a399d77fb5ad30 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 5 ++ .../example/Alpha_complex_from_off.cpp | 6 +- src/Alpha_complex/example/CMakeLists.txt | 2 + src/Alpha_complex/include/gudhi/Alpha_complex.h | 24 ++++-- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 54 +++++++++---- src/Simplex_tree/include/gudhi/Simplex_tree.h | 91 ++++++++++++++++++++++ .../include/gudhi/Delaunay_triangulation_off_io.h | 7 +- src/common/test/dtoffrw_alphashapedoc_result.off | 12 +-- 8 files changed, 166 insertions(+), 35 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 2cb37578..1fb8fdee 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -20,6 +20,9 @@ * along with this program. If not, see . */ +#ifndef INTRO_ALPHA_COMPLEX_H_ +#define INTRO_ALPHA_COMPLEX_H_ + // needs namespace for Doxygen to link on classes namespace Gudhi { // needs namespace for Doxygen to link on classes @@ -117,3 +120,5 @@ namespace alphacomplex { } // namespace alphacomplex } // namespace Gudhi + +#endif // INTRO_ALPHA_COMPLEX_H_ diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index e140fe3d..cd6f5a4b 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -25,7 +25,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); - + // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- @@ -35,14 +35,14 @@ int main(int argc, char **argv) { std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - if (alpha_complex_from_file.filtration(f_simplex) <= alpha_complex_from_file.filtration()) { + //if (alpha_complex_from_file.filtration(f_simplex) <= alpha_complex_from_file.filtration()) { std::cout << " ( "; for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { std::cout << vertex << " "; } std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; std::cout << std::endl; - } + //} } return 0; } diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 10b87f04..24f3a9dc 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIAlphaShapesExample) +add_executable ( flat flat.cpp ) + # need CGAL 4.7 # cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. if(CGAL_FOUND) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 562b80c3..10b290b5 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -105,6 +105,7 @@ class Alpha_complex : public Simplex_tree<> { * the Alpha_complex. * * @param[in] off_file_name OFF file [path and] name. + * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. */ Alpha_complex(const std::string& off_file_name, Filtration_value max_alpha_square = std::numeric_limits::infinity()) @@ -115,25 +116,24 @@ class Alpha_complex : public Simplex_tree<> { exit(-1); // ----- >> } triangulation_ = off_reader.get_complex(); - set_filtration(max_alpha_square); - init(); + init(max_alpha_square); } /** \brief Alpha_complex constructor from a Delaunay triangulation. * * @param[in] triangulation_ptr Pointer on a Delaunay triangulation. + * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. */ Alpha_complex(Delaunay_triangulation* triangulation_ptr, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(triangulation_ptr) { - set_filtration(max_alpha_square); - init(); + init(max_alpha_square); } /** \brief Alpha_complex constructor from a list of points. * - * @param[in] dimension Dimension of points to be inserted. * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d + * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. @@ -155,8 +155,7 @@ class Alpha_complex : public Simplex_tree<> { std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << std::endl; exit(-1); // ----- >> } - set_filtration(max_alpha_square); - init(); + init(max_alpha_square); } /** \brief Alpha_complex destructor from a Delaunay triangulation. @@ -180,12 +179,14 @@ class Alpha_complex : public Simplex_tree<> { private: /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * + * @param[in] max_alpha_square maximum for alpha square value. + * * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more * than 0. * * Initialization can be launched once. */ - void init() { + void init(Filtration_value max_alpha_square) { if (triangulation_ == nullptr) { std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation" << std::endl; return; // ----- >> @@ -287,6 +288,13 @@ class Alpha_complex : public Simplex_tree<> { } } // -------------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------------- + // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension + make_filtration_non_decreasing(); + // Remove all simplices that have a filtration value greater than max_alpha_square + prune_above_filtration(max_alpha_square); + // -------------------------------------------------------------------------------------------- } template diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index f64a8ea9..2912019d 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -88,20 +88,9 @@ BOOST_AUTO_TEST_CASE(ALPHA_DOC_OFF_file_filtered) { std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 25; + const int NUMBER_OF_SIMPLICES = 23; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); - - int num_filtered_simplices = 0; - for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - if (alpha_complex_from_file.filtration(f_simplex) <= alpha_complex_from_file.filtration()) { - num_filtered_simplices++; - } - } - const int NUMBER_OF_FILTERED_SIMPLICES = 23; - std::cout << "num_filtered_simplices=" << num_filtered_simplices << std::endl; - BOOST_CHECK(num_filtered_simplices == NUMBER_OF_FILTERED_SIMPLICES); - } bool are_almost_the_same(float a, float b) { @@ -140,8 +129,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - double max_alpha_square_value = 1e10; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, max_alpha_square_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points); std::cout << "========== Alpha_complex_from_points ==========" << std::endl; @@ -210,4 +198,42 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { BOOST_CHECK_THROW (alpha_complex_from_points.get_point(4), std::out_of_range); BOOST_CHECK_THROW (alpha_complex_from_points.get_point(-1), std::out_of_range); BOOST_CHECK_THROW (alpha_complex_from_points.get_point(1234), std::out_of_range); + + // Test after prune_above_filtration + alpha_complex_from_points.prune_above_filtration(0.6); + // Another way to check num_simplices + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + num_simplices = 0; + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + num_simplices++; + std::cout << " ( "; + for (auto vertex : alpha_complex_from_points.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << alpha_complex_from_points.filtration(f_simplex) << "] "; + std::cout << std::endl; + } + BOOST_CHECK(num_simplices == 10); + std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_simplices() == 10); + + std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_points.dimension() == 4); + std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() == 4); + + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + switch (alpha_complex_from_points.dimension(f_simplex)) { + case 0: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 0.0)); + break; + case 1: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 1.0/2.0)); + break; + default: + BOOST_CHECK(false); // Shall not happen + break; + } + } + } diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 35d839e2..8c1beaef 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -39,6 +39,7 @@ #include #include #include // for greater<> +#include // for numeric_limits infinity namespace Gudhi { /** \defgroup simplex_tree Filtered Complexes @@ -1098,6 +1099,96 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } + + public: + /** \brief Browse the simplex tree to ensure the filtration is not decreasing. + * @return The filtration modification information in order to trigger initialize_filtration. + * \warning initialize_filtration is launched again in case of filtration modification change. + */ + bool make_filtration_non_decreasing() { + bool modified = false; + for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { + if (has_children(sh)) { + modified = modified || rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + } + } + if (modified) { + initialize_filtration(); + } + return modified; + } + + private: + /** \brief Recursively Browse the simplex tree to ensure the filtration is not decreasing. + * @param[in] sib Siblings to be parsed. + * @param[in] upper_filtration Upper level filtration value in the simplex tree. + * @return The filtration modification information in order to trigger initialize_filtration. + */ + bool rec_make_filtration_non_decreasing(Siblings * sib, Filtration_value upper_filtration) { + bool modified = false; + for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { + if (sh->second.filtration() < upper_filtration) { + // Store the filtration modification information + modified = true; + std::cout << "modified" << std::endl; + sh->second.assign_filtration(upper_filtration); + } + if (has_children(sh)) { + modified = modified || rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + } + } + // Make the modified information to be traced by upper call + return modified; + } + + public: + /** \brief Prune above filtration value given as parameter. + * @param[in] filtration Maximum threshold value. + * \warning threshold_ is set from filtration given as parameter. + * \warning The filtration must be valid. If the filtration has not been initialized yet, the method initializes it + * (i.e. order the simplices). If the complex has changed since the last time the filtration was initialized, please + * call `initialize_filtration()` to recompute it. + */ + void prune_above_filtration(Filtration_value filtration) { + threshold_ = filtration; + if (filtration != std::numeric_limits::infinity()) { + // Initialize filtration_vect_ if required + if (filtration_vect_.empty()) { + initialize_filtration(); + } + + // Loop in reverse mode until threshold is reached + auto f_simplex = filtration_vect_.rbegin(); + for (; f_simplex != filtration_vect_.rend() && ((*f_simplex)->second.filtration() > threshold_); f_simplex++) { + remove_maximal_simplex(*f_simplex); + } + // Do not forget to update filtration_vect_ - resize is enough + std::size_t new_size = filtration_vect_.size() - (f_simplex - filtration_vect_.rbegin()); + filtration_vect_.resize(new_size); + } + } + + private: + /** \brief Remove a maximal simplex. + * @param[in] sh Simplex handle on the maximal simplex to remove. + * \warning Exception std::invalid_argument is thrown in sh has children. + */ + void remove_maximal_simplex(Simplex_handle sh) { + // Guarantee the simplex is maximal + if (has_children(sh)) { + throw std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument is not a maximal simplex"); + } + // Simplex is a leaf, it means the child is the Siblings owning the leaf. + Siblings* child = sh->second.children(); + if (child->size() > 1) { + // Not alone, just remove it from members + child->members().erase(sh->first); + } else { + // Sibling is emptied : must be deleted, and its parent must point on his own Sibling + child->oncles()->members().at(child->parent()).assign_children(child->oncles()); + delete child; + } + } private: Vertex_handle null_vertex_; diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 47066a94..4d26bb71 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -19,8 +19,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ -#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ +#ifndef DELAUNAY_TRIANGULATION_OFF_IO_H_ +#define DELAUNAY_TRIANGULATION_OFF_IO_H_ #include #include @@ -256,7 +256,6 @@ class Delaunay_triangulation_off_writer { // no endl on next line - don't know why... stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << complex_ptr->number_of_finite_full_cells() << " 0"; - } // bimap to retrieve vertex handles from points and vice versa @@ -305,4 +304,4 @@ class Delaunay_triangulation_off_writer { } // namespace Gudhi -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ +#endif // DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off index 13c255c6..03b7ca75 100644 --- a/src/common/test/dtoffrw_alphashapedoc_result.off +++ b/src/common/test/dtoffrw_alphashapedoc_result.off @@ -7,9 +7,9 @@ nOFF 0 14 2 19 9 17 -3 1 2 3 -3 4 3 2 -3 5 1 3 -3 5 3 7 -3 7 3 4 -3 6 5 7 +3 0 1 2 +3 3 2 1 +3 4 0 2 +3 4 2 6 +3 6 2 3 +3 5 4 6 -- cgit v1.2.3 From c972b77524faec5d6f297d442539f65b9351654e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 13 Nov 2015 16:41:12 +0000 Subject: Utils.h -> Debug_utils.h More verbose in debug mode (use NDEBUG instead of DEBUG_TRACES) GUDHI_CHECK function to throw in debug or ignore in release mode git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@911 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 250dc0c0f5146f0b9e3fce0e9a8ca0da6af7cf98 --- CMakeLists.txt | 21 +++-- src/Alpha_complex/example/CMakeLists.txt | 4 - src/Alpha_complex/include/gudhi/Alpha_complex.h | 96 +++++++++------------- src/Alpha_complex/test/CMakeLists.txt | 4 - src/CMakeLists.txt | 13 ++- .../policies/Link_condition_valid_contraction.h | 2 +- src/Contraction/include/gudhi/Edge_contraction.h | 2 +- .../include/gudhi/Skeleton_blocker_contractor.h | 2 +- src/Simplex_tree/include/gudhi/Simplex_tree.h | 40 ++++----- .../include/gudhi/Skeleton_blocker.h | 2 +- .../Skeleton_blocker_sub_complex.h | 2 +- .../Skeleton_blockers_simplices_iterators.h | 2 +- .../include/gudhi/Skeleton_blocker_complex.h | 2 +- .../gudhi/Skeleton_blocker_geometric_complex.h | 2 +- .../include/gudhi/Skeleton_blocker_link_complex.h | 2 +- .../test/TestSkeletonBlockerComplex.cpp | 2 +- .../example/Delaunay_triangulation_off_rw.cpp | 5 ++ src/common/include/gudhi/Debug_utils.h | 53 ++++++++++++ .../include/gudhi/Delaunay_triangulation_off_io.h | 19 ++--- src/common/include/gudhi/Utils.h | 46 ----------- 20 files changed, 162 insertions(+), 159 deletions(-) create mode 100644 src/common/include/gudhi/Debug_utils.h delete mode 100644 src/common/include/gudhi/Utils.h (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index 460196d7..b7fb4540 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,17 +2,26 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIdev) include(CMakeGUDHIVersion.txt) -# Generate GUDHI official version file -configure_file(GUDHIVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIVersion.cmake" @ONLY) -find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework chrono timer program_options thread REQUIRED) +if (NOT CMAKE_BUILD_TYPE) + # Set default build type to Release + set(CMAKE_BUILD_TYPE "Release") +endif() + +if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DNDEBUG) +endif() + +enable_testing() set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/src/cmake/modules/") -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/src/cmake/modules/") -message("CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}") message("CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") -enable_testing() +# Generate GUDHI official version file +configure_file(GUDHIVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIVersion.cmake" @ONLY) + +find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework chrono timer program_options thread REQUIRED) if(MSVC) # Turn off some VC++ warnings diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 24f3a9dc..47e42b72 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -29,10 +29,6 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 10b290b5..2cc93a0a 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -26,6 +26,7 @@ // to construct a simplex_tree from Delaunay_triangulation #include #include +#include #include #include // isnan, fmax @@ -39,6 +40,7 @@ #include // NaN #include #include // std::pair +#include namespace Gudhi { @@ -112,7 +114,7 @@ class Alpha_complex : public Simplex_tree<> { : triangulation_(nullptr) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { - std::cerr << "Alpha_complex - Unable to read file " << off_file_name << std::endl; + std::cerr << "Alpha_complex - Unable to read file " << off_file_name; exit(-1); // ----- >> } triangulation_ = off_reader.get_complex(); @@ -137,6 +139,8 @@ class Alpha_complex : public Simplex_tree<> { * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. + * \warning In debug mode, the exception std::invalid_argument is thrown if an empty input point range is passed as + * argument. */ template Alpha_complex(const InputPointRange& points, @@ -144,18 +148,24 @@ class Alpha_complex : public Simplex_tree<> { : triangulation_(nullptr) { auto first = std::begin(points); auto last = std::end(points); - // point_dimension function initialization - Point_Dimension point_dimension = kernel_.point_dimension_d_object(); + + GUDHI_CHECK((first == last), + std::invalid_argument ("Alpha_complex::Alpha_complex(InputPointRange) - Empty input point range")); + + if (first != last) { + // point_dimension function initialization + Point_Dimension point_dimension = kernel_.point_dimension_d_object(); - // Delaunay triangulation is point dimension minus one. - triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); + // Delaunay triangulation is point dimension minus one. + triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); - size_type inserted = triangulation_->insert(first, last); - if (inserted != (last -first)) { - std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << std::endl; - exit(-1); // ----- >> + size_type inserted = triangulation_->insert(first, last); + if (inserted != (last -first)) { + std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first); + exit(-1); // ----- >> + } + init(max_alpha_square); } - init(max_alpha_square); } /** \brief Alpha_complex destructor from a Delaunay triangulation. @@ -188,23 +198,25 @@ class Alpha_complex : public Simplex_tree<> { */ void init(Filtration_value max_alpha_square) { if (triangulation_ == nullptr) { - std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation" << std::endl; + std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation"; return; // ----- >> } if (triangulation_->number_of_vertices() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices" << std::endl; + std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices"; return; // ----- >> } if (triangulation_->maximal_dimension() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation" << std::endl; + std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation"; return; // ----- >> } if (num_vertices() > 0) { - std::cerr << "Alpha_complex init - Cannot init twice" << std::endl; + std::cerr << "Alpha_complex init - Cannot init twice"; return; // ----- >> } set_dimension(triangulation_->maximal_dimension()); + // set_filtration to +inf for prune_above_filtration to be done (if necessary) + set_filtration(std::numeric_limits::infinity()); // -------------------------------------------------------------------------------------------- // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa @@ -213,9 +225,9 @@ class Alpha_complex : public Simplex_tree<> { // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { if (!triangulation_->is_infinite(*vit)) { -#ifdef DEBUG_TRACES - std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; -#endif // DEBUG_TRACES + DBGMSG("Vertex insertion - ", vertex_handle); + DBGMSG(" -> ", vit->point()); + vertex_iterator_to_handle_.emplace(vit, vertex_handle); vertex_handle_to_iterator_.push_back(vit); vertex_handle++; @@ -227,21 +239,12 @@ class Alpha_complex : public Simplex_tree<> { // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { Vector_vertex vertexVector; -#ifdef DEBUG_TRACES - std::cout << "Simplex_tree insertion "; -#endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { if (*vit != nullptr) { -#ifdef DEBUG_TRACES - std::cout << " " << vertex_iterator_to_handle_[*vit]; -#endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure vertexVector.push_back(vertex_iterator_to_handle_[*vit]); } } -#ifdef DEBUG_TRACES - std::cout << std::endl; -#endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); @@ -256,18 +259,11 @@ class Alpha_complex : public Simplex_tree<> { int f_simplex_dim = dimension(f_simplex); if (decr_dim == f_simplex_dim) { Vector_of_CGAL_points pointVector; -#ifdef DEBUG_TRACES - std::cout << "Sigma of dim " << decr_dim << " is"; -#endif // DEBUG_TRACES + DBGMSG("Sigma of dim ", decr_dim); for (auto vertex : simplex_vertex_range(f_simplex)) { pointVector.push_back(get_point(vertex)); -#ifdef DEBUG_TRACES - std::cout << " " << vertex; -#endif // DEBUG_TRACES } -#ifdef DEBUG_TRACES - std::cout << std::endl; -#endif // DEBUG_TRACES + DBGCONT(simplex_vertex_range(f_simplex)); // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) if (isnan(filtration(f_simplex))) { Filtration_value alpha_complex_filtration = 0.0; @@ -279,9 +275,7 @@ class Alpha_complex : public Simplex_tree<> { alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } assign_filtration(f_simplex, alpha_complex_filtration); -#ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl; -#endif // DEBUG_TRACES + DBGMSG("filt(Sigma) is NaN : filt(Sigma) =", filtration(f_simplex)); } propagate_alpha_filtration(f_simplex, decr_dim); } @@ -301,23 +295,16 @@ class Alpha_complex : public Simplex_tree<> { void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { // ### Foreach Tau face of Sigma for (auto f_boundary : boundary_simplex_range(f_simplex)) { -#ifdef DEBUG_TRACES - std::cout << " | --------------------------------------------------\n"; - std::cout << " | Tau "; - for (auto vertex : simplex_vertex_range(f_boundary)) { - std::cout << vertex << " "; - } - std::cout << "is a face of Sigma\n"; - std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl; -#endif // DEBUG_TRACES + DBG("------------- TAU -------------"); + DBGCONT(simplex_vertex_range(f_boundary)); + DBG("is a face of Sigma"); + DBGMSG("isnan(filtration(Tau)=", isnan(filtration(f_boundary))); // ### If filt(Tau) is not NaN if (!isnan(filtration(f_boundary))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); assign_filtration(f_boundary, alpha_complex_filtration); -#ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl; -#endif // DEBUG_TRACES + DBGMSG("filt(Tau) = fmin(filt(Tau), filt(Sigma)) = ", filtration(f_boundary)); // ### Else } else { // No need to compute is_gabriel for dimension <= 2 @@ -344,17 +331,14 @@ class Alpha_complex : public Simplex_tree<> { Is_Gabriel is_gabriel = kernel_.side_of_bounded_sphere_d_object(); bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), point_for_gabriel) != CGAL::ON_BOUNDED_SIDE; -#ifdef DEBUG_TRACES - std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; -#endif // DEBUG_TRACES + DBGMSG("Tau is_gabriel(Sigma)=", is_gab); + DBGMSG(" - vertexForGabriel=", vertexForGabriel); // ### If Tau is not Gabriel of Sigma if (false == is_gab) { // ### filt(Tau) = filt(Sigma) Filtration_value alpha_complex_filtration = filtration(f_simplex); assign_filtration(f_boundary, alpha_complex_filtration); -#ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl; -#endif // DEBUG_TRACES + DBGMSG("filt(Tau) = filt(Sigma) = ", filtration(f_boundary)); } } } diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 847581aa..fa24e1b1 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -14,10 +14,6 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) include_directories (BEFORE "../../include") - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp ) target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd7f4991..0f946e3b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,15 +3,22 @@ project(GUDHI) include("CMakeGUDHIVersion.txt") +if (NOT CMAKE_BUILD_TYPE) + # Set default build type to Release + set(CMAKE_BUILD_TYPE "Release") +endif() + +if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DNDEBUG) +endif() + enable_testing() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") find_package(Boost REQUIRED COMPONENTS system filesystem program_options chrono timer REQUIRED) -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release") -endif() if(MSVC) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4668 /wd4311 /wd4800 /wd4820 /wd4503 /wd4244 /wd4345 /wd4996 /wd4396 /wd4018") else() diff --git a/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h b/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h index 919df243..250bba27 100644 --- a/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h +++ b/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h @@ -23,8 +23,8 @@ #ifndef CONTRACTION_POLICIES_LINK_CONDITION_VALID_CONTRACTION_H_ #define CONTRACTION_POLICIES_LINK_CONDITION_VALID_CONTRACTION_H_ -#include #include +#include namespace Gudhi { diff --git a/src/Contraction/include/gudhi/Edge_contraction.h b/src/Contraction/include/gudhi/Edge_contraction.h index 349bb7d8..011ca9bd 100644 --- a/src/Contraction/include/gudhi/Edge_contraction.h +++ b/src/Contraction/include/gudhi/Edge_contraction.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include namespace Gudhi { diff --git a/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h b/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h index 2759b540..47d798c0 100644 --- a/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h +++ b/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h @@ -37,7 +37,7 @@ #include #include -#include +#include #include diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 8c1beaef..dc8591fc 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -39,7 +40,8 @@ #include #include #include // for greater<> -#include // for numeric_limits infinity +#include +#include // Inf namespace Gudhi { /** \defgroup simplex_tree Filtered Complexes @@ -717,7 +719,7 @@ class Simplex_tree { } else if (the_simplex.size() == 1) { // When reaching the end of recursivity, vector of simplices shall be empty and filled on back recursive if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)) { - std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty" << std::endl; + std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty"; exit(-1); } std::vector first_simplex(1, the_simplex.back()); @@ -726,7 +728,7 @@ class Simplex_tree { insert_result = insert_vertex_vector(first_simplex, filtration); } else { - std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error" << std::endl; + std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error"; exit(-1); } return insert_result; @@ -1099,22 +1101,23 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } - + public: /** \brief Browse the simplex tree to ensure the filtration is not decreasing. - * @return The filtration modification information in order to trigger initialize_filtration. - * \warning initialize_filtration is launched again in case of filtration modification change. + * The simplex tree is browsed starting from the root until the leaf, and the filtration values are set with their + * parent value (increased), in case the values are decreasing. + * @return The filtration modification information. + * \warning Some simplex tree functions require the filtration to be valid. `make_filtration_non_decreasing()` + * function is not launching `initialize_filtration()` but returns the filtration modification information. If the + * complex has changed , please call `initialize_filtration()` to recompute it. */ bool make_filtration_non_decreasing() { bool modified = false; for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { if (has_children(sh)) { - modified = modified || rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); } } - if (modified) { - initialize_filtration(); - } return modified; } @@ -1134,7 +1137,7 @@ class Simplex_tree { sh->second.assign_filtration(upper_filtration); } if (has_children(sh)) { - modified = modified || rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); } } // Make the modified information to be traced by upper call @@ -1150,8 +1153,8 @@ class Simplex_tree { * call `initialize_filtration()` to recompute it. */ void prune_above_filtration(Filtration_value filtration) { - threshold_ = filtration; - if (filtration != std::numeric_limits::infinity()) { + if (filtration < threshold_) { + threshold_ = filtration; // Initialize filtration_vect_ if required if (filtration_vect_.empty()) { initialize_filtration(); @@ -1168,16 +1171,15 @@ class Simplex_tree { } } - private: /** \brief Remove a maximal simplex. * @param[in] sh Simplex handle on the maximal simplex to remove. - * \warning Exception std::invalid_argument is thrown in sh has children. + * \warning In debug mode, the exception std::invalid_argument is thrown if sh has children. */ void remove_maximal_simplex(Simplex_handle sh) { - // Guarantee the simplex is maximal - if (has_children(sh)) { - throw std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument is not a maximal simplex"); - } + // Guarantee the simplex has no children + GUDHI_CHECK(has_children(sh), + std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument is not a maximal simplex")); + // Simplex is a leaf, it means the child is the Siblings owning the leaf. Siblings* child = sh->second.children(); if (child->size() > 1) { diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h index 3be480fd..20df93eb 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h @@ -31,7 +31,7 @@ #include #include -#include // xxx +#include namespace Gudhi { diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h index b33b9606..1b1fe3f0 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h index 4d71b3f5..27411fc1 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h index d26d12b0..dc2d9e29 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h index b8395251..3725b7a2 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h @@ -22,9 +22,9 @@ #ifndef SKELETON_BLOCKER_GEOMETRIC_COMPLEX_H_ #define SKELETON_BLOCKER_GEOMETRIC_COMPLEX_H_ -#include #include #include +#include namespace Gudhi { diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h index 95d8fa97..3d0039a1 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h @@ -22,8 +22,8 @@ #ifndef SKELETON_BLOCKER_LINK_COMPLEX_H_ #define SKELETON_BLOCKER_LINK_COMPLEX_H_ -#include #include +#include namespace Gudhi { diff --git a/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp b/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp index 319e3c43..d56a5c91 100644 --- a/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp +++ b/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "gudhi/Utils.h" +#include "gudhi/Debug_utils.h" #include "gudhi/Test.h" #include "gudhi/Skeleton_blocker.h" //#include "gudhi/Skeleton_blocker_link_complex.h" diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp index 75e4fafb..12accd10 100644 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -24,6 +24,11 @@ int main(int argc, char **argv) { usage(argv[0]); } + +#ifdef GUDHI_NDEBUG + std::cout << "pouet pouet !!" << std::endl; +#endif + std::string offInputFile(argv[1]); // Read the OFF file (input file name given as parameter) and triangulates points Gudhi::Delaunay_triangulation_off_reader off_reader(offInputFile); diff --git a/src/common/include/gudhi/Debug_utils.h b/src/common/include/gudhi/Debug_utils.h new file mode 100644 index 00000000..c479d435 --- /dev/null +++ b/src/common/include/gudhi/Debug_utils.h @@ -0,0 +1,53 @@ +/* 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): David Salinas + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France) + * + * 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 . + */ +#ifndef DEBUG_UTILS_H_ +#define DEBUG_UTILS_H_ + +#include + +#ifdef NDEBUG + // GUDHI_NDEBUG is the Gudhi official flag for debug mode. + #define GUDHI_NDEBUG +#endif + +#define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl + +#ifdef GUDHI_NDEBUG + #define DBG(a) std::cout << "DBG: " << (a) << std::endl + #define DBGMSG(a, b) std::cout << "DBG: " << a << b << std::endl + #define DBGVALUE(a) std::cout << "DBG: " << #a << ": " << a << std::endl + #define DBGCONT(a) std::cout << "DBG: container " << #a << " -> "; for (auto x : a) std::cout << x << ","; std::cout << std::endl +#else + #define DBG(a) (void) 0 + #define DBGMSG(a, b) (void) 0 + #define DBGVALUE(a) (void) 0 + #define DBGCONT(a) (void) 0 +#endif + +// GUDHI_CHECK throw an exception on condition in debug mode, but does nothing in release mode +#ifdef GUDHI_NDEBUG + #define GUDHI_CHECK(cond, excpt) if (cond) throw excpt +#else + #define GUDHI_CHECK(cond, excpt) (void) 0 +#endif + +#endif // DEBUG_UTILS_H_ diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 4d26bb71..dfa70e40 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -22,6 +22,8 @@ #ifndef DELAUNAY_TRIANGULATION_OFF_IO_H_ #define DELAUNAY_TRIANGULATION_OFF_IO_H_ +#include + #include #include #include @@ -64,10 +66,10 @@ class Delaunay_triangulation_off_visitor_reader { * @param[in] num_edges number of edges in the OFF file (not used). */ void init(int dim, int num_vertices, int num_faces, int num_edges) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << - num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; -#endif // DEBUG_TRACES + DBGMSG("Delaunay_triangulation_off_visitor_reader::init - dim=", dim); + DBGMSG(" - num_vertices=", num_vertices); + DBGMSG(" - num_faces=", num_faces); + DBGMSG(" - num_edges=", num_edges); if (num_faces > 0) { std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << "file for Delaunay triangulation - faces are computed." << std::endl; @@ -88,13 +90,8 @@ class Delaunay_triangulation_off_visitor_reader { * @param[in] point vector of vertex coordinates. */ void point(const std::vector& point) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::point "; - for (auto coordinate : point) { - std::cout << coordinate << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES + DBG("Delaunay_triangulation_off_visitor_reader::point"); + DBGCONT(point); complex_->insert(Point(point.size(), point.begin(), point.end())); } diff --git a/src/common/include/gudhi/Utils.h b/src/common/include/gudhi/Utils.h deleted file mode 100644 index 43916f11..00000000 --- a/src/common/include/gudhi/Utils.h +++ /dev/null @@ -1,46 +0,0 @@ -/* 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): David Salinas - * - * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France) - * - * 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 . - */ -#ifndef UTILS_H_ -#define UTILS_H_ - - -#define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl - -// #define DBG_VERBOSE -#ifdef DBG_VERBOSE -#define DBG(a) std::cerr << "DBG: " << (a) << std::endl -#define DBGMSG(a, b) std::cerr << "DBG: " << a << b << std::endl -#define DBGVALUE(a) std::cerr << "DBG: " << #a << ": " << a << std::endl -#define DBGCONT(a) std::cerr << "DBG: container " << #a << " -> "; for (auto x : a) std::cerr << x << ","; std::cerr << -std::endl -#else -// #define DBG(a) a -// #define DBGMSG(a,b) b -// #define DBGVALUE(a) a -// #define DBGCONT(a) a -#define DBG(a) -#define DBGMSG(a, b) -#define DBGVALUE(a) -#define DBGCONT(a) -#endif - -#endif // UTILS_H_ -- cgit v1.2.3 From fe78c077b00e91b3d316f1d64541008a615664e7 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 18 Nov 2015 12:03:43 +0000 Subject: rev911 rollback code review fix fix prune_above_filtration removing every simplices git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@927 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1660da972bd5198214a0f0384be9be66a5312e74 --- CMakeLists.txt | 5 -- src/Alpha_complex/example/CMakeLists.txt | 6 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 67 ++++++++++++++++------ src/CMakeLists.txt | 5 -- src/Simplex_tree/include/gudhi/Simplex_tree.h | 10 ++-- src/common/example/CMakeLists.txt | 4 ++ .../example/Delaunay_triangulation_off_rw.cpp | 5 -- src/common/include/gudhi/Debug_utils.h | 24 ++++---- .../include/gudhi/Delaunay_triangulation_off_io.h | 19 +++--- 9 files changed, 86 insertions(+), 59 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index b7fb4540..197b6f95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,11 +8,6 @@ if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") endif() -if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DNDEBUG) -endif() - enable_testing() set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/src/cmake/modules/") diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 47e42b72..10b87f04 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIAlphaShapesExample) -add_executable ( flat flat.cpp ) - # need CGAL 4.7 # cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. if(CGAL_FOUND) @@ -29,6 +27,10 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 2cc93a0a..6adfa2e6 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -114,7 +114,7 @@ class Alpha_complex : public Simplex_tree<> { : triangulation_(nullptr) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { - std::cerr << "Alpha_complex - Unable to read file " << off_file_name; + std::cerr << "Alpha_complex - Unable to read file " << off_file_name << "\n"; exit(-1); // ----- >> } triangulation_ = off_reader.get_complex(); @@ -161,7 +161,7 @@ class Alpha_complex : public Simplex_tree<> { size_type inserted = triangulation_->insert(first, last); if (inserted != (last -first)) { - std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first); + std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << "\n"; exit(-1); // ----- >> } init(max_alpha_square); @@ -198,19 +198,19 @@ class Alpha_complex : public Simplex_tree<> { */ void init(Filtration_value max_alpha_square) { if (triangulation_ == nullptr) { - std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation"; + std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation\n"; return; // ----- >> } if (triangulation_->number_of_vertices() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices"; + std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices\n"; return; // ----- >> } if (triangulation_->maximal_dimension() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation"; + std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation\n"; return; // ----- >> } if (num_vertices() > 0) { - std::cerr << "Alpha_complex init - Cannot init twice"; + std::cerr << "Alpha_complex init - Cannot init twice\n"; return; // ----- >> } @@ -225,8 +225,9 @@ class Alpha_complex : public Simplex_tree<> { // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { if (!triangulation_->is_infinite(*vit)) { - DBGMSG("Vertex insertion - ", vertex_handle); - DBGMSG(" -> ", vit->point()); +#ifdef DEBUG_TRACES + std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; +#endif // DEBUG_TRACES vertex_iterator_to_handle_.emplace(vit, vertex_handle); vertex_handle_to_iterator_.push_back(vit); @@ -239,12 +240,21 @@ class Alpha_complex : public Simplex_tree<> { // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { Vector_vertex vertexVector; +#ifdef DEBUG_TRACES + std::cout << "Simplex_tree insertion "; +#endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { if (*vit != nullptr) { +#ifdef DEBUG_TRACES + std::cout << " " << vertex_iterator_to_handle_[*vit]; +#endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure vertexVector.push_back(vertex_iterator_to_handle_[*vit]); } } +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); @@ -259,11 +269,18 @@ class Alpha_complex : public Simplex_tree<> { int f_simplex_dim = dimension(f_simplex); if (decr_dim == f_simplex_dim) { Vector_of_CGAL_points pointVector; - DBGMSG("Sigma of dim ", decr_dim); +#ifdef DEBUG_TRACES + std::cout << "Sigma of dim " << decr_dim << " is"; +#endif // DEBUG_TRACES for (auto vertex : simplex_vertex_range(f_simplex)) { pointVector.push_back(get_point(vertex)); +#ifdef DEBUG_TRACES + std::cout << " " << vertex; +#endif // DEBUG_TRACES } - DBGCONT(simplex_vertex_range(f_simplex)); +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) if (isnan(filtration(f_simplex))) { Filtration_value alpha_complex_filtration = 0.0; @@ -275,7 +292,9 @@ class Alpha_complex : public Simplex_tree<> { alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } assign_filtration(f_simplex, alpha_complex_filtration); - DBGMSG("filt(Sigma) is NaN : filt(Sigma) =", filtration(f_simplex)); +#ifdef DEBUG_TRACES + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl; +#endif // DEBUG_TRACES } propagate_alpha_filtration(f_simplex, decr_dim); } @@ -295,16 +314,23 @@ class Alpha_complex : public Simplex_tree<> { void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { // ### Foreach Tau face of Sigma for (auto f_boundary : boundary_simplex_range(f_simplex)) { - DBG("------------- TAU -------------"); - DBGCONT(simplex_vertex_range(f_boundary)); - DBG("is a face of Sigma"); - DBGMSG("isnan(filtration(Tau)=", isnan(filtration(f_boundary))); +#ifdef DEBUG_TRACES + std::cout << " | --------------------------------------------------\n"; + std::cout << " | Tau "; + for (auto vertex : simplex_vertex_range(f_boundary)) { + std::cout << vertex << " "; + } + std::cout << "is a face of Sigma\n"; + std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl; +#endif // DEBUG_TRACES // ### If filt(Tau) is not NaN if (!isnan(filtration(f_boundary))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); assign_filtration(f_boundary, alpha_complex_filtration); - DBGMSG("filt(Tau) = fmin(filt(Tau), filt(Sigma)) = ", filtration(f_boundary)); +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES // ### Else } else { // No need to compute is_gabriel for dimension <= 2 @@ -331,14 +357,17 @@ class Alpha_complex : public Simplex_tree<> { Is_Gabriel is_gabriel = kernel_.side_of_bounded_sphere_d_object(); bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), point_for_gabriel) != CGAL::ON_BOUNDED_SIDE; - DBGMSG("Tau is_gabriel(Sigma)=", is_gab); - DBGMSG(" - vertexForGabriel=", vertexForGabriel); +#ifdef DEBUG_TRACES + std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; +#endif // DEBUG_TRACES // ### If Tau is not Gabriel of Sigma if (false == is_gab) { // ### filt(Tau) = filt(Sigma) Filtration_value alpha_complex_filtration = filtration(f_simplex); assign_filtration(f_boundary, alpha_complex_filtration); - DBGMSG("filt(Tau) = filt(Sigma) = ", filtration(f_boundary)); +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES } } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0f946e3b..9d1eac80 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,11 +8,6 @@ if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") endif() -if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DNDEBUG) -endif() - enable_testing() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index dc8591fc..9b4d6af6 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1173,17 +1173,19 @@ class Simplex_tree { /** \brief Remove a maximal simplex. * @param[in] sh Simplex handle on the maximal simplex to remove. + * \pre Please check the simplex has no coface before removing it. * \warning In debug mode, the exception std::invalid_argument is thrown if sh has children. */ void remove_maximal_simplex(Simplex_handle sh) { // Guarantee the simplex has no children GUDHI_CHECK(has_children(sh), - std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument is not a maximal simplex")); - - // Simplex is a leaf, it means the child is the Siblings owning the leaf. + std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument has children")); + + // Simplex is a leaf, it means the child is the Siblings owning the leaf Siblings* child = sh->second.children(); - if (child->size() > 1) { + if ((child->size() > 1) || (child == root())) { // Not alone, just remove it from members + // Special case when child is the root of the simplex tree, just remove it from members child->members().erase(sh->first); } else { // Sibling is emptied : must be deleted, and its parent must point on his own Sibling diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index d29e31e7..089f0c04 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -26,6 +26,10 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp index 12accd10..75e4fafb 100644 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -24,11 +24,6 @@ int main(int argc, char **argv) { usage(argv[0]); } - -#ifdef GUDHI_NDEBUG - std::cout << "pouet pouet !!" << std::endl; -#endif - std::string offInputFile(argv[1]); // Read the OFF file (input file name given as parameter) and triangulates points Gudhi::Delaunay_triangulation_off_reader off_reader(offInputFile); diff --git a/src/common/include/gudhi/Debug_utils.h b/src/common/include/gudhi/Debug_utils.h index c479d435..48d61fef 100644 --- a/src/common/include/gudhi/Debug_utils.h +++ b/src/common/include/gudhi/Debug_utils.h @@ -24,14 +24,23 @@ #include -#ifdef NDEBUG - // GUDHI_NDEBUG is the Gudhi official flag for debug mode. - #define GUDHI_NDEBUG +#ifndef NDEBUG + // GUDHI_DEBUG is the Gudhi official flag for debug mode. + #define GUDHI_DEBUG +#endif + +// GUDHI_CHECK throw an exception on condition in debug mode, but does nothing in release mode +// Could assert in release mode, but cmake sets NDEBUG (for "NO DEBUG") in this mode, means assert does nothing. +#ifdef GUDHI_DEBUG + #define GUDHI_CHECK(cond, excpt) if (cond) throw excpt +#else + #define GUDHI_CHECK(cond, excpt) (void) 0 #endif #define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl -#ifdef GUDHI_NDEBUG +// #define DBG_VERBOSE +#ifdef DBG_VERBOSE #define DBG(a) std::cout << "DBG: " << (a) << std::endl #define DBGMSG(a, b) std::cout << "DBG: " << a << b << std::endl #define DBGVALUE(a) std::cout << "DBG: " << #a << ": " << a << std::endl @@ -43,11 +52,4 @@ #define DBGCONT(a) (void) 0 #endif -// GUDHI_CHECK throw an exception on condition in debug mode, but does nothing in release mode -#ifdef GUDHI_NDEBUG - #define GUDHI_CHECK(cond, excpt) if (cond) throw excpt -#else - #define GUDHI_CHECK(cond, excpt) (void) 0 -#endif - #endif // DEBUG_UTILS_H_ diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index dfa70e40..4d26bb71 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -22,8 +22,6 @@ #ifndef DELAUNAY_TRIANGULATION_OFF_IO_H_ #define DELAUNAY_TRIANGULATION_OFF_IO_H_ -#include - #include #include #include @@ -66,10 +64,10 @@ class Delaunay_triangulation_off_visitor_reader { * @param[in] num_edges number of edges in the OFF file (not used). */ void init(int dim, int num_vertices, int num_faces, int num_edges) { - DBGMSG("Delaunay_triangulation_off_visitor_reader::init - dim=", dim); - DBGMSG(" - num_vertices=", num_vertices); - DBGMSG(" - num_faces=", num_faces); - DBGMSG(" - num_edges=", num_edges); +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; +#endif // DEBUG_TRACES if (num_faces > 0) { std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << "file for Delaunay triangulation - faces are computed." << std::endl; @@ -90,8 +88,13 @@ class Delaunay_triangulation_off_visitor_reader { * @param[in] point vector of vertex coordinates. */ void point(const std::vector& point) { - DBG("Delaunay_triangulation_off_visitor_reader::point"); - DBGCONT(point); +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::point "; + for (auto coordinate : point) { + std::cout << coordinate << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES complex_->insert(Point(point.size(), point.begin(), point.end())); } -- cgit v1.2.3 From c79ddda239336378d50255ef99ea6c34ceefbb47 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 27 Nov 2015 17:05:22 +0000 Subject: After doc review git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@931 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 578da0e6fff453560e666e8f00147f9e10cb6de6 --- CMakeLists.txt | 6 + src/Alpha_complex/doc/Intro_alpha_complex.h | 91 +++- .../doc/alpha_complex_doc_alpha_shape.ipe | 482 --------------------- .../doc/alpha_complex_doc_alpha_shape.png | Bin 62759 -> 0 bytes .../doc/alpha_complex_representation.ipe | 321 ++++++++++++++ .../example/Alpha_complex_from_off.cpp | 16 +- .../example/Alpha_complex_from_points.cpp | 36 +- src/Alpha_complex/example/CMakeLists.txt | 4 - .../example/alphaoffreader_for_doc.txt | 27 -- .../example/alphaoffreader_for_doc_32.txt | 22 + .../example/alphaoffreader_for_doc_60.txt | 27 ++ src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 + src/CMakeLists.txt | 6 + src/Doxyfile | 3 +- src/GudhUI/CMakeLists.txt | 4 - src/Persistent_cohomology/example/CMakeLists.txt | 8 - src/common/doc/main_page.h | 2 +- src/common/example/CMakeLists.txt | 4 - 18 files changed, 486 insertions(+), 575 deletions(-) delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png create mode 100644 src/Alpha_complex/doc/alpha_complex_representation.ipe delete mode 100644 src/Alpha_complex/example/alphaoffreader_for_doc.txt create mode 100644 src/Alpha_complex/example/alphaoffreader_for_doc_32.txt create mode 100644 src/Alpha_complex/example/alphaoffreader_for_doc_60.txt (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index 197b6f95..d42f7af7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,12 @@ else() message(STATUS "boost include dirs:" ${Boost_INCLUDE_DIRS}) message(STATUS "boost library dirs:" ${Boost_LIBRARY_DIRS}) + if (DEBUG_TRACES) + # For programs to be more verbose + message(STATUS "DEBUG_TRACES are activated") + add_definitions(-DDEBUG_TRACES) + endif() + include_directories(src/common/include/) include_directories(src/Alpha_complex/include/) include_directories(src/Bottleneck/include/) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 1fb8fdee..685a4c2f 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -36,48 +36,58 @@ namespace alphacomplex { * * \section definition Definition * - * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation. + * Alpha_complex is a simplicial complex + * constructed from each finite cell of a Delaunay Triangulation. * * The filtration value of each simplex is computed from the alpha square value of the simplex if it is Gabriel or * from the alpha value of the simplex coface that makes the simplex not Gabriel. * - * Please refer to \cite AlphaShapesDefinition for a more complete alpha complex definition. + * All simplices that have a filtration value strictly greater than a given alpha square value are not inserted into + * the simplex. * - * Alpha complex are interesting because it looks like an \ref alpha-shape "Alpha shape" as described in - * \cite AlphaShapesIntroduction (an alpha complex concept vulgarization). + * \image html "alpha_complex_representation.png" "Alpha simplicial complex representation" * - * \section example Example + * Alpha_complex is constructing a `Simplex_tree` using Delaunay Triangulation + * \cite cgal:hdj-t-15b from CGAL (the Computational Geometry + * Algorithms Library \cite cgal:eb-15b). * - * This example loads points from an OFF file, builds the Delaunay triangulation from the points, and finally - * initialize the alpha complex with it. + * The complex is a template class requiring a dD Geometry Kernel + * \cite cgal:s-gkd-15b from CGAL as template. + * + * \section pointsexample Example from points + * + * This example builds the Delaunay triangulation from the given points in a 2D static kernel, and initializes the + * alpha complex with it. * * Then, it is asked to display information about the alpha complex. * - * \include Alpha_complex_from_off.cpp + * \include Alpha_complex_from_points.cpp * * When launching: * - * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off 60.0 + * \code $> ./alphapoints 60.0 * \endcode * * the program output is: * - * \include alphaoffreader_for_doc.txt + * \include alphaoffreader_for_doc_60.txt * * \section algorithm Algorithm * - * Data structure + * \subsection datastructure Data structure * * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. * (The filtration value is set to NaN, which stands for unknown value): * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" * - * Filtration value computation algorithm - * + * \subsection filtrationcomputation Filtration value computation algorithm + * * \f{algorithm}{ * \caption{Filtration value computation algorithm}\label{alpha} * \begin{algorithmic} - * \For{i : dimension $\rightarrow$ 1} + * \For{i : dimension $\rightarrow$ 0} * \ForAll{$\sigma$ of dimension i} * \If {filtration($\sigma$) is NaN} * \State filtration($\sigma$) = $\alpha^2(\sigma)$ @@ -93,25 +103,58 @@ namespace alphacomplex { * \EndFor * \EndFor * \EndFor + * \State make\_filtration\_non\_decreasing() + * \State prune\_above\_filtration() * \end{algorithmic} * \f} * - * From the example above, it means the algorithm will look into each triangle ([1,2,3], [2,3,4], [1,3,5], ...), - * will compute the filtration value of the triangle, and then will propagate the filtration value as described + * \subsubsection dimension2 Dimension 2 + * + * From the example above, it means the algorithm looks into each triangle ([1,2,3], [2,3,4], [1,3,5], ...), + * computes the filtration value of the triangle, and then propagates the filtration value as described * here : * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" - * Then, the algorithm will look into each edge ([1,2], [2,3], [1,3], ...), - * will compute the filtration value of the edge (in this case, propagation will have no effect). * - * Finally, the algorithm will look into each vertex ([1], [2], [3], [4], [5], [6] and [7]), - * will set the filtration value (0 in case of a vertex - propagation will have no effect). + * \subsubsection dimension1 Dimension 1 + * + * Then, the algorithm looks into each edge ([1,2], [2,3], [1,3], ...), + * computes the filtration value of the edge (in this case, propagation will have no effect). + * + * \subsubsection dimension0 Dimension 0 + * + * Finally, the algorithm looks into each vertex ([1], [2], [3], [4], [5], [6] and [7]) and + * sets the filtration value (0 in case of a vertex - propagation will have no effect). + * + * \subsubsection nondecreasing Non decreasing filtration values + * + * As Alpha square value computed from CGAL is an approximation, we have to make filtration non decreasing while + * increasing the dimension for our simplicial complex to be valid (cf. + * `Simplex_tree::make_filtration_non_decreasing()`). + * + * \subsubsection pruneabove Prune above given filtration value + * + * The simplex tree is pruned from the given maximum alpha square value (cf. `Simplex_tree::prune_above_filtration()`). + * In this example, the value is given by the user as argument of the program. * - * \section alpha-shape Alpha shape * - * In the example above, the alpha shape of \f$\alpha^2_{63} < \alpha^2 < \alpha^2_{62}\f$ is the alpha complex where the - * \f$\alpha^2_{63} <\f$ filtration value \f$< \alpha^2_{62}\f$ as described in \cite AlphaShapesIntroduction + * \section offexample Example from OFF file + * + * This example builds the Delaunay triangulation in a dynamic kernel, and initializes the alpha complex with it. + * + * + * Then, it is asked to display information about the alpha complex. + * + * \include Alpha_complex_from_off.cpp + * + * When launching: + * + * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off 32.0 + * \endcode + * + * the program output is: + * + * \include alphaoffreader_for_doc_32.txt * - * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" * \copyright GNU General Public License v3. * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim */ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe deleted file mode 100644 index 7563cf3d..00000000 --- a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe +++ /dev/null @@ -1,482 +0,0 @@ - - - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - -0.6 0 0 0.6 0 0 e - - - - - -0.5 0 0 0.5 0 0 e - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h - - - - - --0.5 -0.5 m -0.5 -0.5 l -0.5 0.5 l --0.5 0.5 l -h - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - - - --0.43 -0.57 m -0.57 0.43 l -0.43 0.57 l --0.57 -0.43 l -h - - --0.43 0.57 m -0.57 -0.43 l -0.43 -0.57 l --0.57 0.43 l -h - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - --1 0.333 m -0 0 l --1 -0.333 l - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Alpha shape -0 -1 -2 -3 -4 -5 -6 -0 -1 -2 -2 -1 -2 -2 -3 -3 -3 -3 -4 -4 -4 -4 -6 -6 -6 -6 -6 -6 -5 -6 -5 - -4 0 0 4 320 704 e - - -322.919 706.788 m -317.189 701.058 l -317.189 701.203 l - - -317.551 706.934 m -322.629 701.058 l - - -230 680 m -240 670 l - - -230 680 m -240 670 l - - -230 680 m -240 670 l - - -230 680 m -240 670 l - - -230 680 m -220 670 l - - -230 680 m -230 670 l - - -220 660 m -220 650 l - - -230 660 m -230 650 l - - -260 680 m -260 670 l - - -260 660 m -260 650 l - - -300 680 m -300 670 l - - -300 680 m -290 670 l - - -290 660 m -290 650 l - - -300 660 m -300 650 l - - -330 680 m -330 670 l - - -350 680 m -350 670 l - - -350 660 m -350 650 l - - -320 700 m -240 690 l - - -320 700 m -270 690 l - - -320 700 m -310 690 l - - -320 700 m -330 690 l - - -320 700 m -350 690 l - - -320 700 m -380 690 l - - -320 700 m -400 690 l - -Alpha complex structure - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -60 710 m -40 660 l - - -40 660 m -130 690 l - - -130 690 m -60 710 l - - -40 660 m -80 580 l - - -80 580 m -130 580 l -130 580 l - - -130 580 m -110 520 l - - -110 520 m -50 530 l -50 530 l -50 530 l - - -50 530 m -80 580 l - - -130 580 m -130 690 l - - - -108.275 743.531 m -166.45 743.531 l - -$\alpha$ -filtration value $> \alpha$ are greyed - -280 660 m -300 680 l - - -280 660 m -300 640 l - - -370 660 m -350 680 l - - -370 660 m -350 640 l - - -290 670 m -360 670 l - - -290 650 m -360 650 l - -equivalent - - diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png deleted file mode 100644 index 2d5f59a3..00000000 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png and /dev/null differ diff --git a/src/Alpha_complex/doc/alpha_complex_representation.ipe b/src/Alpha_complex/doc/alpha_complex_representation.ipe new file mode 100644 index 00000000..8687d694 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_representation.ipe @@ -0,0 +1,321 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +109.771 601.912 m +159.595 601.797 l +140.058 541.915 l +h + + +79.8776 552.169 m +109.756 601.699 l +139.812 542.209 l +h + + +69.8453 682.419 m +159.925 712.208 l +90.12 732.039 l +h + +Alpha complex +0 +1 +2 +3 +4 +5 +6 + +58.1341 0 0 58.1341 218.925 692.601 e + + +60 710 m +40 660 l + + +40 660 m +130 690 l + + +130 690 m +60 710 l + + +40 660 m +80 580 l + + +80 580 m +130 580 l +130 580 l + + +130 580 m +110 520 l + + +110 520 m +50 530 l +50 530 l +50 530 l + + +50 530 m +80 580 l + + +130 580 m +130 690 l + + + +108.275 743.531 m +166.45 743.531 l + +$\alpha$ + + + + + + +150.038 609.9 m +179.929 549.727 l + + + + + diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index cd6f5a4b..4f381892 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,8 +1,6 @@ #include #include -// to construct a Delaunay_triangulation from a OFF file -#include #include void usage(char * const progName) { @@ -35,14 +33,12 @@ int main(int argc, char **argv) { std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - //if (alpha_complex_from_file.filtration(f_simplex) <= alpha_complex_from_file.filtration()) { - std::cout << " ( "; - for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { - std::cout << vertex << " "; - } - std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; - std::cout << std::endl; - //} + std::cout << " ( "; + for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; + std::cout << std::endl; } return 0; } diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index e460f177..62f594d1 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -6,34 +6,50 @@ #include #include -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" +#include -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel; typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " alpha_square_max_value" << std::endl; + std::cerr << " i.e.: " << progName << " 32.0" << std::endl; + exit(-1); // ----- >> +} + int main(int argc, char **argv) { + if (argc != 2) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + double alpha_square_max_value = atof(argv[1]); + // ---------------------------------------------------------------------------- // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - std::vector coords = { 0.0, 0.0, 0.0, 1.0 }; + std::vector coords = { 1.0, 1.0 }; + points.push_back(Point(coords.begin(), coords.end())); + coords = { 7.0, 0.0 }; + points.push_back(Point(coords.begin(), coords.end())); + coords = { 4.0, 6.0 }; + points.push_back(Point(coords.begin(), coords.end())); + coords = { 9.0, 6.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords = { 0.0, 0.0, 1.0, 0.0 }; + coords = { 0.0, 14.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords = { 0.0, 1.0, 0.0, 0.0 }; + coords = { 2.0, 19.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords = { 1.0, 0.0, 0.0, 0.0 }; + coords = { 9.0, 17.0 }; points.push_back(Point(coords.begin(), coords.end())); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - double max_alpha_square_value = 1e10; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, max_alpha_square_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, alpha_square_max_value); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 10b87f04..33ff6805 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -27,10 +27,6 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc.txt b/src/Alpha_complex/example/alphaoffreader_for_doc.txt deleted file mode 100644 index 71f29a00..00000000 --- a/src/Alpha_complex/example/alphaoffreader_for_doc.txt +++ /dev/null @@ -1,27 +0,0 @@ -Alpha complex is of dimension 2 - 25 simplices - 7 vertices. -Iterator on alpha complex simplices in the filtration order, with [filtration value]: - ( 0 ) -> [0] - ( 1 ) -> [0] - ( 2 ) -> [0] - ( 3 ) -> [0] - ( 4 ) -> [0] - ( 5 ) -> [0] - ( 6 ) -> [0] - ( 3 2 ) -> [6.25] - ( 5 4 ) -> [7.25] - ( 2 0 ) -> [8.5] - ( 1 0 ) -> [9.25] - ( 3 1 ) -> [10] - ( 2 1 ) -> [11.25] - ( 3 2 1 ) -> [12.5] - ( 2 1 0 ) -> [12.9959] - ( 6 5 ) -> [13.25] - ( 4 2 ) -> [20] - ( 6 4 ) -> [22.7367] - ( 6 5 4 ) -> [22.7367] - ( 6 3 ) -> [30.25] - ( 6 2 ) -> [36.5] - ( 6 3 2 ) -> [36.5] - ( 6 4 2 ) -> [37.2449] - ( 4 0 ) -> [59.7107] - ( 4 2 0 ) -> [59.7107] diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt new file mode 100644 index 00000000..553431a9 --- /dev/null +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt @@ -0,0 +1,22 @@ +Alpha complex is of dimension 2 - 20 simplices - 7 vertices. +Iterator on alpha complex simplices in the filtration order, with [filtration value]: + ( 0 ) -> [0] + ( 1 ) -> [0] + ( 2 ) -> [0] + ( 3 ) -> [0] + ( 4 ) -> [0] + ( 5 ) -> [0] + ( 6 ) -> [0] + ( 5 4 ) -> [6.25] + ( 4 1 ) -> [20] + ( 4 2 ) -> [8.5] + ( 6 2 ) -> [9.25] + ( 6 5 ) -> [10] + ( 6 4 ) -> [11.25] + ( 6 5 4 ) -> [12.5] + ( 6 4 2 ) -> [12.9959] + ( 3 0 ) -> [13.25] + ( 4 1 ) -> [20] + ( 1 0 ) -> [22.7367] + ( 3 1 0 ) -> [22.7367] + ( 5 0 ) -> [30.25] diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt new file mode 100644 index 00000000..71f29a00 --- /dev/null +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt @@ -0,0 +1,27 @@ +Alpha complex is of dimension 2 - 25 simplices - 7 vertices. +Iterator on alpha complex simplices in the filtration order, with [filtration value]: + ( 0 ) -> [0] + ( 1 ) -> [0] + ( 2 ) -> [0] + ( 3 ) -> [0] + ( 4 ) -> [0] + ( 5 ) -> [0] + ( 6 ) -> [0] + ( 3 2 ) -> [6.25] + ( 5 4 ) -> [7.25] + ( 2 0 ) -> [8.5] + ( 1 0 ) -> [9.25] + ( 3 1 ) -> [10] + ( 2 1 ) -> [11.25] + ( 3 2 1 ) -> [12.5] + ( 2 1 0 ) -> [12.9959] + ( 6 5 ) -> [13.25] + ( 4 2 ) -> [20] + ( 6 4 ) -> [22.7367] + ( 6 5 4 ) -> [22.7367] + ( 6 3 ) -> [30.25] + ( 6 2 ) -> [36.5] + ( 6 3 2 ) -> [36.5] + ( 6 4 2 ) -> [37.2449] + ( 4 0 ) -> [59.7107] + ( 4 2 0 ) -> [59.7107] diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 6adfa2e6..2dae4028 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -27,6 +27,8 @@ #include #include #include +// to construct a Delaunay_triangulation from a OFF file +#include #include #include // isnan, fmax diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d1eac80..3a75527e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,6 +42,12 @@ else() INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) + if (DEBUG_TRACES) + message(STATUS "DEBUG_TRACES are activated") + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() + #--------------------------------------------------------------------------------------- # Gudhi compilation part include_directories(include) diff --git a/src/Doxyfile b/src/Doxyfile index 81f55e29..9cd73444 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -673,6 +673,7 @@ LAYOUT_FILE = # also \cite for info how to create references. CITE_BIB_FILES = biblio/bibliography.bib \ + biblio/how_to_cite_cgal.bib \ biblio/how_to_cite_gudhi.bib #--------------------------------------------------------------------------- @@ -812,7 +813,7 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = biblio/ +EXAMPLE_PATH = biblio/ \ example/common/ \ example/Alpha_complex/ diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index 5c2afdd0..75adba08 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -102,10 +102,6 @@ if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND ) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable (acp alpha_complex_persistence.cpp) target_link_libraries(acp ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${QT_LIBRARIES}) diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index 8caf7d8b..eb4ee3e3 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -35,10 +35,6 @@ if(GMPXX_FOUND AND GMP_FOUND) target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) if(CGAL_FOUND) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable(alpha_shapes_persistence alpha_shapes_persistence.cpp) target_link_libraries(alpha_shapes_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) add_test(alpha_shapes_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) @@ -70,10 +66,6 @@ if(GMPXX_FOUND AND GMP_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable (alphacomplexpersistence alpha_complex_persistence.cpp) target_link_libraries(alphacomplexpersistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 3edcbd0b..3c42f72d 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -63,7 +63,7 @@ * CGAL is a C++ library which provides easy access to efficient and reliable geometric algorithms. * * The following examples require the Computational Geometry Algorithms - * Library (CGAL) and will not be built if CGAL is not installed: + * Library (CGAL \cite cgal:eb-15b) and will not be built if CGAL is not installed: * \li GudhUI * \li Persistent_cohomology/alpha_shapes_persistence * \li Simplex_tree/simplex_tree_from_alpha_shapes_3 diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index 089f0c04..d29e31e7 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -26,10 +26,6 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) -- cgit v1.2.3 From f9b5b9b3306f3f00f5bfa2724cbfa087d5161fcb Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 11 Dec 2015 15:41:39 +0000 Subject: Commit code and doc review Still issue and lot of logs in simplex_tree::prune_above_filtration git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@945 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: cd4f60ddcacb0444e0eb3b9323d8042eb49b132e --- CMakeLists.txt | 4 +- biblio/bibliography.bib | 16 -- src/Alpha_complex/doc/Intro_alpha_complex.h | 8 +- src/Alpha_complex/doc/alpha_complex_doc.ipe | 24 +- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 46746 -> 49973 bytes src/Alpha_complex/doc/alpha_complex_doc_135.ipe | 88 +++---- src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 127130 -> 80794 bytes .../doc/alpha_complex_representation.png | Bin 0 -> 16737 bytes .../example/Alpha_complex_from_points.cpp | 22 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +- src/Alpha_complex/test/CMakeLists.txt | 2 + src/Simplex_tree/include/gudhi/Simplex_tree.h | 95 ++++++-- .../gudhi/Simplex_tree/Simplex_tree_siblings.h | 4 + src/Simplex_tree/test/simplex_tree_unit_test.cpp | 266 ++++++++++++++++++++- .../example/dtoffrw_alphashapedoc_result.off | 15 ++ .../example/dtoffrw_alphashapedoc_result.txt | 1 - .../include/gudhi/Delaunay_triangulation_off_io.h | 2 +- src/common/test/dtoffrw_unit_test.cpp | 4 +- 18 files changed, 436 insertions(+), 121 deletions(-) create mode 100644 src/Alpha_complex/doc/alpha_complex_representation.png create mode 100644 src/common/example/dtoffrw_alphashapedoc_result.off (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index d42f7af7..d0770dd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,8 @@ if(MSVC) # Turn off some VC++ warnings SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4668 /wd4311 /wd4800 /wd4820 /wd4503 /wd4244 /wd4345 /wd4996 /wd4396 /wd4018") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -std=c++11 -Wall -Wpedantic -Wsign-compare") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -std=c++11 -fsanitize=memory -fno-omit-frame-pointer -Wall -Wpedantic -Wsign-compare") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O1") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") endif() diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index 859696b4..3fd1c10a 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -897,22 +897,6 @@ language={English} bibsource = {DBLP, http://dblp.uni-trier.de} } -@ARTICLE{AlphaShapesDefinition, - author = {N. Akkiraju, H. Edelsbrunner, M. Facello, P. Fu, E. P. Mucke, and C. Varela}, - title = {\href{http://pub.ist.ac.at/~edels/Papers/1995-P-06-AlphaShapesSoftware.pdf}{Alpha shapes: definition and software}}, - journal = {Proc. Internat. Comput. Geom. Software Workshop 1995}, - year = {1995}, - bibsource = {http://pub.ist.ac.at} -} - -@ARTICLE{AlphaShapesIntroduction, - author = {Kaspar Fischer}, - title = {\href{http://www.cs.uu.nl/docs/vakken/ddm/texts/Delaunay/alphashapes.pdf}{Introduction to Alpha Shapes}}, - journal = {Unknown}, - year = {Unknown}, - bibsource = {http://www.cs.uu.nl} -} - misc{buddha_stanford_scan, author = "", title = "The Stanford 3D Scanning Repository", diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 685a4c2f..12d62ac0 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -37,10 +37,10 @@ namespace alphacomplex { * \section definition Definition * * Alpha_complex is a simplicial complex - * constructed from each finite cell of a Delaunay Triangulation. + * constructed from the finite cells of a Delaunay Triangulation. * - * The filtration value of each simplex is computed from the alpha square value of the simplex if it is Gabriel or - * from the alpha value of the simplex coface that makes the simplex not Gabriel. + * The filtration value of each simplex is computed from the circumradius of the simplex if it is Gabriel or + * from the alpha value of the simplex cofaces that make it not Gabriel. * * All simplices that have a filtration value strictly greater than a given alpha square value are not inserted into * the simplex. @@ -78,7 +78,7 @@ namespace alphacomplex { * * \subsection datastructure Data structure * - * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. + * In order to build the alpha complex, first, a Simplex tree is built from the cells of a Delaunay Triangulation. * (The filtration value is set to NaN, which stands for unknown value): * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" * diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe index b5601143..e74f9bc4 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -1,7 +1,7 @@ - - + + @@ -202,13 +202,13 @@ h + + - - @@ -232,14 +232,7 @@ h - - - - - - - - + 320 580 m 350 520 l 290 530 l @@ -434,5 +427,12 @@ h 280 610 m 170 610 l + + + + + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index 601ac051..c9eab275 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc.png and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe index 28b893b8..5d1d29d4 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe @@ -1,7 +1,7 @@ - - + + @@ -202,13 +202,13 @@ h + + - - @@ -232,14 +232,7 @@ h - - - - - - - - + 320 580 m 350 520 l 290 530 l @@ -288,19 +281,11 @@ h 77.2727 0 0 77.2727 243.636 591.818 e - 243.428 591.569 m 186.061 643.28 l $\alpha_{420}$ - - - - - - - 320 580 m 350 520 l @@ -325,7 +310,6 @@ h modified (NaN) 0 -1 2 3 4 @@ -357,18 +341,10 @@ modified (NaN) 29.1548 0 0 29.1548 305 555 e - 304.883 555.015 m 334.509 555.015 l - - - - - - - 320 580 m 350 520 l @@ -391,10 +367,7 @@ modified (NaN) [0,4] is not Gabriel $\rightarrow$ $\alpha_{40} = \alpha_{420}$ 0 -1 -2 3 -4 5 6 @@ -420,16 +393,6 @@ modified (NaN) 290 530 m 280 660 l - -65.192 0 0 65.192 285 595 e - - - - - - - - 320 580 m 350 520 l @@ -483,7 +446,6 @@ modified (NaN) 44.5799 0 0 44.5799 425.934 457.774 e - 425.854 457.774 m 470.795 457.774 l @@ -505,10 +467,48 @@ modified (NaN) For all faces of [4,2,0] N.B. : is Gabriel on a single point has no sense. Dimension =2 - $\sigma$ = [4,2,0] - 247.333 430.892 m 311.764 430.892 l + + + + + + + + + + + + + +1 + + + + + +4 + + +1 + + +2 + +65.192 0 0 65.192 285 595 e + + + + + + + + + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png index 5dce5edd..ef7187f7 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_135.png and b/src/Alpha_complex/doc/alpha_complex_doc_135.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_representation.png b/src/Alpha_complex/doc/alpha_complex_representation.png new file mode 100644 index 00000000..06e54c06 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_representation.png differ diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 62f594d1..00e988a6 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -30,21 +30,13 @@ int main(int argc, char **argv) { // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - - std::vector coords = { 1.0, 1.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 7.0, 0.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 4.0, 6.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 9.0, 6.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 0.0, 14.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 2.0, 19.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 9.0, 17.0 }; - points.push_back(Point(coords.begin(), coords.end())); + points.push_back(Point(1.0, 1.0)); + points.push_back(Point(7.0, 0.0)); + points.push_back(Point(4.0, 6.0)); + points.push_back(Point(9.0, 6.0)); + points.push_back(Point(0.0, 14.0)); + points.push_back(Point(2.0, 19.0)); + points.push_back(Point(9.0, 17.0)); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 2dae4028..9f931066 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -125,7 +125,9 @@ class Alpha_complex : public Simplex_tree<> { /** \brief Alpha_complex constructor from a Delaunay triangulation. * - * @param[in] triangulation_ptr Pointer on a Delaunay triangulation. + * @param[in] triangulation_ptr Pointer on a + * CGAL::Delaunay_triangulation \cite cgal:hdj-t-15b. * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. */ Alpha_complex(Delaunay_triangulation* triangulation_ptr, @@ -170,7 +172,7 @@ class Alpha_complex : public Simplex_tree<> { } } - /** \brief Alpha_complex destructor from a Delaunay triangulation. + /** \brief Alpha_complex destructor. * * @warning Deletes the Delaunay triangulation. */ diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index fa24e1b1..d7c13da0 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -18,6 +18,8 @@ if(CGAL_FOUND) add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp ) target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_executable ( cerr cerr.cpp ) + # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 3adf06d3..4b04e75a 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -530,7 +530,7 @@ class Simplex_tree { return dimension_; } - /** \brief Returns true iff the node in the simplex tree pointed by + /** \brief Returns true if the node in the simplex tree pointed by * sh has children.*/ bool has_children(Simplex_handle sh) const { return (sh->second.children()->parent() == sh->first); @@ -1134,7 +1134,6 @@ class Simplex_tree { if (sh->second.filtration() < upper_filtration) { // Store the filtration modification information modified = true; - std::cout << "modified" << std::endl; sh->second.assign_filtration(upper_filtration); } if (has_children(sh)) { @@ -1154,21 +1153,51 @@ class Simplex_tree { * call `initialize_filtration()` to recompute it. */ void prune_above_filtration(Filtration_value filtration) { - if (filtration < threshold_) { - threshold_ = filtration; - // Initialize filtration_vect_ if required - if (filtration_vect_.empty()) { - initialize_filtration(); - } +std::cout << "prune_above_filtration - filtration=" << filtration << std::endl; + // No action if filtration is not stored + if (Options::store_filtration) { + if (filtration < threshold_) { + threshold_ = filtration; + // Initialize filtration_vect_ if required + if (filtration_vect_.empty()) { +std::cout << "prune_above_filtration - initialize_filtration" << std::endl; + initialize_filtration(); + } + +std::cout << "prune_above_filtration - after initialize_filtration "; +for(auto sh : filtration_vect_) { +for (auto vertex : simplex_vertex_range(sh)) { +std::cout << (int) vertex << ", "; +} +std::cout << " - filtration=" << sh->second.filtration() << " - " << &(sh->second) << std::endl; +} - // Loop in reverse mode until threshold is reached - auto f_simplex = filtration_vect_.rbegin(); - for (; f_simplex != filtration_vect_.rend() && ((*f_simplex)->second.filtration() > threshold_); f_simplex++) { - remove_maximal_simplex(*f_simplex); + + // Loop in reverse mode until threshold is reached + auto f_simplex = filtration_vect_.rbegin(); + for (; (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > threshold_); f_simplex++) { + +std::cout << "prune_above_filtration - remove "; +for (auto vertex : simplex_vertex_range(*f_simplex)) { +std::cout << (int) vertex << ", "; +} +std::cout << " - " << &((*f_simplex)->second) << std::endl; + + remove_maximal_simplex(*f_simplex); + } +std::cout << "prune_above_filtration - remove STOPPED ON "; +for (auto vertex : simplex_vertex_range(*f_simplex)) { +std::cout << (int) vertex << ", "; +} +std::cout << " - filtration=" << (*f_simplex)->second.filtration() << " - " << &(*f_simplex->second) << std::endl; + if (f_simplex != filtration_vect_.rbegin()) { + // Do not forget to update filtration_vect_ - resize is enough + std::size_t new_size = filtration_vect_.size() - (f_simplex - filtration_vect_.rbegin()); +std::cout << "prune_above_filtration - resize" << new_size << std::endl; + filtration_vect_.resize(new_size); + } + } - // Do not forget to update filtration_vect_ - resize is enough - std::size_t new_size = filtration_vect_.size() - (f_simplex - filtration_vect_.rbegin()); - filtration_vect_.resize(new_size); } } @@ -1187,14 +1216,46 @@ class Simplex_tree { if ((child->size() > 1) || (child == root())) { // Not alone, just remove it from members // Special case when child is the root of the simplex tree, just remove it from members - child->members().erase(sh->first); +std::cout << "remove_maximal_simplex - members removal" << std::endl; + child->erase(sh->first); } else { // Sibling is emptied : must be deleted, and its parent must point on his own Sibling +std::cout << "remove_maximal_simplex - members is empty" << std::endl; child->oncles()->members().at(child->parent()).assign_children(child->oncles()); delete child; } } - +/***************************************************************************************************************/ + public: + /** \brief Prints the simplex_tree hierarchically. + * Since it prints the vertices recursively, one can watch its tree shape. + */ + void print_tree() { + for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { + std::cout << sh->first << " "; + if (has_children(sh)) { + std::cout << "("; + rec_print(sh->second.children()); + std::cout << ")"; + } + std::cout << std::endl; + } + } + + + /** \brief Recursively prints the simplex_tree, using depth first search. */ + private: + void rec_print(Siblings * sib) { + for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { + std::cout << " " << sh->first << " "; + if (has_children(sh)) { + std::cout << "("; + rec_print(sh->second.children()); + std::cout << ")"; + } + } + } +/*****************************************************************************************************************/ private: Vertex_handle null_vertex_; /** \brief Upper bound on the filtration values of the simplices.*/ diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h index 158ee1f7..c1ff8bf2 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h @@ -116,6 +116,10 @@ class Simplex_tree_siblings { return members_.size(); } + void erase(const Vertex_handle vh) { + members_.erase(vh); + } + Simplex_tree_siblings * oncles_; Vertex_handle parent_; Dictionary members_; diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 00cf69bc..f6bd5411 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -362,7 +362,9 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { } -bool sort_in_decr_order (Vertex_handle i,Vertex_handle j) { return (i>j); } +bool sort_in_decr_order(Vertex_handle i, Vertex_handle j) { + return (i > j); +} BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { std::cout << "********************************************************************" << std::endl; @@ -476,7 +478,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { BOOST_CHECK(vertex == SimplexVector6[position]); position++; } - + /* Inserted simplex: */ /* 1 6 */ /* o---o */ @@ -720,14 +722,268 @@ BOOST_AUTO_TEST_CASE(copy_move_on_simplex_tree) { // Check there is a new simplex tree reference BOOST_CHECK(&st_move != &st_copy); BOOST_CHECK(&st_move != &st); - + typeST st_empty; // Check st has been emptied by the move BOOST_CHECK(st == st_empty); BOOST_CHECK(st.filtration() == 0); BOOST_CHECK(st.dimension() == -1); BOOST_CHECK(st.num_simplices() == 0); - BOOST_CHECK(st.num_vertices() == (size_t)0); - + BOOST_CHECK(st.num_vertices() == (size_t) 0); + std::cout << "Printing st once again- address = " << &st << std::endl; } + +BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) { + std::cout << "********************************************************************" << std::endl; + std::cout << "MAKE FILTRATION NON DECREASING" << std::endl; + typeST st; + + st.insert_simplex_and_subfaces({2, 1, 0}, 4.0); + st.insert_simplex_and_subfaces({3, 0}, 3.0); + st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); + // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 4.0 + // to 1.0 + st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + // FIXME + st.set_dimension(3); + + // Copy constructor + typeST st_copy = st; + + // Check default insertion ensures the filtration values are non decreasing + BOOST_CHECK(!st.make_filtration_non_decreasing()); + // Check the simplex tree is not modified by the function + BOOST_CHECK(st == st_copy); + + // Make { 0, 1 } decreasing + st.assign_filtration(st.find({0, 1}), 0.5); + // Make { 1, 6, 7 } decreasing + st.assign_filtration(st.find({1, 6, 7}), 0.4); + // Make { 3, 4 } decreasing + st.assign_filtration(st.find({3, 4}), 0.3); + // Make { 4, 5 } decreasing + st.assign_filtration(st.find({4, 5}), 0.1); + + // Check the filtration values were decreasing + BOOST_CHECK(st.make_filtration_non_decreasing()); + // Check the simplex tree has been modified by the function to retrieve the initial simplex tree + BOOST_CHECK(st == st_copy); + + // Change { 0, 3 }, but still non decreasing + st.assign_filtration(st.find({0, 3}), 1.01); + // Change { 0, 1, 6, 7 }, but still non decreasing + st.assign_filtration(st.find({0, 1, 6, 7}), 1.201); + // Change { 1, 2 }, but still non decreasing + st.assign_filtration(st.find({1, 2}), 1.05); + // Change { 4 }, but still non decreasing + st.assign_filtration(st.find({4}), 1.123); + + // Check the filtration values are non decreasing + BOOST_CHECK(!st.make_filtration_non_decreasing()); + // Check the simplex tree has been modified from the original + BOOST_CHECK(st != st_copy); + +} + +struct MyOptions : Simplex_tree_options_full_featured { + // Not doing persistence, so we don't need those + static const bool store_key = false; + static const bool store_filtration = false; + // I have few vertices + typedef short Vertex_handle; +}; +typedef Simplex_tree miniST; + +/*BOOST_AUTO_TEST_CASE(remove_maximal_simplex) { + std::cout << "********************************************************************" << std::endl; + std::cout << "REMOVE MAXIMAL SIMPLEX" << std::endl; + + miniST st; + + // FIXME + st.set_dimension(3); + + st.insert_simplex_and_subfaces({0, 1, 6, 7}); + st.insert_simplex_and_subfaces({3, 4, 5}); + + // Constructs a copy at this state for further test purpose + miniST st_pruned = st; + + st.insert_simplex_and_subfaces({3, 0}); + st.insert_simplex_and_subfaces({2, 1, 0}); + + // Constructs a copy at this state for further test purpose + miniST st_complete = st; + // st_complete and st: + // 1 6 + // o---o + // /X\7/ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 + // st_pruned: + // 1 6 + // o---o + // \7/ + // o o---o + // 0 3\X/4 + // o + // 5 + +#ifdef GUDHI_DEBUG + std::cout << "Check exception throw in debug mode" << std::endl; + // throw excpt because sh has children + BOOST_CHECK_THROW (st.remove_maximal_simplex(st.find({0, 1, 6})), std::invalid_argument); + BOOST_CHECK_THROW (st.remove_maximal_simplex(st.find({3})), std::invalid_argument); + BOOST_CHECK(st == st_complete); +#endif + + st.remove_maximal_simplex(st.find({0, 2})); + st.remove_maximal_simplex(st.find({0, 1, 2})); + st.remove_maximal_simplex(st.find({1, 2})); + st.remove_maximal_simplex(st.find({2})); + st.remove_maximal_simplex(st.find({0, 3})); + + BOOST_CHECK(st == st_pruned); + // Remove all, but as the simplex tree is not storing filtration, there is no modification + st.prune_above_filtration(0.0); + BOOST_CHECK(st == st_pruned); + + miniST st_wo_seven; + // FIXME + st_wo_seven.set_dimension(3); + + st_wo_seven.insert_simplex_and_subfaces({0, 1, 6}); + st_wo_seven.insert_simplex_and_subfaces({3, 4, 5}); + // st_wo_seven: + // 1 6 + // o---o + // \X/ + // o o---o + // 0 3\X/4 + // o + // 5 + + // Remove all 7 to test the both remove_maximal_simplex cases (when _members is empty or not) + st.remove_maximal_simplex(st.find({0, 1, 6, 7})); + st.remove_maximal_simplex(st.find({0, 1, 7})); + st.remove_maximal_simplex(st.find({0, 6, 7})); + st.remove_maximal_simplex(st.find({0, 7})); + st.remove_maximal_simplex(st.find({1, 6, 7})); + st.remove_maximal_simplex(st.find({1, 7})); + st.remove_maximal_simplex(st.find({6, 7})); + st.remove_maximal_simplex(st.find({7})); + + BOOST_CHECK(st == st_wo_seven); +}*/ + +BOOST_AUTO_TEST_CASE(prune_above_filtration) { + std::cout << "********************************************************************" << std::endl; + std::cout << "PRUNE ABOVE FILTRATION" << std::endl; + typeST st; + + // FIXME + st.set_dimension(3); + + st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); + st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); + st.set_filtration(6.0); + + // Constructs a copy at this state for further test purpose + typeST st_pruned = st; + st_pruned.initialize_filtration(); // reset + + st.insert_simplex_and_subfaces({3, 0}, 3.0); + st.insert_simplex_and_subfaces({2, 1, 0}, 4.0); + + // Constructs a copy at this state for further test purpose + typeST st_complete = st; + // st_complete and st: + // 1 6 + // o---o + // /X\7/ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 + // st_pruned: + // 1 6 + // o---o + // \7/ + // o o---o + // 0 3\X/4 + // o + // 5 + + // Check the no action cases + // greater than initial filtration value + st.prune_above_filtration(10.0); + BOOST_CHECK(st == st_complete); + // equal to initial filtration value + st.prune_above_filtration(6.0); + BOOST_CHECK(st == st_complete); + // lower than initial filtration value, but still greater than the maximum filtration value + st_complete.set_filtration(5.0); + st.prune_above_filtration(5.0); + BOOST_CHECK(st == st_complete); + + // Display the Simplex_tree - Can not be done in the middle of 2 inserts + std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + std::cout << " " << "[" << st.filtration(f_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; + } + + // Check the pruned cases + // Set the st_pruned filtration for operator== + st_pruned.set_filtration(2.5); + st.prune_above_filtration(2.5); + /*BOOST_CHECK(st == st_pruned); + + st_pruned.set_filtration(2.0); + st.prune_above_filtration(2.0); + BOOST_CHECK(st == st_pruned); +*/ +/* std::cout << "The complex contains " << st.num_simplices() << " simplices --------------------------" << std::endl; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + st.print_tree(); + + std::cout << "The pruned complex contains " << st_pruned.num_simplices() << " simplices --------------------------" << std::endl; + std::cout << " - dimension " << st_pruned.dimension() << " - filtration " << st_pruned.filtration() << std::endl; + st_pruned.print_tree(); + + typeST st_empty; + // FIXME + st_empty.set_dimension(3); + st.prune_above_filtration(0.0); + */ + /*BOOST_CHECK(st == st_empty); + + // Test case to the limit + st.prune_above_filtration(-1.0); + st_empty.set_filtration(-1.0); + BOOST_CHECK(st == st_empty); +*/ +} + +/*BOOST_AUTO_TEST_CASE(sanitizer) { + int a[2] = {1, 0}; + int b=a[2]; +}*/ diff --git a/src/common/example/dtoffrw_alphashapedoc_result.off b/src/common/example/dtoffrw_alphashapedoc_result.off new file mode 100644 index 00000000..03b7ca75 --- /dev/null +++ b/src/common/example/dtoffrw_alphashapedoc_result.off @@ -0,0 +1,15 @@ +nOFF +2 7 6 0 +1 1 +7 0 +4 6 +9 6 +0 14 +2 19 +9 17 +3 0 1 2 +3 3 2 1 +3 4 0 2 +3 4 2 6 +3 6 2 3 +3 5 4 6 diff --git a/src/common/example/dtoffrw_alphashapedoc_result.txt b/src/common/example/dtoffrw_alphashapedoc_result.txt index 57761d14..8e659740 100644 --- a/src/common/example/dtoffrw_alphashapedoc_result.txt +++ b/src/common/example/dtoffrw_alphashapedoc_result.txt @@ -1,3 +1,2 @@ Number of vertices= 7 Number of finite full cells= 6 - diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 6335d243..b3f4a299 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -135,7 +135,7 @@ class Delaunay_triangulation_off_visitor_reader { * * When launching: * - * \code $> ./dtoffrw ../../data/points/alphashapedoc.off triangulated.off + * \code $> ./dtoffrw ../../data/points/alphacomplexdoc triangulated.off * \endcode * * the program output is: diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp index 20094229..f682df1a 100644 --- a/src/common/test/dtoffrw_unit_test.cpp +++ b/src/common/test/dtoffrw_unit_test.cpp @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE( Delaunay_triangulation_doc_test ) BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) { - Gudhi::Delaunay_triangulation_off_reader off_reader("pouetpouet_tralala.off"); + Gudhi::Delaunay_triangulation_off_reader off_reader("some_impossible_weird_file_name.off"); // Check the read operation was correct BOOST_CHECK(!off_reader.is_valid()); T* triangulation = off_reader.get_complex(); @@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_write_test ) T* triangulation = off_reader.get_complex(); // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces - Gudhi::Delaunay_triangulation_off_writer off_writer("/pouetpouet_tralala/pouetpouet_tralala/pouetpouet_tralala.off", triangulation); + Gudhi::Delaunay_triangulation_off_writer off_writer("/some_impossible_weird_directory_name/another_weird_directory_name/some_impossible_weird_file_name.off", triangulation); // Check the write operation was correct BOOST_CHECK(!off_writer.is_valid()); -- cgit v1.2.3 From 73e025369bd50511b67b4f8e290a2c3a533ded88 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 19 Jan 2016 10:28:37 +0000 Subject: make_filtration_non_decreasing fix Ut rewrite git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@974 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3326338b9454923b59d3e42add0f3530c6dbe16f --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 4 +- src/Simplex_tree/include/gudhi/Simplex_tree.h | 37 ++++------ src/Simplex_tree/test/simplex_tree_unit_test.cpp | 88 ++++++++++++++++-------- 3 files changed, 78 insertions(+), 51 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 9f931066..1ab6766c 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -308,7 +308,9 @@ class Alpha_complex : public Simplex_tree<> { // -------------------------------------------------------------------------------------------- // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension - make_filtration_non_decreasing(); + if (make_filtration_non_decreasing()) { + initialize_filtration(); + } // Remove all simplices that have a filtration value greater than max_alpha_square prune_above_filtration(max_alpha_square); // -------------------------------------------------------------------------------------------- diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 16485c89..dbef8517 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -129,10 +129,6 @@ class Simplex_tree { /* \brief Set of nodes sharing a same parent in the simplex tree. */ typedef Simplex_tree_siblings Siblings; - /** \brief Element of a flat_map. - * 'value_type' is Map_element. */ - typedef typename std::pair Map_element; - struct Key_simplex_base_real { Key_simplex_base_real() : key_(-1) {} void assign_key(Simplex_key k) { key_ = k; } @@ -1131,15 +1127,10 @@ class Simplex_tree { */ bool make_filtration_non_decreasing() { bool modified = false; - - // Find the maximum filtration value in the border - Simplex_handle max_border_value = std::max_element( std::begin(root_.members()), std::end(root_.members()), - [](const Map_element& sh1, const Map_element& sh2) { - return sh1.second.filtration() < sh2.second.filtration(); - }); - for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { + // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree + for (auto sh = (root_.members().end() - 1); sh >= root_.members().begin(); --sh) { if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children(), max_border_value->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children()); } } return modified; @@ -1148,25 +1139,27 @@ class Simplex_tree { private: /** \brief Recursively Browse the simplex tree to ensure the filtration is not decreasing. * @param[in] sib Siblings to be parsed. - * @param[in] upper_filtration Upper level filtration value in the simplex tree. * @return The filtration modification information in order to trigger initialize_filtration. */ - bool rec_make_filtration_non_decreasing(Siblings * sib, Filtration_value upper_filtration) { + bool rec_make_filtration_non_decreasing(Siblings * sib) { bool modified = false; - // Find the maximum filtration value in the border - Simplex_handle max_border_value = std::max_element( std::begin(sib->members()), std::end(sib->members()), - [](const Map_element& sh1, const Map_element& sh2) { - return sh1.second.filtration() < sh2.second.filtration(); - }); for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { - if (sh->second.filtration() < upper_filtration) { + // Find the maximum filtration value in the border + Boundary_simplex_range boundary = boundary_simplex_range(sh); + Boundary_simplex_iterator max_border = std::max_element( std::begin(boundary), std::end(boundary), + [](Simplex_handle sh1, Simplex_handle sh2) { + return filtration(sh1) < filtration(sh2); + } ); + + Filtration_value max_filt_border_value = filtration(*max_border); + if (sh->second.filtration() < max_filt_border_value) { // Store the filtration modification information modified = true; - sh->second.assign_filtration(upper_filtration); + sh->second.assign_filtration(max_filt_border_value); } if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children(), max_border_value->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children()); } } // Make the modified information to be traced by upper call diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 25ae5ed3..cd6746a6 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -806,46 +806,78 @@ BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) { st.insert_simplex_and_subfaces({3, 0}, 2.0); st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); - typeST st_bis = st; - // Check default insertion ensures the filtration values are non decreasing + // Inserted simplex: + // 1 + // o + // /X\ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 + + std::cout << "Check default insertion ensures the filtration values are non decreasing" << std::endl; BOOST_CHECK(!st.make_filtration_non_decreasing()); // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 2.0 // to 1.0 st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); - /* Inserted simplex: */ - /* 1 6 */ - /* o---o */ - /* /X\7/ */ - /* o---o---o---o */ - /* 2 0 3\X/4 */ - /* o */ - /* 5 */ - - BOOST_CHECK(st.make_filtration_non_decreasing()); + // Inserted simplex: + // 1 6 + // o---o + // /X\7/ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 - // Check make_filtration_non_decreasing is just not modifying root values - st_bis.insert_simplex_and_subfaces({0, 1, 6, 7}, 2.0); - st_bis.assign_filtration(st_bis.find({0}), 1.0); - st_bis.assign_filtration(st_bis.find({1}), 1.0); - st_bis.assign_filtration(st_bis.find({6}), 1.0); - st_bis.assign_filtration(st_bis.find({7}), 1.0); + std::cout << "Check default second insertion ensures the filtration values are non decreasing" << std::endl; + BOOST_CHECK(!st.make_filtration_non_decreasing()); - BOOST_CHECK(st == st_bis); + // Copy original simplex tree + typeST st_copy = st; - // Check make_filtration_non_decreasing can modify non-root values (leaves and non-leaf) - st.assign_filtration(st.find({0, 1, 6, 7}), 1.99); - st.assign_filtration(st.find({3, 4}), 1.5); - st.assign_filtration(st.find({0, 3}), -1.0); + // Modify specific values for st to become like st_copy thanks to make_filtration_non_decreasing + st.assign_filtration(st.find({0,1,6,7}), 0.8); + st.assign_filtration(st.find({0,1,6}), 0.9); + st.assign_filtration(st.find({0,6}), 0.6); + st.assign_filtration(st.find({3,4,5}), 1.2); + st.assign_filtration(st.find({3,4}), 1.1); + st.assign_filtration(st.find({4,5}), 1.99); + + std::cout << "Check the simplex_tree is rolled back in case of decreasing filtration values" << std::endl; BOOST_CHECK(st.make_filtration_non_decreasing()); - BOOST_CHECK(st == st_bis); + BOOST_CHECK(st == st_copy); - // Check make_filtration_non_decreasing is not modifying when increasing - st.assign_filtration(st.find({0, 1, 6, 7}), 4.5); - st.assign_filtration(st.find({3, 4, 5}), 15.0); + // Other simplex tree + typeST st_other; + st_other.insert_simplex_and_subfaces({2, 1, 0}, 3.0); // This one is different from st + st_other.insert_simplex_and_subfaces({3, 0}, 2.0); + st_other.insert_simplex_and_subfaces({3, 4, 5}, 2.0); + st_other.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); + + // Modify specific values for st to become like st_other thanks to make_filtration_non_decreasing + st.assign_filtration(st.find({2}), 3.0); + // By modifying just the simplex {2} + // {0,1,2}, {1,2} and {0,2} will be modified + + std::cout << "Check the simplex_tree is repaired in case of decreasing filtration values" << std::endl; + BOOST_CHECK(st.make_filtration_non_decreasing()); + BOOST_CHECK(st == st_other); + + // Modify specific values for st still to be non-decreasing + st.assign_filtration(st.find({0,1,2}), 10.0); + st.assign_filtration(st.find({0,2}), 9.0); + st.assign_filtration(st.find({0,1,6,7}), 50.0); + st.assign_filtration(st.find({0,1,6}), 49.0); + st.assign_filtration(st.find({0,1,7}), 48.0); + // Other copy simplex tree + typeST st_other_copy = st; + + std::cout << "Check the simplex_tree is not modified in case of non-decreasing filtration values" << std::endl; BOOST_CHECK(!st.make_filtration_non_decreasing()); - + BOOST_CHECK(st == st_other_copy); + } struct MyOptions : Simplex_tree_options_full_featured { -- cgit v1.2.3 From cbf1f4c98c9e6d7ba3b7c552e43c7c98ed349954 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Feb 2016 10:03:48 +0000 Subject: Make example for doc shorter. Include strategy reviewal git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@992 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 23d3e71d7d0fb4d649f73e53959626c5cbb0acd8 --- src/Alpha_complex/example/Alpha_complex_from_off.cpp | 9 +++++---- .../example/Alpha_complex_from_points.cpp | 18 ++---------------- src/Alpha_complex/include/gudhi/Alpha_complex.h | 1 - .../example/alpha_complex_persistence.cpp | 17 ++++++++++------- 4 files changed, 17 insertions(+), 28 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 4f381892..780f904b 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,12 +1,13 @@ +#include +#include + #include #include -#include - void usage(char * const progName) { std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value" << std::endl; std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0" << std::endl; - exit(-1); // ----- >> + exit(-1); // ----- >> } int main(int argc, char **argv) { @@ -23,7 +24,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); - + // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 00e988a6..dab161c9 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -1,31 +1,17 @@ -#include -#include #include +#include #include #include #include -#include - typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel; typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " alpha_square_max_value" << std::endl; - std::cerr << " i.e.: " << progName << " 32.0" << std::endl; - exit(-1); // ----- >> -} - int main(int argc, char **argv) { - if (argc != 2) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } + double alpha_square_max_value = 32.0; - double alpha_square_max_value = atof(argv[1]); - // ---------------------------------------------------------------------------- // Init of a list of points // ---------------------------------------------------------------------------- diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 1ab6766c..962ed8dc 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -34,7 +34,6 @@ #include // isnan, fmax #include -#include #include #include diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp index 0dabdeac..d2f9a4a2 100644 --- a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -1,13 +1,15 @@ -#include -#include - #include +#include // to construct a Delaunay_triangulation from a OFF file #include #include #include +#include +#include +#include // for numeric_limits + void program_options(int argc, char * argv[] , std::string & off_file_points , std::string & output_file_diag @@ -21,10 +23,10 @@ int main(int argc, char **argv) { Filtration_value alpha_square_max_value; int coeff_field_characteristic; Filtration_value min_persistence; - - program_options(argc, argv, off_file_points, output_file_diag, alpha_square_max_value, coeff_field_characteristic, min_persistence); - + program_options(argc, argv, off_file_points, output_file_diag, alpha_square_max_value, + coeff_field_characteristic, min_persistence); + // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- @@ -80,7 +82,8 @@ void program_options(int argc, char * argv[] ("help,h", "produce help message") ("output-file,o", po::value(&output_file_diag)->default_value(std::string()), "Name of file in which the persistence diagram is written. Default print in std::cout") - ("max-alpha-square-value,r", po::value(&alpha_square_max_value)->default_value(std::numeric_limits::infinity()), + ("max-alpha-square-value,r", + po::value(&alpha_square_max_value)->default_value(std::numeric_limits::infinity()), "Maximal alpha square value for the Alpha complex construction.") ("field-charac,p", po::value(&coeff_field_characteristic)->default_value(11), "Characteristic p of the coefficient field Z/pZ for computing homology.") -- cgit v1.2.3 From 26bed354555e0f0fc18c6adc6a4b0fe27379a4a6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 3 Feb 2016 11:37:33 +0000 Subject: Mentionning Delaunay complex in Alpha complex documentation (user and reference) Specifying Alpha complex Kernel must be an Epick_d dD kernel (user and reference) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@998 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b1a7a0cadd236bbfa6c529f2979ad2096414e207 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 4 +++- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 8eea6ba7..b109956d 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -52,10 +52,12 @@ namespace alphacomplex { * \cite cgal:hdj-t-15b from CGAL (the Computational Geometry * Algorithms Library \cite cgal:eb-15b). * - * The complex is a template class requiring a dD Geometry Kernel * \cite cgal:s-gkd-15b from CGAL as template. * + * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. + * * \section pointsexample Example from points * * This example builds the Delaunay triangulation from the given points in a 2D static kernel, and initializes the diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 962ed8dc..0898c6cd 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -57,6 +57,12 @@ namespace alphacomplex { * * Please refer to \ref alpha_complex for examples. * + * The complex is a template class requiring an Epick_d dD Geometry Kernel + * \cite cgal:s-gkd-15b from CGAL as template. + * + * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. + * */ template class Alpha_complex : public Simplex_tree<> { -- cgit v1.2.3 From 1f7bd529827a5da3fdae315935a682c4337ca7cd Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 10:28:31 +0000 Subject: Alpha complex documentation generated had no scrolling menu for alpha complexes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1039 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 91b8bc91510c4605956682db729f80c03f9b982f --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 0898c6cd..5183828f 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -49,7 +49,9 @@ namespace alphacomplex { /** * \brief Alpha complex data structure. - * + * + * \ingroup alpha_complex + * * \details * The data structure can be constructed from a CGAL Delaunay triangulation (for more informations on CGAL Delaunay * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) or from -- cgit v1.2.3 From a28d3c6ba5ab9687626992cc0402c4399c76ecaf Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 15 Mar 2016 14:23:19 +0000 Subject: In Delaunay_triangulation_off_io.h, constructing the Triangulation from a vector of Points is a more efficient way (instead of inserting points on the fly). As consequence, the documentation needs to be rewritten as the points index are changed. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1046 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: bdb0196b61418a983cfaf7f6781a3a2906e8b136 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 8 +- src/Alpha_complex/doc/alpha_complex_doc.ipe | 371 ++++++++++----- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 49973 -> 25150 bytes src/Alpha_complex/doc/alpha_complex_doc_135.ipe | 514 --------------------- src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 80794 -> 0 bytes src/Alpha_complex/doc/alpha_complex_doc_421.ipe | 514 +++++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc_421.png | Bin 0 -> 100798 bytes .../doc/alpha_complex_representation.ipe | 14 +- .../doc/alpha_complex_representation.png | Bin 16737 -> 14628 bytes src/Alpha_complex/example/CMakeLists.txt | 8 +- .../example/alphaoffreader_for_doc_32.txt | 26 +- .../example/alphaoffreader_for_doc_60.txt | 36 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 1 + src/common/example/CMakeLists.txt | 6 + .../example/dtoffrw_alphashapedoc_result.off | 18 +- .../include/gudhi/Delaunay_triangulation_off_io.h | 26 +- src/common/test/CMakeLists.txt | 4 +- src/common/test/dtoffrw_alphashapedoc_result.off | 18 +- 18 files changed, 851 insertions(+), 713 deletions(-) delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.ipe delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.png create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_421.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_421.png (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 0987e0e7..deecf93f 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -112,19 +112,19 @@ namespace alphacomplex { * * \subsubsection dimension2 Dimension 2 * - * From the example above, it means the algorithm looks into each triangle ([1,2,3], [2,3,4], [1,3,5], ...), + * From the example above, it means the algorithm looks into each triangle ([4,2,1], [2,4,6], [4,5,6], ...), * computes the filtration value of the triangle, and then propagates the filtration value as described * here : - * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" + * \image html "alpha_complex_doc_421.png" "Filtration value propagation example" * * \subsubsection dimension1 Dimension 1 * - * Then, the algorithm looks into each edge ([1,2], [2,3], [1,3], ...), + * Then, the algorithm looks into each edge ([1,2], [4,2], [4,1], ...), * computes the filtration value of the edge (in this case, propagation will have no effect). * * \subsubsection dimension0 Dimension 0 * - * Finally, the algorithm looks into each vertex ([1], [2], [3], [4], [5], [6] and [7]) and + * Finally, the algorithm looks into each vertex ([0], [1], [2], [3], [4], [5] and [6]) and * sets the filtration value (0 in case of a vertex - propagation will have no effect). * * \subsubsection nondecreasing Non decreasing filtration values diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe index e74f9bc4..99bd05af 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -1,7 +1,7 @@ - + @@ -253,13 +253,13 @@ h 320 580 l Delaunay triangulation -0 -1 -2 -3 -4 -5 -6 +2 +6 +4 +5 +1 +3 +0 280 660 m 300 710 l @@ -278,161 +278,282 @@ h 320 580 l 280 660 l -0 -1 -2 -2 -1 -2 -2 -3 -3 -3 -3 -4 -4 -4 -4 -6 -6 -6 -6 -6 -6 -5 -6 -5 - + 4 0 0 4 320 704 e - + 322.919 706.788 m 317.189 701.058 l 317.189 701.203 l - + 317.551 706.934 m 322.629 701.058 l - -230 680 m -240 670 l + +240 620 m +220 600 l - -230 680 m -240 670 l + +240 620 m +220 640 l - -230 680 m -240 670 l +Simplex tree structure + +280 630 m +170 630 l - -230 680 m -240 670 l + +280 610 m +170 610 l - -230 680 m -220 670 l + + + + + + + +3 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -230 680 m -230 670 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -220 660 m -220 650 l +4 +3 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -230 660 m -230 650 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -260 680 m -260 670 l +4 +1 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -260 660 m -260 650 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -300 680 m -300 670 l +5 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -300 680 m -290 670 l +5 +3 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -290 660 m -290 650 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -300 660 m -300 650 l +4 +2 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -330 680 m -330 670 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -350 680 m -350 670 l +4 +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -350 660 m -350 650 l +4 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -240 690 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -270 690 l +6 +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -310 690 l +5 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -330 690 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -350 690 l +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -380 690 l +6 + +292 716 m +292 728 l +316 728 l +316 716 l +h - -320 700 m -400 690 l + +316 716 m +316 728 l +340 728 l +340 716 l +h - -240 620 m -220 600 l + +340 716 m +340 728 l +364 728 l +364 716 l +h - -240 620 m -220 640 l + +364 716 m +364 728 l +388 728 l +388 716 l +h + + +388 716 m +388 728 l +412 728 l +412 716 l +h + + +412 716 m +412 728 l +436 728 l +436 716 l +h + + +436 716 m +436 728 l +460 728 l +460 716 l +h + +0 +1 +2 +3 +4 +5 +6 + +436 708 m +436 716 l + + +364 708 m +364 716 l + + +364 688 m +364 696 l + + +320 688 m +320 696 l + + +296 708 m +308 716 l +308 716 l + + +264 688 m +268 696 l + + +292 688 m +292 696 l + + +388 736 m +388 728 l -Simplex tree structure -280 630 m -170 630 l +372 612 m +376 620 l -280 610 m -170 610 l +448 612 m +448 620 l - - - - - - - diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index c9eab275..cfe3ede6 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc.png and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe deleted file mode 100644 index 5d1d29d4..00000000 --- a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe +++ /dev/null @@ -1,514 +0,0 @@ - - - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - -0.6 0 0 0.6 0 0 e - - - - - -0.5 0 0 0.5 0 0 e - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h - - - - - --0.5 -0.5 m -0.5 -0.5 l -0.5 0.5 l --0.5 0.5 l -h - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - - - --0.43 -0.57 m -0.57 0.43 l -0.43 0.57 l --0.57 -0.43 l -h - - --0.43 0.57 m -0.57 -0.43 l -0.43 -0.57 l --0.57 0.43 l -h - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - --1 0.333 m -0 0 l --1 -0.333 l - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -Cell [4,2,0] -0 -1 -2 -3 -4 -5 -6 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - - -77.2727 0 0 77.2727 243.636 591.818 e - - -243.428 591.569 m -186.061 643.28 l - -$\alpha_{420}$ - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -[2,0] is Gabriel $\rightarrow$ $\alpha_{20}$ is not$\\$ -modified (NaN) - -0 -2 -3 -4 -5 -6 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{20}$ - -290 530 m -320 580 l - - -29.1548 0 0 29.1548 305 555 e - - -304.883 555.015 m -334.509 555.015 l - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -[0,4] is not Gabriel $\rightarrow$ $\alpha_{40} = \alpha_{420}$ -0 -3 -5 -6 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{40}$ - -290 530 m -280 660 l - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -0 -1 -2 -3 -5 -6 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{42}$ -4 - -406.093 497.775 m -446.094 418.092 l - - -44.5799 0 0 44.5799 425.934 457.774 e - - -425.854 457.774 m -470.795 457.774 l - -[2,4] is Gabriel $\rightarrow$ $\alpha_{42}$ is not modified (NaN) - - -205.028 596.091 m -110.946 544.02 l - - -280.768 588.99 m -280.768 547.57 l - - -341.123 594.316 m -413.904 554.079 l - -For all faces of [4,2,0] -N.B. : is Gabriel on a single point has no sense. -Dimension =2 - $\sigma$ = [4,2,0] - -247.333 430.892 m -311.764 430.892 l - - - - - - - - - - - - - - -1 - - - - - -4 - - -1 - - -2 - -65.192 0 0 65.192 285 595 e - - - - - - - - - - - - - diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png deleted file mode 100644 index ef7187f7..00000000 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_135.png and /dev/null differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_421.ipe b/src/Alpha_complex/doc/alpha_complex_doc_421.ipe new file mode 100644 index 00000000..727816c5 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc_421.ipe @@ -0,0 +1,514 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +Cell [4,2,1] +2 +6 +4 +5 +1 +3 +0 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + + +77.2727 0 0 77.2727 243.636 591.818 e + + +243.428 591.569 m +186.061 643.28 l + +$\alpha_{421}$ + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[4,2] is Gabriel $\rightarrow$ $\alpha_{42}$ is not$\\$ +modified (NaN) + +2 +4 +5 +1 +3 +0 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{42}$ + +290 530 m +320 580 l + + +29.1548 0 0 29.1548 305 555 e + + +304.883 555.015 m +334.509 555.015 l + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[2,1] is not Gabriel $\rightarrow$ $\alpha_{21} = \alpha_{421}$ +2 +5 +3 +0 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{12}$ + +290 530 m +280 660 l + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +2 +6 +4 +5 +3 +0 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{41}$ +1 + +406.093 497.775 m +446.094 418.092 l + + +44.5799 0 0 44.5799 425.934 457.774 e + + +425.854 457.774 m +470.795 457.774 l + +[4,1] is Gabriel $\rightarrow$ $\alpha_{41}$ is not modified (NaN) + + +205.028 596.091 m +110.946 544.02 l + + +280.768 588.99 m +280.768 547.57 l + + +341.123 594.316 m +413.904 554.079 l + +For all faces of [4,2,1] +N.B. : is Gabriel on a single point has no sense. +Dimension =2 - $\sigma$ = [4,2,1] + +247.333 430.892 m +311.764 430.892 l + + + + + + + + + + + + + + +6 + + + + + +1 + + +6 + + +4 + +65.192 0 0 65.192 285 595 e + + + + + + + + + + + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_421.png b/src/Alpha_complex/doc/alpha_complex_doc_421.png new file mode 100644 index 00000000..1cce4402 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc_421.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_representation.ipe b/src/Alpha_complex/doc/alpha_complex_representation.ipe index 8687d694..fead1661 100644 --- a/src/Alpha_complex/doc/alpha_complex_representation.ipe +++ b/src/Alpha_complex/doc/alpha_complex_representation.ipe @@ -251,13 +251,13 @@ h h Alpha complex -0 -1 -2 -3 -4 -5 -6 +2 +6 +4 +5 +1 +3 +0 58.1341 0 0 58.1341 218.925 692.601 e diff --git a/src/Alpha_complex/doc/alpha_complex_representation.png b/src/Alpha_complex/doc/alpha_complex_representation.png index 06e54c06..9833bff3 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_representation.png and b/src/Alpha_complex/doc/alpha_complex_representation.png differ diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index e904133b..debb440d 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -18,15 +18,15 @@ if(CGAL_FOUND) # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - # Do not forget to copy test results files in current binary dir - file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - file(COPY "alphaoffreader_for_doc_60.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(alphaoffreader_doc_60 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader alphacomplexdoc.off 60.0 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt) add_test(alphaoffreader_doc_32 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader alphacomplexdoc.off 32.0 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt) if (DIFF_PATH) + # Do not forget to copy test results files in current binary dir + file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + file(COPY "alphaoffreader_for_doc_60.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + add_test(alphaoffreader_doc_60_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_60.txt) add_test(alphaoffreader_doc_32_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt) endif() diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt index 13183e86..5869fdff 100644 --- a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt @@ -7,16 +7,16 @@ Iterator on alpha complex simplices in the filtration order, with [filtration va ( 4 ) -> [0] ( 5 ) -> [0] ( 6 ) -> [0] - ( 3 2 ) -> [6.25] - ( 5 4 ) -> [7.25] - ( 2 0 ) -> [8.5] - ( 1 0 ) -> [9.25] - ( 3 1 ) -> [10] - ( 2 1 ) -> [11.25] - ( 3 2 1 ) -> [12.5] - ( 2 1 0 ) -> [12.9959] - ( 6 5 ) -> [13.25] - ( 4 2 ) -> [20] - ( 6 4 ) -> [22.7367] - ( 6 5 4 ) -> [22.7367] - ( 6 3 ) -> [30.25] + ( 5 4 ) -> [6.25] + ( 3 1 ) -> [7.25] + ( 4 2 ) -> [8.5] + ( 6 2 ) -> [9.25] + ( 6 5 ) -> [10] + ( 6 4 ) -> [11.25] + ( 6 5 4 ) -> [12.5] + ( 6 4 2 ) -> [12.9959] + ( 3 0 ) -> [13.25] + ( 4 1 ) -> [20] + ( 1 0 ) -> [22.7367] + ( 3 1 0 ) -> [22.7367] + ( 5 0 ) -> [30.25] diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt index 71f29a00..1d17a58a 100644 --- a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt @@ -7,21 +7,21 @@ Iterator on alpha complex simplices in the filtration order, with [filtration va ( 4 ) -> [0] ( 5 ) -> [0] ( 6 ) -> [0] - ( 3 2 ) -> [6.25] - ( 5 4 ) -> [7.25] - ( 2 0 ) -> [8.5] - ( 1 0 ) -> [9.25] - ( 3 1 ) -> [10] - ( 2 1 ) -> [11.25] - ( 3 2 1 ) -> [12.5] - ( 2 1 0 ) -> [12.9959] - ( 6 5 ) -> [13.25] - ( 4 2 ) -> [20] - ( 6 4 ) -> [22.7367] - ( 6 5 4 ) -> [22.7367] - ( 6 3 ) -> [30.25] - ( 6 2 ) -> [36.5] - ( 6 3 2 ) -> [36.5] - ( 6 4 2 ) -> [37.2449] - ( 4 0 ) -> [59.7107] - ( 4 2 0 ) -> [59.7107] + ( 5 4 ) -> [6.25] + ( 3 1 ) -> [7.25] + ( 4 2 ) -> [8.5] + ( 6 2 ) -> [9.25] + ( 6 5 ) -> [10] + ( 6 4 ) -> [11.25] + ( 6 5 4 ) -> [12.5] + ( 6 4 2 ) -> [12.9959] + ( 3 0 ) -> [13.25] + ( 4 1 ) -> [20] + ( 1 0 ) -> [22.7367] + ( 3 1 0 ) -> [22.7367] + ( 5 0 ) -> [30.25] + ( 4 0 ) -> [36.5] + ( 5 4 0 ) -> [36.5] + ( 4 1 0 ) -> [37.2449] + ( 2 1 ) -> [59.7107] + ( 4 2 1 ) -> [59.7107] diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 5183828f..a69afb51 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -48,6 +48,7 @@ namespace Gudhi { namespace alphacomplex { /** + * \class Alpha_complex Alpha_complex.h gudhi/Alpha_complex.h * \brief Alpha complex data structure. * * \ingroup alpha_complex diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index 6c2e7669..91e78ea2 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -13,6 +13,12 @@ if(CGAL_FOUND) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(dtoffrw ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) + if (DIFF_PATH) + # Do not forget to copy test results files in current binary dir + file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + add_test(dtoffrw_result_off_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) + endif() + else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/common/example/dtoffrw_alphashapedoc_result.off b/src/common/example/dtoffrw_alphashapedoc_result.off index 03b7ca75..d1839a43 100644 --- a/src/common/example/dtoffrw_alphashapedoc_result.off +++ b/src/common/example/dtoffrw_alphashapedoc_result.off @@ -1,15 +1,15 @@ nOFF 2 7 6 0 +9 17 +0 14 1 1 -7 0 +2 19 4 6 9 6 -0 14 -2 19 -9 17 -3 0 1 2 -3 3 2 1 -3 4 0 2 -3 4 2 6 -3 6 2 3 +7 0 +3 5 0 4 +3 0 1 4 +3 3 1 0 +3 4 1 2 3 5 4 6 +3 6 4 2 diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index b3f4a299..529774f0 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -31,7 +31,9 @@ namespace Gudhi { -/** \brief OFF file visitor implementation according to Off_reader in order to construct a CGAL Delaunay triangulation. +/** + * \class Delaunay_triangulation_off_visitor_reader Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h + * \brief OFF file visitor implementation according to Off_reader in order to construct a CGAL Delaunay triangulation. * * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page * http://doc.cgal.org/latest/Triangulation/ @@ -41,7 +43,7 @@ class Delaunay_triangulation_off_visitor_reader { private: Complex* complex_; typedef typename Complex::Point Point; - + std::vector point_cloud; public: // TODO(VR) : Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. @@ -95,7 +97,9 @@ class Delaunay_triangulation_off_visitor_reader { } std::cout << std::endl; #endif // DEBUG_TRACES - complex_->insert(Point(point.size(), point.begin(), point.end())); + // Fill the point cloud + // VR: complex_->insert(Point(point.size(), point.begin(), point.end())); + point_cloud.push_back(Point(point.size(), point.begin(), point.end())); } // Off_reader visitor maximal_face implementation - not used @@ -103,9 +107,11 @@ class Delaunay_triangulation_off_visitor_reader { // For Delaunay Triangulation, only points are read } - // Off_reader visitor done implementation - not used + // Off_reader visitor done implementation void done() { - // Nothing to be done on end of OFF file read + // It is advised to insert all the points at a time in a Delaunay Triangulation because points are sorted at the + // beginning of the insertion + complex_->insert(point_cloud.begin(), point_cloud.end()); } /** \brief Returns the constructed Delaunay triangulation. @@ -119,7 +125,9 @@ class Delaunay_triangulation_off_visitor_reader { } }; -/** \brief OFF file reader implementation in order to construct a Delaunay triangulation. +/** + * \class Delaunay_triangulation_off_reader Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h + * \brief OFF file reader implementation in order to construct a Delaunay triangulation. * * This class is using the Delaunay_triangulation_off_visitor_reader to visit the OFF file according to Off_reader. * @@ -135,7 +143,7 @@ class Delaunay_triangulation_off_visitor_reader { * * When launching: * - * \code $> ./dtoffrw ../../data/points/alphacomplexdoc triangulated.off + * \code $> ./dtoffrw ../../data/points/alphacomplexdoc.off triangulated.off * \endcode * * the program output is: @@ -203,7 +211,9 @@ class Delaunay_triangulation_off_reader { Complex* complex_; }; -/** \brief OFF file writer from a Delaunay triangulation. +/** + * \class Delaunay_triangulation_off_writer Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h + * \brief OFF file writer from a Delaunay triangulation. * * This class constructs the OFF file header according to http://www.geomview.org/docs/html/OFF.html * diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 50655a93..12eecda8 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -21,8 +21,6 @@ if(CGAL_FOUND) add_executable ( dtoffrw_UT dtoffrw_unit_test.cpp ) target_link_libraries(dtoffrw_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - # Do not forget to copy test files in current binary dir - file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) @@ -32,6 +30,8 @@ if(CGAL_FOUND) --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/dtoffrw_UT.xml --log_level=test_suite --report_level=no) if (DIFF_PATH) + # Do not forget to copy test result files in current binary dir + file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) add_test(dtoffrw_diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) endif() diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off index 03b7ca75..d1839a43 100644 --- a/src/common/test/dtoffrw_alphashapedoc_result.off +++ b/src/common/test/dtoffrw_alphashapedoc_result.off @@ -1,15 +1,15 @@ nOFF 2 7 6 0 +9 17 +0 14 1 1 -7 0 +2 19 4 6 9 6 -0 14 -2 19 -9 17 -3 0 1 2 -3 3 2 1 -3 4 0 2 -3 4 2 6 -3 6 2 3 +7 0 +3 5 0 4 +3 0 1 4 +3 3 1 0 +3 4 1 2 3 5 4 6 +3 6 4 2 -- cgit v1.2.3 From 298c080b45250f2b8f16a0c31ace9bb6fc666c93 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 16 Mar 2016 08:33:04 +0000 Subject: CppCheck and CppLint fixes for alpha complexes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1047 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a9b42ad2f8751384b5227fa3da8f380cda9b3696 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 4 ++-- .../example/Alpha_complex_from_off.cpp | 2 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 21 ++++++++++----------- src/GudhUI/model/Model.h | 2 +- src/GudhUI/utils/Bar_code_persistence.h | 11 ++++++++--- src/GudhUI/utils/Persistence_compute.h | 1 - src/GudhUI/view/FirstCoordProjector.h | 1 - .../example/alpha_complex_3d_persistence.cpp | 15 ++++----------- .../example/Delaunay_triangulation_off_rw.cpp | 14 +++++++------- .../include/gudhi/Delaunay_triangulation_off_io.h | 10 +++------- src/common/include/gudhi/Off_reader.h | 2 +- 11 files changed, 37 insertions(+), 46 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index deecf93f..f55d7029 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -161,8 +161,8 @@ namespace alphacomplex { */ /** @} */ // end defgroup alpha_complex -} // namespace alphacomplex +} // namespace alphacomplex -} // namespace Gudhi +} // namespace Gudhi #endif // INTRO_ALPHA_COMPLEX_H_ diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 80445a22..18a1a20d 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -27,7 +27,7 @@ int main(int argc, char **argv) { std::streambuf* streambufffer; std::ofstream ouput_file_stream; - + if (argc == 4) { ouput_file_stream.open(std::string(argv[3])); streambufffer = ouput_file_stream.rdbuf(); diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index a69afb51..eab66384 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef ALPHA_COMPLEX_H_ -#define ALPHA_COMPLEX_H_ +#ifndef DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ +#define DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ // to construct a simplex_tree from Delaunay_triangulation #include @@ -97,7 +97,6 @@ class Alpha_complex : public Simplex_tree<> { // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; - //typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; typedef typename std::vector< CGAL_vertex_iterator > Vector_vertex_iterator; private: @@ -141,7 +140,7 @@ class Alpha_complex : public Simplex_tree<> { Alpha_complex(Delaunay_triangulation* triangulation_ptr, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(triangulation_ptr) { - init(max_alpha_square); + init(max_alpha_square); } /** \brief Alpha_complex constructor from a list of points. @@ -160,17 +159,17 @@ class Alpha_complex : public Simplex_tree<> { : triangulation_(nullptr) { auto first = std::begin(points); auto last = std::end(points); - + GUDHI_CHECK((first == last), - std::invalid_argument ("Alpha_complex::Alpha_complex(InputPointRange) - Empty input point range")); - + std::invalid_argument("Alpha_complex::Alpha_complex(InputPointRange) - Empty input point range")); + if (first != last) { // point_dimension function initialization Point_Dimension point_dimension = kernel_.point_dimension_d_object(); // Delaunay triangulation is point dimension minus one. triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); - + size_type inserted = triangulation_->insert(first, last); if (inserted != (last -first)) { std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << "\n"; @@ -227,7 +226,7 @@ class Alpha_complex : public Simplex_tree<> { } set_dimension(triangulation_->maximal_dimension()); - // set_filtration to +inf for prune_above_filtration to be done (if necessary) + // set_filtration to +inf for prune_above_filtration to be done (if necessary) set_filtration(std::numeric_limits::infinity()); // -------------------------------------------------------------------------------------------- @@ -247,7 +246,7 @@ class Alpha_complex : public Simplex_tree<> { } } // -------------------------------------------------------------------------------------------- - + // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { @@ -393,4 +392,4 @@ class Alpha_complex : public Simplex_tree<> { } // namespace Gudhi -#endif // ALPHA_COMPLEX_H_ +#endif // DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ diff --git a/src/GudhUI/model/Model.h b/src/GudhUI/model/Model.h index 99a82eba..1c39c0d7 100644 --- a/src/GudhUI/model/Model.h +++ b/src/GudhUI/model/Model.h @@ -71,7 +71,7 @@ class CGAL_geometric_flag_complex_wrapper { void maximal_face(std::vector vertices) { if (!load_only_points_) { - //std::cout << "size:" << vertices.size() << std::endl; + // std::cout << "size:" << vertices.size() << std::endl; for (int i = 0; i < vertices.size(); ++i) for (int j = i + 1; j < vertices.size(); ++j) complex_.add_edge(Vertex_handle(vertices[i]), Vertex_handle(vertices[j])); diff --git a/src/GudhUI/utils/Bar_code_persistence.h b/src/GudhUI/utils/Bar_code_persistence.h index a4cd8156..b527d684 100644 --- a/src/GudhUI/utils/Bar_code_persistence.h +++ b/src/GudhUI/utils/Bar_code_persistence.h @@ -12,6 +12,10 @@ #include #include // NaN, infinity #include // for pair +#include + +#ifndef UTILS_BAR_CODE_PERSISTENCE_H_ +#define UTILS_BAR_CODE_PERSISTENCE_H_ class Bar_code_persistence { private: @@ -21,7 +25,6 @@ class Bar_code_persistence { double max_death; public: - Bar_code_persistence() : min_birth(std::numeric_limits::quiet_NaN()), max_death(std::numeric_limits::quiet_NaN()) { } @@ -45,13 +48,13 @@ class Bar_code_persistence { QGraphicsScene * scene = new QGraphicsScene(); view->setScene(scene); double ratio = 600.0 / (max_death - min_birth); - //std::cout << "min_birth=" << min_birth << " - max_death=" << max_death << " - ratio=" << ratio << std::endl; + // std::cout << "min_birth=" << min_birth << " - max_death=" << max_death << " - ratio=" << ratio << std::endl; double height = 0.0, birth = 0.0, death = 0.0; int pers_num = 1; for (auto& persistence : persistence_vector) { height = 5.0 * pers_num; - //std::cout << "[" << pers_num << "] birth=" << persistence.first << " - death=" << persistence.second << std::endl; + // std::cout << "[" << pers_num << "] birth=" << persistence.first << " - death=" << persistence.second << std::endl; if (std::isfinite(persistence.first)) birth = ((persistence.first - min_birth) * ratio) + 50.0; else @@ -83,3 +86,5 @@ class Bar_code_persistence { view->show(); } }; + +#endif // UTILS_BAR_CODE_PERSISTENCE_H_ diff --git a/src/GudhUI/utils/Persistence_compute.h b/src/GudhUI/utils/Persistence_compute.h index 1f04cc6b..97165490 100644 --- a/src/GudhUI/utils/Persistence_compute.h +++ b/src/GudhUI/utils/Persistence_compute.h @@ -85,7 +85,6 @@ template class Persistence_compute { stream << "p dimension birth death: \n"; pcoh.output_diagram(stream); - } }; diff --git a/src/GudhUI/view/FirstCoordProjector.h b/src/GudhUI/view/FirstCoordProjector.h index 3ceda3f5..a4027b7f 100644 --- a/src/GudhUI/view/FirstCoordProjector.h +++ b/src/GudhUI/view/FirstCoordProjector.h @@ -36,7 +36,6 @@ class FirstCoordProjector3D : public Projector3D { return Point_3(p.x(), p.y(), p.z()); else if (p.dimension() >= 2) return Point_3(p.x(), p.y(), 0.0); - } }; diff --git a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp index ac208957..f81951ce 100644 --- a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp @@ -39,9 +39,6 @@ #include #include -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; - // Alpha_shape_3 templates type definitions typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Alpha_shape_vertex_base_3 Vb; @@ -66,11 +63,12 @@ typedef Alpha_shape_3::Edge Edge_3; typedef std::list Vertex_list; // gudhi type definition -typedef Simplex_tree ST; +typedef Gudhi::Simplex_tree ST; typedef ST::Vertex_handle Simplex_tree_vertex; typedef std::map Alpha_shape_simplex_tree_map; typedef std::pair Alpha_shape_simplex_tree_pair; typedef std::vector< Simplex_tree_vertex > Simplex_tree_vector_vertex; +typedef Gudhi::persistent_cohomology::Persistent_cohomology< ST, Gudhi::persistent_cohomology::Field_Zp > PCOH; Vertex_list from(const Cell_handle& ch) { Vertex_list the_list; @@ -131,12 +129,7 @@ int main(int argc, char * const argv[]) { usage(argv[0]); } - int coeff_field_characteristic = 0; - int returnedScanValue = sscanf(argv[2], "%d", &coeff_field_characteristic); - if ((returnedScanValue == EOF) || (coeff_field_characteristic <= 0)) { - std::cerr << "Error: " << argv[2] << " is not correct\n"; - usage(argv[0]); - } + int coeff_field_characteristic = atoi(argv[2]); Filtration_value min_persistence = 0.0; returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); @@ -282,7 +275,7 @@ int main(int argc, char * const argv[]) { std::cout << "Simplex_tree dim: " << simplex_tree.dimension() << std::endl; // Compute the persistence diagram of the complex - Persistent_cohomology< ST, Field_Zp > pcoh(simplex_tree); + PCOH pcoh(simplex_tree); // initializes the coefficient field for homology pcoh.init_coefficients(coeff_field_characteristic); diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp index 75e4fafb..4c7a9aaf 100644 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -10,12 +10,12 @@ // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instantiation of the +// The triangulation uses the default instantiation of the // TriangulationDataStructure template parameter void usage(char * const progName) { std::cerr << "Usage: " << progName << " inputFile.off outputFile.off" << std::endl; - exit(-1); // ----- >> + exit(-1); } int main(int argc, char **argv) { @@ -30,9 +30,9 @@ int main(int argc, char **argv) { // Check the read operation was correct if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << offInputFile << std::endl; - exit(-1); // ----- >> + exit(-1); } - + // Retrieve the triangulation T* triangulation = off_reader.get_complex(); // Operations on triangulation @@ -47,8 +47,8 @@ int main(int argc, char **argv) { // Check the write operation was correct if (!off_writer.is_valid()) { std::cerr << "Unable to write file " << offOutputFile << std::endl; - exit(-1); // ----- >> + exit(-1); } - + return 0; -} \ No newline at end of file +} diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 529774f0..e623cf7b 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -44,8 +44,8 @@ class Delaunay_triangulation_off_visitor_reader { Complex* complex_; typedef typename Complex::Point Point; std::vector point_cloud; - public: + public: // TODO(VR) : Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. /** \brief Delaunay_triangulation_off_visitor_reader constructor @@ -153,7 +153,6 @@ class Delaunay_triangulation_off_visitor_reader { template class Delaunay_triangulation_off_reader { public: - /** \brief Reads the OFF file and constructs the Delaunay triangulation from the points * that are in the OFF file. * @@ -180,7 +179,6 @@ class Delaunay_triangulation_off_reader { std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << name_file << "\n"; } - } /** \brief Returns if the OFF file read operation was successful or not. @@ -201,7 +199,6 @@ class Delaunay_triangulation_off_reader { if (valid_) return complex_; return nullptr; - } private: @@ -285,7 +282,6 @@ class Delaunay_triangulation_off_writer { } for (auto cit = complex_ptr->finite_full_cells_begin(); cit != complex_ptr->finite_full_cells_end(); ++cit) { - std::vector vertexVector; stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { stream << points_to_vh[(*vit)->point()] - 1 << " "; @@ -299,7 +295,7 @@ class Delaunay_triangulation_off_writer { name_file << "\n"; } } - + /** \brief Returns if the OFF write operation was successful or not. * * @return OFF file write status. @@ -313,6 +309,6 @@ class Delaunay_triangulation_off_writer { bool valid_; }; -} // namespace Gudhi +} // namespace Gudhi #endif // DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index e45a7600..2420ae72 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -160,7 +160,7 @@ class Off_reader { iss >> num_face_vertices; std::vector face; face.assign(std::istream_iterator(iss), std::istream_iterator()); - //if (face.size() != (off_info_.dim + 1)) return false; + // if (face.size() != (off_info_.dim + 1)) return false; visitor.maximal_face(face); } return true; -- cgit v1.2.3 From fa4810bea8d480f09d4cba5beba51805522cfdfe Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 17 Mar 2016 10:13:47 +0000 Subject: Fix cpplint/cppcheck git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1052 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d598999dec360fb4a80ca3e228128d889bfed3c7 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 6 +++--- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index f55d7029..0dea2b16 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef INTRO_ALPHA_COMPLEX_H_ -#define INTRO_ALPHA_COMPLEX_H_ +#ifndef DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ +#define DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ // needs namespace for Doxygen to link on classes namespace Gudhi { @@ -165,4 +165,4 @@ namespace alphacomplex { } // namespace Gudhi -#endif // INTRO_ALPHA_COMPLEX_H_ +#endif // DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index eab66384..415aa032 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ -#define DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ +#ifndef ALPHA_COMPLEX_H_ +#define ALPHA_COMPLEX_H_ // to construct a simplex_tree from Delaunay_triangulation #include @@ -392,4 +392,4 @@ class Alpha_complex : public Simplex_tree<> { } // namespace Gudhi -#endif // DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ +#endif // ALPHA_COMPLEX_H_ -- cgit v1.2.3 From 26e05a189a31846cd1aa97e055ff3595d9dddca1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 17 Mar 2016 13:44:28 +0000 Subject: Use post and exception doxygen tag instead of warnings everywhere. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1053 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 5e263835e662d66ef068c73d3efe71f72f90de10 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 5 +- src/Simplex_tree/include/gudhi/Simplex_tree.h | 79 ++++++++-------------- .../include/gudhi/Delaunay_triangulation_off_io.h | 19 ++---- 3 files changed, 37 insertions(+), 66 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 415aa032..2d2d77a5 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -150,8 +150,7 @@ class Alpha_complex : public Simplex_tree<> { * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. - * \warning In debug mode, the exception std::invalid_argument is thrown if an empty input point range is passed as - * argument. + * \exception std::invalid_argument In debug mode, if an empty input point range is passed as argument. */ template Alpha_complex(const InputPointRange& points, @@ -191,7 +190,7 @@ class Alpha_complex : public Simplex_tree<> { * * @param[in] vertex Vertex handle of the point to retrieve. * @return The point found. - * @warning Exception std::out_of_range is thrown in case vertex is not found. + * @exception std::out_of_range In case vertex is not found (cf. std::vector::at). */ Point_d get_point(Vertex_handle vertex) const { return vertex_handle_to_iterator_.at(vertex)->point(); diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index b7b4b8b2..7b55df11 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -47,7 +47,7 @@ #include #include // Inf #include -#include // for std::max +#include // for std::max namespace Gudhi { /** \defgroup simplex_tree Filtered Complexes @@ -141,7 +141,8 @@ class Simplex_tree { void assign_key(Simplex_key) { } Simplex_key key() const { assert(false); return -1; } }; - typedef typename std::conditional::type Key_simplex_base; + typedef typename std::conditional::type + Key_simplex_base; struct Filtration_simplex_base_real { Filtration_simplex_base_real() : filt_(0) {} @@ -450,7 +451,7 @@ class Simplex_tree { } /** \brief Sets the filtration value of a simplex. - * \warning In debug mode, the exception std::invalid_argument is thrown if sh is a null_simplex. + * \exception std::invalid_argument In debug mode, if sh is a null_simplex. */ void assign_filtration(Simplex_handle sh, Filtration_value fv) { GUDHI_CHECK(sh == null_simplex(), @@ -596,7 +597,19 @@ class Simplex_tree { private: /** \brief Inserts a simplex represented by a vector of vertex. - \warning the vector must be sorted by increasing vertex handle order */ + * @param[in] simplex vector of Vertex_handles, representing the vertices of the new simplex. The vector must be + * sorted by increasing vertex handle order. + * @param[in] filtration the filtration value assigned to the new simplex. + * @return If the new simplex is inserted successfully (i.e. it was not in the + * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned + * to the new simplex. + * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion + * fails and the simplex already in the complex has a filtration value strictly bigger than 'filtration', + * we assign this simplex with the new value 'filtration', and set the Simplex_handle field of the + * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to + * null_simplex. + * + */ std::pair insert_vertex_vector(const std::vector& simplex, Filtration_value filtration) { Siblings * curr_sib = &root_; @@ -629,7 +642,7 @@ class Simplex_tree { * * @param[in] simplex range of Vertex_handles, representing the vertices of the new simplex * @param[in] filtration the filtration value assigned to the new simplex. - * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the + * @return If the new simplex is inserted successfully (i.e. it was not in the * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned * to the new simplex. * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion @@ -668,7 +681,7 @@ class Simplex_tree { * * @param[in] Nsimplex range of Vertex_handles, representing the vertices of the new N-simplex * @param[in] filtration the filtration value assigned to the new N-simplex. - * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the + * @return If the new simplex is inserted successfully (i.e. it was not in the * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned * to the new simplex. * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion @@ -677,7 +690,7 @@ class Simplex_tree { * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to * null_simplex. */ - template> + template> std::pair insert_simplex_and_subfaces(const InputVertexRange& Nsimplex, Filtration_value filtration = 0) { auto first = std::begin(Nsimplex); @@ -1124,7 +1137,7 @@ class Simplex_tree { * The simplex tree is browsed starting from the root until the leaf, and the filtration values are set with their * parent value (increased), in case the values are decreasing. * @return The filtration modification information. - * \warning Some simplex tree functions require the filtration to be valid. `make_filtration_non_decreasing()` + * \post Some simplex tree functions require the filtration to be valid. `make_filtration_non_decreasing()` * function is not launching `initialize_filtration()` but returns the filtration modification information. If the * complex has changed , please call `initialize_filtration()` to recompute it. */ @@ -1154,7 +1167,7 @@ class Simplex_tree { Boundary_simplex_iterator max_border = std::max_element(std::begin(boundary), std::end(boundary), [](Simplex_handle sh1, Simplex_handle sh2) { return filtration(sh1) < filtration(sh2); - } ); + }); Filtration_value max_filt_border_value = filtration(*max_border); if (simplex.second.filtration() < max_filt_border_value) { @@ -1173,7 +1186,7 @@ class Simplex_tree { public: /** \brief Prune above filtration value given as parameter. * @param[in] filtration Maximum threshold value. - * \warning The filtration must be valid. If the filtration has not been initialized yet, the method initializes it + * \post The filtration must be valid. If the filtration has not been initialized yet, the method initializes it * (i.e. order the simplices). If the complex has changed since the last time the filtration was initialized, please * call `initialize_filtration()` to recompute it. */ @@ -1182,7 +1195,7 @@ class Simplex_tree { if (filtration_vect_.empty()) { initialize_filtration(); } - + std::vector> simplex_list_to_removed; // Loop in reverse mode until threshold is reached // Do not erase while looping, because removing is shifting data in a flat_map @@ -1234,18 +1247,18 @@ class Simplex_tree { rec_prune_above_filtration(simplex.second.children(), filt); } }*/ - + /** \brief Remove a maximal simplex. * @param[in] sh Simplex handle on the maximal simplex to remove. * \pre Please check the simplex has no coface before removing it. - * \warning In debug mode, the exception std::invalid_argument is thrown if sh has children. - * \warning Be aware that removing is shifting data in a flat_map (initialize_filtration to be done). + * \exception std::invalid_argument In debug mode, if sh has children. + * \post Be aware that removing is shifting data in a flat_map (initialize_filtration to be done). */ void remove_maximal_simplex(Simplex_handle sh) { // Guarantee the simplex has no children GUDHI_CHECK(has_children(sh), std::invalid_argument("Simplex_tree::remove_maximal_simplex - argument has children")); - + // Simplex is a leaf, it means the child is the Siblings owning the leaf Siblings* child = sh->second.children(); @@ -1259,42 +1272,6 @@ class Simplex_tree { delete child; } } -/***************************************************************************************************************/ - public: - /** \brief Prints the simplex_tree hierarchically. - * Since it prints the vertices recursively, one can watch its tree shape. - */ - void debug_tree() { - std::cout << "{" << &root_ << "} -------------------------------------------------------------------" << std::endl; - for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { - std::cout << sh->first << " [" << sh->second.filtration() << "] "; - if (has_children(sh)) { - rec_debug_tree(sh->second.children()); - } else { - std::cout << " {- " << sh->second.children() << "} "; - } - std::cout << std::endl; - } - std::cout << "--------------------------------------------------------------------------------------" << std::endl; - } - - - /** \brief Recursively prints the simplex_tree, using depth first search. */ - private: - void rec_debug_tree(Siblings * sib) { - std::cout << " {" << sib << "} ("; - for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { - std::cout << " " << sh->first << " [" << sh->second.filtration() << "] "; - if (has_children(sh)) { - rec_debug_tree(sh->second.children()); - } else { - std::cout << " {- " << sh->second.children() << "} "; - } - } - std::cout << ")"; - } - -/*****************************************************************************************************************/ private: Vertex_handle null_vertex_; diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index e623cf7b..7bf5569e 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -98,7 +98,6 @@ class Delaunay_triangulation_off_visitor_reader { std::cout << std::endl; #endif // DEBUG_TRACES // Fill the point cloud - // VR: complex_->insert(Point(point.size(), point.begin(), point.end())); point_cloud.push_back(Point(point.size(), point.begin(), point.end())); } @@ -116,9 +115,7 @@ class Delaunay_triangulation_off_visitor_reader { /** \brief Returns the constructed Delaunay triangulation. * - * @return A pointer on the Delaunay triangulation. - * - * @warning The returned pointer can be nullptr. + * @return A pointer on the Delaunay triangulation. Default value is nullptr. */ Complex* get_complex() const { return complex_; @@ -157,8 +154,8 @@ class Delaunay_triangulation_off_reader { * that are in the OFF file. * * @param[in] name_file OFF file to read. - * - * @warning Check with is_valid() function to see if read operation was successful. + * + * \post Check with is_valid() function to see if read operation was successful. */ Delaunay_triangulation_off_reader(const std::string & name_file) : valid_(false) { @@ -191,9 +188,7 @@ class Delaunay_triangulation_off_reader { /** \brief Returns the constructed Delaunay triangulation. * - * @return A pointer on the Delaunay triangulation. - * - * @warning The returned pointer can be nullptr. + * @return A pointer on the Delaunay triangulation. Default value is nullptr. */ Complex* get_complex() const { if (valid_) @@ -242,12 +237,12 @@ class Delaunay_triangulation_off_writer { public: typedef typename Complex::Point Point; - /** \brief Writes the OFF file from the Delaunay triangulation + /** \brief Writes the OFF file from the Delaunay triangulation. * * @param[in] name_file OFF file to write. * @param[in] complex_ptr pointer on a Delaunay triangulation. - * - * @warning Check with is_valid() function to see if write operation was successful. + * + * \post Check with is_valid() function to see if write operation was successful. */ Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) : valid_(false) { -- cgit v1.2.3 From 071c0495ae1ed556f17120ca7c249106f5e34f9b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 22 Mar 2016 09:32:32 +0000 Subject: Delaunay triangulation is point dimension. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1066 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 672164328b3b1ac104811fb2fd79a3771c92d60e --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 2d2d77a5..0b6875af 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -166,8 +166,8 @@ class Alpha_complex : public Simplex_tree<> { // point_dimension function initialization Point_Dimension point_dimension = kernel_.point_dimension_d_object(); - // Delaunay triangulation is point dimension minus one. - triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); + // Delaunay triangulation is point dimension. + triangulation_ = new Delaunay_triangulation(point_dimension(*first)); size_type inserted = triangulation_->insert(first, last); if (inserted != (last -first)) { -- cgit v1.2.3 From ce097f4fd26faf1b52d7a50769f809feeab60c3d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 22 Mar 2016 12:55:19 +0000 Subject: Add a comment to say Alpha complex takes the ownership of the pointer on the Delaunay Triangulation. Add public typedef Delaunay_triangulation, Point_d and Geom_traits git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1067 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1137a9912ebac38a14d680921e62cd36e0068153 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 0b6875af..7c64b53e 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -34,6 +34,7 @@ #include // isnan, fmax #include +#include #include #include @@ -62,13 +63,24 @@ namespace alphacomplex { * * The complex is a template class requiring an Epick_d dD Geometry Kernel - * \cite cgal:s-gkd-15b from CGAL as template. + * \cite cgal:s-gkd-15b from CGAL as template, default value is CGAL::Epick_d + * < + * CGAL::Dynamic_dimension_tag > * * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. * */ -template +template> class Alpha_complex : public Simplex_tree<> { + public: + /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ + typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; + /** \brief A point in Euclidean space.*/ + typedef typename Kernel::Point_d Point_d; + /** \brief Geometric traits class that provides the geometric types and predicates needed by Delaunay + * triangulations.*/ + typedef Kernel Geom_traits; private: // From Simplex_tree // Type required to insert into a simplex_tree (with or without subfaces). @@ -77,15 +89,10 @@ class Alpha_complex : public Simplex_tree<> { // Simplex_result is the type returned from simplex_tree insert function. typedef typename std::pair Simplex_result; - // Delaunay_triangulation type required to create an alpha-complex. - typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; - typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; typedef typename Kernel::Point_dimension_d Point_Dimension; - typedef typename Kernel::Point_d Point_d; - // Type required to compute squared radius, or side of bounded sphere on a vector of points. typedef typename std::vector Vector_of_CGAL_points; @@ -135,6 +142,8 @@ class Alpha_complex : public Simplex_tree<> { * @param[in] triangulation_ptr Pointer on a * CGAL::Delaunay_triangulation \cite cgal:hdj-t-15b. + * Alpha_complex takes ownership of the Delaunay_triangulation object, which must have been allocated using operator + * new. * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. */ Alpha_complex(Delaunay_triangulation* triangulation_ptr, -- cgit v1.2.3 From 5276b0a9e344ed0bb4fdb8b079f2ce86649d12a4 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 22 Mar 2016 16:07:08 +0000 Subject: GUDHI_CHECK was not intuitive. Reverse GUDHI_CHECK calls. No exception when no point is given in contrction. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1070 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: bf6a08d48b5b29a5b24bf5107116e399dfc0a6bc --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 4 ---- src/Simplex_tree/include/gudhi/Simplex_tree.h | 4 ++-- src/common/include/gudhi/Debug_utils.h | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 7c64b53e..330b3b34 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -159,7 +159,6 @@ class Alpha_complex : public Simplex_tree<> { * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. - * \exception std::invalid_argument In debug mode, if an empty input point range is passed as argument. */ template Alpha_complex(const InputPointRange& points, @@ -168,9 +167,6 @@ class Alpha_complex : public Simplex_tree<> { auto first = std::begin(points); auto last = std::end(points); - GUDHI_CHECK((first == last), - std::invalid_argument("Alpha_complex::Alpha_complex(InputPointRange) - Empty input point range")); - if (first != last) { // point_dimension function initialization Point_Dimension point_dimension = kernel_.point_dimension_d_object(); diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 7b55df11..aa8f059e 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -454,7 +454,7 @@ class Simplex_tree { * \exception std::invalid_argument In debug mode, if sh is a null_simplex. */ void assign_filtration(Simplex_handle sh, Filtration_value fv) { - GUDHI_CHECK(sh == null_simplex(), + GUDHI_CHECK(sh != null_simplex(), std::invalid_argument("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex")); sh->second.assign_filtration(fv); } @@ -1256,7 +1256,7 @@ class Simplex_tree { */ void remove_maximal_simplex(Simplex_handle sh) { // Guarantee the simplex has no children - GUDHI_CHECK(has_children(sh), + GUDHI_CHECK(!has_children(sh), std::invalid_argument("Simplex_tree::remove_maximal_simplex - argument has children")); // Simplex is a leaf, it means the child is the Siblings owning the leaf diff --git a/src/common/include/gudhi/Debug_utils.h b/src/common/include/gudhi/Debug_utils.h index 48d61fef..7573a9db 100644 --- a/src/common/include/gudhi/Debug_utils.h +++ b/src/common/include/gudhi/Debug_utils.h @@ -29,12 +29,12 @@ #define GUDHI_DEBUG #endif -// GUDHI_CHECK throw an exception on condition in debug mode, but does nothing in release mode +// GUDHI_CHECK throw an exception if expression is false in debug mode, but does nothing in release mode // Could assert in release mode, but cmake sets NDEBUG (for "NO DEBUG") in this mode, means assert does nothing. #ifdef GUDHI_DEBUG - #define GUDHI_CHECK(cond, excpt) if (cond) throw excpt + #define GUDHI_CHECK(expression, excpt) if ((expression) == 0) throw excpt #else - #define GUDHI_CHECK(cond, excpt) (void) 0 + #define GUDHI_CHECK(expression, excpt) (void) 0 #endif #define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl -- cgit v1.2.3 From bbf22c32a893c9875f6ea0e217d0bf6cf77c3257 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 23 Mar 2016 08:09:39 +0000 Subject: prune_above_filtration returns filtration vector modification information instead of calling initialize_filtration() git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1071 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6fdc1797ac6e7b452abe150643f0ec9578c3bbab --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 10 ++- src/Simplex_tree/include/gudhi/Simplex_tree.h | 16 ++--- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 71 +++++++++++++++++----- 4 files changed, 77 insertions(+), 26 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 330b3b34..33830175 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -230,8 +230,6 @@ class Alpha_complex : public Simplex_tree<> { } set_dimension(triangulation_->maximal_dimension()); - // set_filtration to +inf for prune_above_filtration to be done (if necessary) - set_filtration(std::numeric_limits::infinity()); // -------------------------------------------------------------------------------------------- // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa @@ -323,7 +321,9 @@ class Alpha_complex : public Simplex_tree<> { initialize_filtration(); } // Remove all simplices that have a filtration value greater than max_alpha_square - prune_above_filtration(max_alpha_square); + if (prune_above_filtration(max_alpha_square)) { + initialize_filtration(); + } // -------------------------------------------------------------------------------------------- } diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 2912019d..315582d1 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -78,7 +78,8 @@ BOOST_AUTO_TEST_CASE(ALPHA_DOC_OFF_file_filtered) { std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << max_alpha_square_value << "==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); + // Use of the default dynamic kernel + Gudhi::alphacomplex::Alpha_complex<> alpha_complex_from_file(off_file_name, max_alpha_square_value); const int DIMENSION = 2; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -200,7 +201,12 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { BOOST_CHECK_THROW (alpha_complex_from_points.get_point(1234), std::out_of_range); // Test after prune_above_filtration - alpha_complex_from_points.prune_above_filtration(0.6); + bool modified = alpha_complex_from_points.prune_above_filtration(0.6); + if (modified) { + alpha_complex_from_points.initialize_filtration(); + } + BOOST_CHECK(modified); + // Another way to check num_simplices std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; num_simplices = 0; diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index aa8f059e..af298f33 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1186,11 +1186,14 @@ class Simplex_tree { public: /** \brief Prune above filtration value given as parameter. * @param[in] filtration Maximum threshold value. - * \post The filtration must be valid. If the filtration has not been initialized yet, the method initializes it - * (i.e. order the simplices). If the complex has changed since the last time the filtration was initialized, please - * call `initialize_filtration()` to recompute it. + * @return The filtration modification information. + * \pre The filtration must be valid. If the filtration has not been initialized yet, the method initializes it + * (i.e. order the simplices). + * \post Some simplex tree functions require the filtration to be valid. `prune_above_filtration()` + * function is not launching `initialize_filtration()` but returns the filtration modification information. If the + * complex has changed , please call `initialize_filtration()` to recompute it. */ - void prune_above_filtration(Filtration_value filtration) { + bool prune_above_filtration(Filtration_value filtration) { // Initialize filtration_vect_ if required if (filtration_vect_.empty()) { initialize_filtration(); @@ -1213,13 +1216,12 @@ class Simplex_tree { remove_maximal_simplex(sh); } // Re-initialize filtration_vect_ if dta were removed, because removing is shifting data in a flat_map - if (simplex_list_to_removed.size() > 0) - initialize_filtration(); + return (simplex_list_to_removed.size() > 0); } /* // Another alternative for prune_above_filtration - // Seg fault in this state + // initialize_filtration is not called. UT are not passed. void prune_above_filtration(Filtration_value filt) { if (!Options::store_filtration || filt >= filtration()) return; rec_prune_above_filtration(root(), filt); diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index b8c1cc35..b1bb23b1 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -1012,20 +1012,30 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { // o // 5 + bool simplex_is_changed = false; // Check the no action cases // greater than initial filtration value - st.prune_above_filtration(10.0); + simplex_is_changed = st.prune_above_filtration(10.0); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_complete); + BOOST_CHECK(!simplex_is_changed); // equal to initial filtration value - st.prune_above_filtration(6.0); + simplex_is_changed = st.prune_above_filtration(6.0); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_complete); + BOOST_CHECK(!simplex_is_changed); // lower than initial filtration value, but still greater than the maximum filtration value - st.prune_above_filtration(5.0); + simplex_is_changed = st.prune_above_filtration(5.0); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_complete); + BOOST_CHECK(!simplex_is_changed); // Display the Simplex_tree std::cout << "The complex contains " << st.num_simplices() << " simplices"; - std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << " - dimension " << st.dimension() << std::endl; std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; for (auto f_simplex : st.filtration_simplex_range()) { std::cout << " " << "[" << st.filtration(f_simplex) << "] "; @@ -1036,35 +1046,46 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { } // Check the pruned cases - // Set the st_pruned filtration for operator== - st.prune_above_filtration(2.5); + simplex_is_changed = st.prune_above_filtration(2.5); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_pruned); + BOOST_CHECK(simplex_is_changed); // Display the Simplex_tree std::cout << "The complex pruned at 2.5 contains " << st.num_simplices() << " simplices"; - std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << " - dimension " << st.dimension() << std::endl; - st.prune_above_filtration(2.0); + simplex_is_changed = st.prune_above_filtration(2.0); + if (simplex_is_changed) + st.initialize_filtration(); std::cout << "The complex pruned at 2.0 contains " << st.num_simplices() << " simplices"; - std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << " - dimension " << st.dimension() << std::endl; BOOST_CHECK(st == st_pruned); + BOOST_CHECK(!simplex_is_changed); typeST st_empty; // FIXME st_empty.set_dimension(3); - st.prune_above_filtration(0.0); + simplex_is_changed = st.prune_above_filtration(0.0); + if (simplex_is_changed) + st.initialize_filtration(); // Display the Simplex_tree std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices"; - std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << " - dimension " << st.dimension() << std::endl; BOOST_CHECK(st == st_empty); + BOOST_CHECK(simplex_is_changed); // Test case to the limit - st.prune_above_filtration(-1.0); + simplex_is_changed = st.prune_above_filtration(-1.0); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_empty); + BOOST_CHECK(!simplex_is_changed); } BOOST_AUTO_TEST_CASE(mini_prune_above_filtration) { @@ -1096,11 +1117,33 @@ BOOST_AUTO_TEST_CASE(mini_prune_above_filtration) { std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; BOOST_CHECK(st.num_simplices() == 27); + // Test case to the limit - With these options, there is no filtration, which means filtration is 0 + bool simplex_is_changed = st.prune_above_filtration(1.0); + if (simplex_is_changed) + st.initialize_filtration(); + // Display the Simplex_tree + std::cout << "The complex pruned at 1.0 contains " << st.num_simplices() << " simplices" << std::endl; + BOOST_CHECK(!simplex_is_changed); + BOOST_CHECK(st.num_simplices() == 27); + + simplex_is_changed = st.prune_above_filtration(0.0); + if (simplex_is_changed) + st.initialize_filtration(); + // Display the Simplex_tree + std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices" << std::endl; + BOOST_CHECK(!simplex_is_changed); + BOOST_CHECK(st.num_simplices() == 27); + // Test case to the limit - st.prune_above_filtration(-1.0); + simplex_is_changed = st.prune_above_filtration(-1.0); + if (simplex_is_changed) + st.initialize_filtration(); + // Display the Simplex_tree + std::cout << "The complex pruned at -1.0 contains " << st.num_simplices() << " simplices" << std::endl; + BOOST_CHECK(simplex_is_changed); + BOOST_CHECK(st.num_simplices() == 0); // Display the Simplex_tree std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; - BOOST_CHECK(st.num_simplices() == 0); } \ No newline at end of file -- cgit v1.2.3 From eefb9628f71cd74127cfc9ffa4f8db0803d82ad9 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 24 Mar 2016 12:40:15 +0000 Subject: prune_above_filtration version that is no more using filtration vector. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1073 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 95dca83fa459abd902624bf2a5f631925e4cf9b0 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 8 +++--- src/Simplex_tree/include/gudhi/Simplex_tree.h | 35 ++----------------------- 2 files changed, 6 insertions(+), 37 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 33830175..2b27a459 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -317,11 +317,11 @@ class Alpha_complex : public Simplex_tree<> { // -------------------------------------------------------------------------------------------- // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension - if (make_filtration_non_decreasing()) { - initialize_filtration(); - } + bool modified_filt = make_filtration_non_decreasing(); // Remove all simplices that have a filtration value greater than max_alpha_square - if (prune_above_filtration(max_alpha_square)) { + // Remark: prune_above_filtration does not require initialize_filtration to be done before. + modified_filt |= prune_above_filtration(max_alpha_square); + if (modified_filt) { initialize_filtration(); } // -------------------------------------------------------------------------------------------- diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 1bad8d7d..f5bc0a11 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1187,42 +1187,11 @@ class Simplex_tree { /** \brief Prune above filtration value given as parameter. * @param[in] filtration Maximum threshold value. * @return The filtration modification information. - * \pre The filtration must be valid. If the filtration has not been initialized yet, the method initializes it - * (i.e. order the simplices). * \post Some simplex tree functions require the filtration to be valid. `prune_above_filtration()` * function is not launching `initialize_filtration()` but returns the filtration modification information. If the * complex has changed , please call `initialize_filtration()` to recompute it. */ - bool prune_above_filtration(Filtration_value filtration) { - // Initialize filtration_vect_ if required - if (filtration_vect_.empty()) { - initialize_filtration(); - } - - std::vector> simplex_list_to_removed; - // Loop in reverse mode until threshold is reached - // Do not erase while looping, because removing is shifting data in a flat_map - for (auto f_simplex = filtration_vect_.rbegin(); - (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > filtration); - f_simplex++) { - std::vector simplex_to_remove; - for (auto vertex : simplex_vertex_range(*f_simplex)) - simplex_to_remove.insert(simplex_to_remove.begin(), vertex); - simplex_list_to_removed.push_back(simplex_to_remove); - } - for (auto simplex_to_remove : simplex_list_to_removed) { - Simplex_handle sh = find_simplex(simplex_to_remove); - if (sh != null_simplex()) - remove_maximal_simplex(sh); - } - // Re-initialize filtration_vect_ if dta were removed, because removing is shifting data in a flat_map - return (simplex_list_to_removed.size() > 0); - } - - - // Another alternative for prune_above_filtration - // UT are passed and performance are similar. - /*bool prune_above_filtration(Filtration_value filt) { + bool prune_above_filtration(Filtration_value filt) { return rec_prune_above_filtration(root(), filt); } @@ -1249,7 +1218,7 @@ class Simplex_tree { modified |= rec_prune_above_filtration(simplex.second.children(), filt); } return modified; - }*/ + } public: /** \brief Remove a maximal simplex. -- cgit v1.2.3 From fb22bc9ca84f5b3c55a598bf0c903a73c117e783 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 11:08:33 +0000 Subject: Replace Delaunay_triangulation_off_io.h and Delaunay_triangulation_off_rw.cpp with Points_off_io.h and CGAL_points_off_reader.cpp Adapt UT and examples for this Adapt Alpha complex for it Alpha complex is now inserting points in a faster way (after a spatial_sort). Remove Alpha complex construction from a pointer on Delaunay triangulation (no more needed). Adapt documentation to all these modifications Forbid copy/move constructor/assignment operator on Alpha complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1098 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 08a673b66451b5cb03fbdf482d696d93b35d220f --- src/Alpha_complex/doc/Intro_alpha_complex.h | 6 +- src/Alpha_complex/doc/alpha_complex_doc.ipe | 136 ++++-- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 25150 -> 25554 bytes src/Alpha_complex/doc/alpha_complex_doc_420.ipe | 514 +++++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc_420.png | Bin 0 -> 80794 bytes src/Alpha_complex/doc/alpha_complex_doc_421.ipe | 514 --------------------- src/Alpha_complex/doc/alpha_complex_doc_421.png | Bin 100798 -> 0 bytes .../doc/alpha_complex_representation.ipe | 16 +- .../doc/alpha_complex_representation.png | Bin 14628 -> 14606 bytes .../example/Alpha_complex_from_off.cpp | 8 +- .../example/Alpha_complex_from_points.cpp | 15 +- .../example/alphaoffreader_for_doc_32.txt | 26 +- .../example/alphaoffreader_for_doc_60.txt | 36 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 109 +++-- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 2 - .../example/alpha_complex_persistence.cpp | 3 +- src/common/example/CGAL_points_off_reader.cpp | 43 ++ src/common/example/CMakeLists.txt | 12 +- .../example/Delaunay_triangulation_off_rw.cpp | 54 --- src/common/example/cgaloffreader_result.txt | 7 + .../example/dtoffrw_alphashapedoc_result.off | 15 - .../example/dtoffrw_alphashapedoc_result.txt | 2 - .../include/gudhi/Delaunay_triangulation_off_io.h | 348 -------------- src/common/include/gudhi/Points_off_io.h | 178 +++++++ src/common/test/CMakeLists.txt | 14 +- src/common/test/dtoffrw_alphashapedoc_result.off | 22 +- src/common/test/dtoffrw_unit_test.cpp | 90 ---- src/common/test/points_off_reader_unit_test.cpp | 78 ++++ 28 files changed, 1044 insertions(+), 1204 deletions(-) create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_420.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_420.png delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_421.ipe delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_421.png create mode 100644 src/common/example/CGAL_points_off_reader.cpp delete mode 100644 src/common/example/Delaunay_triangulation_off_rw.cpp create mode 100644 src/common/example/cgaloffreader_result.txt delete mode 100644 src/common/example/dtoffrw_alphashapedoc_result.off delete mode 100644 src/common/example/dtoffrw_alphashapedoc_result.txt delete mode 100644 src/common/include/gudhi/Delaunay_triangulation_off_io.h create mode 100644 src/common/include/gudhi/Points_off_io.h delete mode 100644 src/common/test/dtoffrw_unit_test.cpp create mode 100644 src/common/test/points_off_reader_unit_test.cpp (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 0dea2b16..9d0dcefa 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -112,14 +112,14 @@ namespace alphacomplex { * * \subsubsection dimension2 Dimension 2 * - * From the example above, it means the algorithm looks into each triangle ([4,2,1], [2,4,6], [4,5,6], ...), + * From the example above, it means the algorithm looks into each triangle ([0,1,2], [0,2,4], [1,2,3], ...), * computes the filtration value of the triangle, and then propagates the filtration value as described * here : - * \image html "alpha_complex_doc_421.png" "Filtration value propagation example" + * \image html "alpha_complex_doc_420.png" "Filtration value propagation example" * * \subsubsection dimension1 Dimension 1 * - * Then, the algorithm looks into each edge ([1,2], [4,2], [4,1], ...), + * Then, the algorithm looks into each edge ([0,1], [0,2], [1,2], ...), * computes the filtration value of the edge (in this case, propagation will have no effect). * * \subsubsection dimension0 Dimension 0 diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe index 99bd05af..baf0d26a 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -1,7 +1,7 @@ - + @@ -253,13 +253,13 @@ h 320 580 l Delaunay triangulation -2 -6 -4 -5 -1 -3 -0 +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -314,7 +314,7 @@ h -3 +2 300 688 m 300 676 l @@ -322,15 +322,14 @@ h 312 688 l h - +2 + 300 688 m 300 676 l 312 676 l 312 688 l h -4 -3 300 688 m 300 676 l @@ -338,6 +337,8 @@ h 312 688 l h +4 +1 300 688 m 300 676 l @@ -345,39 +346,15 @@ h 312 688 l h -4 -1 - -300 688 m -300 676 l -312 676 l -312 688 l -h - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -5 - + 300 688 m 300 676 l 312 676 l 312 688 l h -5 +4 3 - -300 688 m -300 676 l -312 676 l -312 688 l -h - 300 688 m 300 676 l @@ -385,7 +362,6 @@ h 312 688 l h -4 2 300 688 m @@ -401,7 +377,7 @@ h 312 688 l h -4 +3 6 300 688 m @@ -418,14 +394,14 @@ h 312 688 l h - + 300 688 m 300 676 l 312 676 l 312 688 l h -6 +6 6 300 688 m @@ -442,22 +418,22 @@ h 312 688 l h - + 300 688 m 300 676 l 312 676 l 312 688 l h -6 - +6 + 300 688 m 300 676 l 312 676 l 312 688 l h -6 +6 292 716 m 292 728 l @@ -514,11 +490,11 @@ h 4 5 6 - + 436 708 m 436 716 l - + 364 708 m 364 716 l @@ -535,11 +511,11 @@ h 308 716 l 308 716 l - + 264 688 m 268 696 l - + 292 688 m 292 696 l @@ -555,5 +531,65 @@ h 448 612 m 448 620 l +3 + +300 688 m +300 676 l +312 676 l +312 688 l +h + + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +364 688 m +364 696 l + + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +436 708 m +436 716 l + + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +436 708 m +436 716 l + diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index cfe3ede6..0b6201da 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc.png and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_420.ipe b/src/Alpha_complex/doc/alpha_complex_doc_420.ipe new file mode 100644 index 00000000..5d1d29d4 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc_420.ipe @@ -0,0 +1,514 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +Cell [4,2,0] +0 +1 +2 +3 +4 +5 +6 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + + +77.2727 0 0 77.2727 243.636 591.818 e + + +243.428 591.569 m +186.061 643.28 l + +$\alpha_{420}$ + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[2,0] is Gabriel $\rightarrow$ $\alpha_{20}$ is not$\\$ +modified (NaN) + +0 +2 +3 +4 +5 +6 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{20}$ + +290 530 m +320 580 l + + +29.1548 0 0 29.1548 305 555 e + + +304.883 555.015 m +334.509 555.015 l + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[0,4] is not Gabriel $\rightarrow$ $\alpha_{40} = \alpha_{420}$ +0 +3 +5 +6 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{40}$ + +290 530 m +280 660 l + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +0 +1 +2 +3 +5 +6 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{42}$ +4 + +406.093 497.775 m +446.094 418.092 l + + +44.5799 0 0 44.5799 425.934 457.774 e + + +425.854 457.774 m +470.795 457.774 l + +[2,4] is Gabriel $\rightarrow$ $\alpha_{42}$ is not modified (NaN) + + +205.028 596.091 m +110.946 544.02 l + + +280.768 588.99 m +280.768 547.57 l + + +341.123 594.316 m +413.904 554.079 l + +For all faces of [4,2,0] +N.B. : is Gabriel on a single point has no sense. +Dimension =2 - $\sigma$ = [4,2,0] + +247.333 430.892 m +311.764 430.892 l + + + + + + + + + + + + + + +1 + + + + + +4 + + +1 + + +2 + +65.192 0 0 65.192 285 595 e + + + + + + + + + + + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_420.png b/src/Alpha_complex/doc/alpha_complex_doc_420.png new file mode 100644 index 00000000..ef7187f7 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc_420.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_421.ipe b/src/Alpha_complex/doc/alpha_complex_doc_421.ipe deleted file mode 100644 index 727816c5..00000000 --- a/src/Alpha_complex/doc/alpha_complex_doc_421.ipe +++ /dev/null @@ -1,514 +0,0 @@ - - - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - -0.6 0 0 0.6 0 0 e - - - - - -0.5 0 0 0.5 0 0 e - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h - - - - - --0.5 -0.5 m -0.5 -0.5 l -0.5 0.5 l --0.5 0.5 l -h - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - - - --0.43 -0.57 m -0.57 0.43 l -0.43 0.57 l --0.57 -0.43 l -h - - --0.43 0.57 m -0.57 -0.43 l -0.43 -0.57 l --0.57 0.43 l -h - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - --1 0.333 m -0 0 l --1 -0.333 l - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -Cell [4,2,1] -2 -6 -4 -5 -1 -3 -0 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - - -77.2727 0 0 77.2727 243.636 591.818 e - - -243.428 591.569 m -186.061 643.28 l - -$\alpha_{421}$ - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -[4,2] is Gabriel $\rightarrow$ $\alpha_{42}$ is not$\\$ -modified (NaN) - -2 -4 -5 -1 -3 -0 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{42}$ - -290 530 m -320 580 l - - -29.1548 0 0 29.1548 305 555 e - - -304.883 555.015 m -334.509 555.015 l - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -[2,1] is not Gabriel $\rightarrow$ $\alpha_{21} = \alpha_{421}$ -2 -5 -3 -0 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{12}$ - -290 530 m -280 660 l - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -2 -6 -4 -5 -3 -0 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{41}$ -1 - -406.093 497.775 m -446.094 418.092 l - - -44.5799 0 0 44.5799 425.934 457.774 e - - -425.854 457.774 m -470.795 457.774 l - -[4,1] is Gabriel $\rightarrow$ $\alpha_{41}$ is not modified (NaN) - - -205.028 596.091 m -110.946 544.02 l - - -280.768 588.99 m -280.768 547.57 l - - -341.123 594.316 m -413.904 554.079 l - -For all faces of [4,2,1] -N.B. : is Gabriel on a single point has no sense. -Dimension =2 - $\sigma$ = [4,2,1] - -247.333 430.892 m -311.764 430.892 l - - - - - - - - - - - - - - -6 - - - - - -1 - - -6 - - -4 - -65.192 0 0 65.192 285 595 e - - - - - - - - - - - - - diff --git a/src/Alpha_complex/doc/alpha_complex_doc_421.png b/src/Alpha_complex/doc/alpha_complex_doc_421.png deleted file mode 100644 index 1cce4402..00000000 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_421.png and /dev/null differ diff --git a/src/Alpha_complex/doc/alpha_complex_representation.ipe b/src/Alpha_complex/doc/alpha_complex_representation.ipe index fead1661..e8096b93 100644 --- a/src/Alpha_complex/doc/alpha_complex_representation.ipe +++ b/src/Alpha_complex/doc/alpha_complex_representation.ipe @@ -1,7 +1,7 @@ - + @@ -251,13 +251,13 @@ h h Alpha complex -2 -6 -4 -5 -1 -3 -0 +0 +1 +2 +3 +4 +5 +6 58.1341 0 0 58.1341 218.925 692.601 e diff --git a/src/Alpha_complex/doc/alpha_complex_representation.png b/src/Alpha_complex/doc/alpha_complex_representation.png index 9833bff3..7b81cd69 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_representation.png and b/src/Alpha_complex/doc/alpha_complex_representation.png differ diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 18a1a20d..963ef5ca 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -4,17 +4,15 @@ #include #include -void usage(char * const progName) { +void usage(int nbArgs, char * const progName) { + std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n"; std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value [ouput_file.txt]\n"; std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0\n"; exit(-1); // ----- >> } int main(int argc, char **argv) { - if ((argc != 3) && (argc != 4)) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; - usage(argv[0]); - } + if ((argc != 3) && (argc != 4)) usage(argc, (argv[0] - 1)); std::string off_file_name(argv[1]); double alpha_square_max_value = atof(argv[2]); diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 815e40d7..cd17af1e 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -4,13 +4,26 @@ #include #include #include +#include // for numeric limits typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel; typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; +void usage(int nbArgs, char * const progName) { + std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n"; + std::cerr << "Usage: " << progName << " [alpha_square_max_value]\n"; + std::cerr << " i.e.: " << progName << " 60.0\n"; + exit(-1); // ----- >> +} + int main(int argc, char **argv) { - double alpha_square_max_value = 60.0; + if ((argc != 1) && (argc != 2)) usage(argc, (argv[0] - 1)); + + // Delaunay complex if alpha_square_max_value is not given by the user. + double alpha_square_max_value = std::numeric_limits::infinity(); + if (argc == 2) + alpha_square_max_value = atof(argv[1]); // ---------------------------------------------------------------------------- // Init of a list of points diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt index 5869fdff..13183e86 100644 --- a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt @@ -7,16 +7,16 @@ Iterator on alpha complex simplices in the filtration order, with [filtration va ( 4 ) -> [0] ( 5 ) -> [0] ( 6 ) -> [0] - ( 5 4 ) -> [6.25] - ( 3 1 ) -> [7.25] - ( 4 2 ) -> [8.5] - ( 6 2 ) -> [9.25] - ( 6 5 ) -> [10] - ( 6 4 ) -> [11.25] - ( 6 5 4 ) -> [12.5] - ( 6 4 2 ) -> [12.9959] - ( 3 0 ) -> [13.25] - ( 4 1 ) -> [20] - ( 1 0 ) -> [22.7367] - ( 3 1 0 ) -> [22.7367] - ( 5 0 ) -> [30.25] + ( 3 2 ) -> [6.25] + ( 5 4 ) -> [7.25] + ( 2 0 ) -> [8.5] + ( 1 0 ) -> [9.25] + ( 3 1 ) -> [10] + ( 2 1 ) -> [11.25] + ( 3 2 1 ) -> [12.5] + ( 2 1 0 ) -> [12.9959] + ( 6 5 ) -> [13.25] + ( 4 2 ) -> [20] + ( 6 4 ) -> [22.7367] + ( 6 5 4 ) -> [22.7367] + ( 6 3 ) -> [30.25] diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt index 1d17a58a..71f29a00 100644 --- a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt @@ -7,21 +7,21 @@ Iterator on alpha complex simplices in the filtration order, with [filtration va ( 4 ) -> [0] ( 5 ) -> [0] ( 6 ) -> [0] - ( 5 4 ) -> [6.25] - ( 3 1 ) -> [7.25] - ( 4 2 ) -> [8.5] - ( 6 2 ) -> [9.25] - ( 6 5 ) -> [10] - ( 6 4 ) -> [11.25] - ( 6 5 4 ) -> [12.5] - ( 6 4 2 ) -> [12.9959] - ( 3 0 ) -> [13.25] - ( 4 1 ) -> [20] - ( 1 0 ) -> [22.7367] - ( 3 1 0 ) -> [22.7367] - ( 5 0 ) -> [30.25] - ( 4 0 ) -> [36.5] - ( 5 4 0 ) -> [36.5] - ( 4 1 0 ) -> [37.2449] - ( 2 1 ) -> [59.7107] - ( 4 2 1 ) -> [59.7107] + ( 3 2 ) -> [6.25] + ( 5 4 ) -> [7.25] + ( 2 0 ) -> [8.5] + ( 1 0 ) -> [9.25] + ( 3 1 ) -> [10] + ( 2 1 ) -> [11.25] + ( 3 2 1 ) -> [12.5] + ( 2 1 0 ) -> [12.9959] + ( 6 5 ) -> [13.25] + ( 4 2 ) -> [20] + ( 6 4 ) -> [22.7367] + ( 6 5 4 ) -> [22.7367] + ( 6 3 ) -> [30.25] + ( 6 2 ) -> [36.5] + ( 6 3 2 ) -> [36.5] + ( 6 4 2 ) -> [37.2449] + ( 4 0 ) -> [59.7107] + ( 4 2 0 ) -> [59.7107] diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 2b27a459..21eb5f48 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -27,14 +27,16 @@ #include #include #include -// to construct a Delaunay_triangulation from a OFF file -#include +// to construct Alpha_complex from a OFF file of points +#include #include #include // isnan, fmax +//#include #include #include +#include #include #include @@ -43,6 +45,7 @@ #include #include // std::pair #include +#include // for std::iota namespace Gudhi { @@ -57,7 +60,7 @@ namespace alphacomplex { * \details * The data structure can be constructed from a CGAL Delaunay triangulation (for more informations on CGAL Delaunay * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) or from - * an OFF file (cf. Delaunay_triangulation_off_reader). + * an OFF file (cf. Points_off_reader). * * Please refer to \ref alpha_complex for examples. * @@ -74,13 +77,19 @@ namespace alphacomplex { template> class Alpha_complex : public Simplex_tree<> { public: + // Add an int in TDS to save point index in the structure + typedef CGAL::Triangulation_data_structure, + CGAL::Triangulation_full_cell > TDS; /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ - typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; + typedef CGAL::Delaunay_triangulation Delaunay_triangulation; + /** \brief A point in Euclidean space.*/ typedef typename Kernel::Point_d Point_d; /** \brief Geometric traits class that provides the geometric types and predicates needed by Delaunay * triangulations.*/ typedef Kernel Geom_traits; + private: // From Simplex_tree // Type required to insert into a simplex_tree (with or without subfaces). @@ -104,7 +113,7 @@ class Alpha_complex : public Simplex_tree<> { // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; - typedef typename std::vector< CGAL_vertex_iterator > Vector_vertex_iterator; + typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Vector_vertex_iterator; private: /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ @@ -128,28 +137,13 @@ class Alpha_complex : public Simplex_tree<> { Alpha_complex(const std::string& off_file_name, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(nullptr) { - Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); + Gudhi::Points_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { std::cerr << "Alpha_complex - Unable to read file " << off_file_name << "\n"; exit(-1); // ----- >> } - triangulation_ = off_reader.get_complex(); - init(max_alpha_square); - } - /** \brief Alpha_complex constructor from a Delaunay triangulation. - * - * @param[in] triangulation_ptr Pointer on a - * CGAL::Delaunay_triangulation \cite cgal:hdj-t-15b. - * Alpha_complex takes ownership of the Delaunay_triangulation object, which must have been allocated using operator - * new. - * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. - */ - Alpha_complex(Delaunay_triangulation* triangulation_ptr, - Filtration_value max_alpha_square = std::numeric_limits::infinity()) - : triangulation_(triangulation_ptr) { - init(max_alpha_square); + init_from_range(off_reader.get_point_cloud(), max_alpha_square); } /** \brief Alpha_complex constructor from a list of points. @@ -164,23 +158,7 @@ class Alpha_complex : public Simplex_tree<> { Alpha_complex(const InputPointRange& points, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(nullptr) { - auto first = std::begin(points); - auto last = std::end(points); - - if (first != last) { - // point_dimension function initialization - Point_Dimension point_dimension = kernel_.point_dimension_d_object(); - - // Delaunay triangulation is point dimension. - triangulation_ = new Delaunay_triangulation(point_dimension(*first)); - - size_type inserted = triangulation_->insert(first, last); - if (inserted != (last -first)) { - std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << "\n"; - exit(-1); // ----- >> - } - init(max_alpha_square); - } + init_from_range(points, max_alpha_square); } /** \brief Alpha_complex destructor. @@ -191,6 +169,12 @@ class Alpha_complex : public Simplex_tree<> { delete triangulation_; } + // Forbid copy/move constructor/assignment operator + Alpha_complex(const Alpha_complex& other) = delete; + Alpha_complex& operator= (const Alpha_complex& other) = delete; + Alpha_complex (Alpha_complex&& other) = delete; + Alpha_complex& operator= (Alpha_complex&& other) = delete; + /** \brief get_point returns the point corresponding to the vertex given as parameter. * * @param[in] vertex Vertex handle of the point to retrieve. @@ -202,6 +186,44 @@ class Alpha_complex : public Simplex_tree<> { } private: + template + void init_from_range(const InputPointRange& points, Filtration_value max_alpha_square) { + auto first = std::begin(points); + auto last = std::end(points); + if (first != last) { + // point_dimension function initialization + Point_Dimension point_dimension = kernel_.point_dimension_d_object(); + + // Delaunay triangulation is point dimension. + triangulation_ = new Delaunay_triangulation(point_dimension(*first)); + + std::vector points(first, last); + + // Creates a vector {0, 1, ..., N-1} + std::vector indices(boost::counting_iterator(0), + boost::counting_iterator(points.size())); + + // Sort indices considering CGAL spatial sort + typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; + spatial_sort(indices.begin(),indices.end(),Search_traits_d(&(points[0]))); + + typename Delaunay_triangulation::Full_cell_handle hint; + for (auto index : indices) { + typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(points[index], hint); + // Save index value as data to retrieve it after insertion + pos->data() = index; + hint = pos->full_cell(); + } + + if (triangulation_->number_of_vertices() != (last -first)) { + std::cerr << "Alpha_complex - insertion failed " << triangulation_->number_of_vertices() << " != " << + (last -first) << "\n"; + exit(-1); // ----- >> + } + init(max_alpha_square); + } + } + /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * * @param[in] max_alpha_square maximum for alpha square value. @@ -233,18 +255,15 @@ class Alpha_complex : public Simplex_tree<> { // -------------------------------------------------------------------------------------------- // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa - // Start to insert at handle = 0 - default integer value - Vertex_handle vertex_handle = Vertex_handle(); // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { if (!triangulation_->is_infinite(*vit)) { #ifdef DEBUG_TRACES - std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; + std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES - vertex_iterator_to_handle_.emplace(vit, vertex_handle); - vertex_handle_to_iterator_.push_back(vit); - vertex_handle++; + vertex_iterator_to_handle_.emplace(vit, vit->data()); + vertex_handle_to_iterator_.emplace(vit->data(), vit); } } // -------------------------------------------------------------------------------------------- diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 315582d1..80b39924 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -32,8 +32,6 @@ #include #include -// to construct a Delaunay_triangulation from a OFF file -#include #include // Use dynamic_dimension_tag for the user to be able to set dimension diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp index d2f9a4a2..8f9f077c 100644 --- a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -1,8 +1,7 @@ #include #include -// to construct a Delaunay_triangulation from a OFF file -#include + #include #include diff --git a/src/common/example/CGAL_points_off_reader.cpp b/src/common/example/CGAL_points_off_reader.cpp new file mode 100644 index 00000000..076afd5b --- /dev/null +++ b/src/common/example/CGAL_points_off_reader.cpp @@ -0,0 +1,43 @@ +#include + +// For CGAL points type in dimension d +// cf. http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Point__d.html +#include + +#include +#include + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef typename Kernel::Point_d Point_d; + +void usage(int argc, char * const progName) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + std::cerr << "Usage: " << progName << " inputFile.off" << std::endl; + exit(-1); +} + +int main(int argc, char **argv) { + if (argc != 2) usage(argc, (argv[0] - 1)); + + std::string offInputFile(argv[1]); + // Read the OFF file (input file name given as parameter) and triangulate points + Gudhi::Points_off_reader off_reader(offInputFile); + // Check the read operation was correct + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << offInputFile << std::endl; + exit(-1); + } + + // Retrieve the triangulation + std::vector point_cloud = off_reader.get_point_cloud(); + + int n = 0; + for (auto point : point_cloud) { + std::cout << "Point[" << n << "] = "; + for (int i = 0; i < point.dimension(); i++) + std::cout << point[i] << " "; + std::cout << "\n"; + ++n; + } + return 0; +} diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index 91e78ea2..2914756e 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -9,15 +9,9 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) - target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(dtoffrw ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) - - if (DIFF_PATH) - # Do not forget to copy test results files in current binary dir - file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - add_test(dtoffrw_result_off_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) - endif() + add_executable ( cgaloffreader CGAL_points_off_reader.cpp ) + target_link_libraries(cgaloffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(cgaloffreader ${CMAKE_CURRENT_BINARY_DIR}/cgaloffreader ${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp deleted file mode 100644 index 4c7a9aaf..00000000 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// to construct a Delaunay_triangulation from a OFF file -#include - -#include -#include - -#include -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instantiation of the -// TriangulationDataStructure template parameter - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " inputFile.off outputFile.off" << std::endl; - exit(-1); -} - -int main(int argc, char **argv) { - if (argc != 3) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - std::string offInputFile(argv[1]); - // Read the OFF file (input file name given as parameter) and triangulates points - Gudhi::Delaunay_triangulation_off_reader off_reader(offInputFile); - // Check the read operation was correct - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << offInputFile << std::endl; - exit(-1); - } - - // Retrieve the triangulation - T* triangulation = off_reader.get_complex(); - // Operations on triangulation - std::cout << "Number of vertices= " << triangulation->number_of_vertices() << std::endl; - std::cout << "Number of finite full cells= " << triangulation->number_of_finite_full_cells() << std::endl; - - std::string outFileName(argv[2]); - std::string offOutputFile(outFileName); - // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces - Gudhi::Delaunay_triangulation_off_writer off_writer(offOutputFile, triangulation); - - // Check the write operation was correct - if (!off_writer.is_valid()) { - std::cerr << "Unable to write file " << offOutputFile << std::endl; - exit(-1); - } - - return 0; -} diff --git a/src/common/example/cgaloffreader_result.txt b/src/common/example/cgaloffreader_result.txt new file mode 100644 index 00000000..1deb8dbd --- /dev/null +++ b/src/common/example/cgaloffreader_result.txt @@ -0,0 +1,7 @@ +Point[0] = 1 1 +Point[1] = 7 0 +Point[2] = 4 6 +Point[3] = 9 6 +Point[4] = 0 14 +Point[5] = 2 19 +Point[6] = 9 17 diff --git a/src/common/example/dtoffrw_alphashapedoc_result.off b/src/common/example/dtoffrw_alphashapedoc_result.off deleted file mode 100644 index d1839a43..00000000 --- a/src/common/example/dtoffrw_alphashapedoc_result.off +++ /dev/null @@ -1,15 +0,0 @@ -nOFF -2 7 6 0 -9 17 -0 14 -1 1 -2 19 -4 6 -9 6 -7 0 -3 5 0 4 -3 0 1 4 -3 3 1 0 -3 4 1 2 -3 5 4 6 -3 6 4 2 diff --git a/src/common/example/dtoffrw_alphashapedoc_result.txt b/src/common/example/dtoffrw_alphashapedoc_result.txt deleted file mode 100644 index 8e659740..00000000 --- a/src/common/example/dtoffrw_alphashapedoc_result.txt +++ /dev/null @@ -1,2 +0,0 @@ -Number of vertices= 7 -Number of finite full cells= 6 diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h deleted file mode 100644 index 50be9a59..00000000 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ /dev/null @@ -1,348 +0,0 @@ -/* 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 Saclay (France) - * - * 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 . - */ -#ifndef DELAUNAY_TRIANGULATION_OFF_IO_H_ -#define DELAUNAY_TRIANGULATION_OFF_IO_H_ - -#include -#include -#include -#include - -#include - -#include - -#include "gudhi/Off_reader.h" - -namespace Gudhi { - -/** - * \class Delaunay_triangulation_off_visitor_reader Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h - * \brief OFF file visitor implementation according to Off_reader in order to construct a CGAL Delaunay triangulation. - * - * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page - * http://doc.cgal.org/latest/Triangulation/ - */ -template -class Delaunay_triangulation_off_visitor_reader { - private: - Complex* complex_; - typedef typename Complex::Point_d Point_d; - typedef typename Complex::size_type size_type; - std::vector point_cloud; - - public: - // TODO(VR) : Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. - - /** \brief Delaunay_triangulation_off_visitor_reader constructor - * - * @param[in] complex_ptr_ pointer on a Delaunay triangulation. - */ - Delaunay_triangulation_off_visitor_reader(Complex* complex_ptr_) - : complex_(nullptr) { } - - /** \brief Off_reader visitor init implementation. - * - * The init parameters are set from OFF file header. - * Dimension value is required in order to construct Delaunay triangulation. - * - * @param[in] dim space dimension of vertices. - * @param[in] num_vertices number of vertices in the OFF file (not used). - * @param[in] num_faces number of faces in the OFF file (not used). - * @param[in] num_edges number of edges in the OFF file (not used). - */ - void init(int dim, int num_vertices, int num_faces, int num_edges) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << - num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; -#endif // DEBUG_TRACES - if (num_faces > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << - "file for Delaunay triangulation - faces are computed.\n"; - } - if (num_edges > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << - "file for Delaunay triangulation - edges are computed.\n"; - } - // Complex construction with dimension from file - complex_ = new Complex(dim); - } - - /** \brief Off_reader visitor point implementation. - * - * The point function is called on each vertex line from OFF file. - * This function inserts the vertex in the Delaunay triangulation. - * - * @param[in] point vector of vertex coordinates. - */ - void point(const std::vector& point) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::point "; - for (auto coordinate : point) { - std::cout << coordinate << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES - // Fill the point cloud - point_cloud.push_back(Point_d(point.size(), point.begin(), point.end())); - } - - // Off_reader visitor maximal_face implementation - not used - void maximal_face(const std::vector& face) { - // For Delaunay Triangulation, only points are read - } - - // Off_reader visitor done implementation - void done() { - // It is advised to insert all the points at a time in a Delaunay Triangulation because points are sorted at the - // beginning of the insertion - size_type inserted = complex_->insert(point_cloud.begin(), point_cloud.end()); - if (inserted != (point_cloud.end() -point_cloud.begin())) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::done - insertion failed " << inserted << " != " << - (point_cloud.end() -point_cloud.begin()) << "\n"; - } - } - - /** \brief Returns the constructed Delaunay triangulation. - * - * @return A pointer on the Delaunay triangulation. Default value is nullptr. - */ - Complex* get_complex() const { - return complex_; - } - - private: - template - size_type insert_with_index(const PointRangeIterator& first, const PointRangeIterator& last) { - size_type vertices_before_insertion = complex_->number_of_vertices(); - std::vector points(first, last); - - std::vector indices; - indices.reserve(points.size()); - - // Creates a vector {0, 1, ..., N-1} - std::copy(boost::counting_iterator(0), boost::counting_iterator(points.size()), - std::back_inserter(indices)); - - // Sort indices considering CGAL spatial sort - typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; - spatial_sort(indices.begin(),indices.end(),Search_traits_d(&(points[0]))); - - typename Delaunay_triangulation::Full_cell_handle hint; - for (typename std::vector::const_iterator it = indices.begin(), end = indices.end(); - it != end; ++it) { - typename Delaunay_triangulation::Vertex_handle pos = complex_->insert(points[*it], hint); - // Save index value as data to retrieve it after insertion - pos->data() = *it; - hint = pos->full_cell(); - } - - return (complex_->number_of_vertices() - vertices_before_insertion); - } - -}; - -/** - * \class Delaunay_triangulation_off_reader Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h - * \brief OFF file reader implementation in order to construct a Delaunay triangulation. - * - * This class is using the Delaunay_triangulation_off_visitor_reader to visit the OFF file according to Off_reader. - * - * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page - * http://doc.cgal.org/latest/Triangulation/ - * - * \section Example - * - * This example loads points from an OFF file and builds the Delaunay triangulation. - * Then, it is asked to display the number of vertices and finites full cells from the Delaunay triangulation. - * - * \include Delaunay_triangulation_off_rw.cpp - * - * When launching: - * - * \code $> ./dtoffrw ../../data/points/alphacomplexdoc.off triangulated.off - * \endcode - * - * the program output is: - * - * \include dtoffrw_alphashapedoc_result.txt - */ -template -class Delaunay_triangulation_off_reader { - public: - /** \brief Reads the OFF file and constructs the Delaunay triangulation from the points - * that are in the OFF file. - * - * @param[in] name_file OFF file to read. - * - * \post Check with is_valid() function to see if read operation was successful. - */ - Delaunay_triangulation_off_reader(const std::string & name_file) - : valid_(false) { - std::ifstream stream(name_file); - if (stream.is_open()) { - Delaunay_triangulation_off_visitor_reader off_visitor(complex_); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - if (valid_) { - complex_ = off_visitor.get_complex(); - if (complex_ == nullptr) { - std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader off_visitor returns " << - "an empty pointer\n"; - valid_ = false; - } - } - } else { - std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << - name_file << "\n"; - } - } - - /** \brief Returns if the OFF file read operation was successful or not. - * - * @return OFF file read status. - */ - bool is_valid() const { - return valid_; - } - - /** \brief Returns the constructed Delaunay triangulation. - * - * @return A pointer on the Delaunay triangulation. Default value is nullptr. - */ - Complex* get_complex() const { - if (valid_) - return complex_; - return nullptr; - } - - private: - /** \brief OFF file read status.*/ - bool valid_; - /** \brief A pointer on the Delaunay triangulation.*/ - Complex* complex_; -}; - -/** - * \class Delaunay_triangulation_off_writer Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h - * \brief OFF file writer from a Delaunay triangulation. - * - * This class constructs the OFF file header according to http://www.geomview.org/docs/html/OFF.html - * - * The header is followed by the list of points coordinates (Delaunay triangulation vertices) - * - * And finally is followed by the list of faces (Delaunay triangulation finite full cells) - * - * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page - * http://doc.cgal.org/latest/Triangulation/ - * - * \section Example - * - * This example loads points from an OFF file and builds the Delaunay triangulation. - * Then, the Delaunay triangulation is saved in a new file including the triangulation as a list of faces. - * - * \include Delaunay_triangulation_off_rw.cpp - * - * When launching: - * - * \code $> ./dtoffrw ../../data/points/alphashapedoc.off triangulated.off - * \endcode - * - * The result will be an OFF file of dimension 2 with the 7 points from alphashapedoc.off followed by the 6 - * triangulations of dimension 3 (the first value on each faces): - * \include dtoffrw_alphashapedoc_result.off - */ -template -class Delaunay_triangulation_off_writer { - public: - typedef typename Complex::Point Point; - - /** \brief Writes the OFF file from the Delaunay triangulation. - * - * @param[in] name_file OFF file to write. - * @param[in] complex_ptr pointer on a Delaunay triangulation. - * - * \post Check with is_valid() function to see if write operation was successful. - */ - Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) - : valid_(false) { - std::ofstream stream(name_file); - if (stream.is_open()) { - if (complex_ptr->current_dimension() == 3) { - // OFF header - stream << "OFF" << std::endl; - // no endl on next line - don't know why... - stream << complex_ptr->number_of_vertices() << " " << complex_ptr->number_of_finite_full_cells() << " 0"; - } else { - // nOFF header - stream << "nOFF" << std::endl; - // no endl on next line - don't know why... - stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << - complex_ptr->number_of_finite_full_cells() << " 0"; - } - - // bimap to retrieve vertex handles from points and vice versa - std::map< Point, int > points_to_vh; - // Start to insert at default handle value - int vertex_handle = int(); - - // Points list - for (auto vit = complex_ptr->vertices_begin(); vit != complex_ptr->vertices_end(); ++vit) { - for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { - stream << *Coord << " "; - } - stream << std::endl; - points_to_vh[vit->point()] = vertex_handle; - vertex_handle++; - } - - for (auto cit = complex_ptr->finite_full_cells_begin(); cit != complex_ptr->finite_full_cells_end(); ++cit) { - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - stream << points_to_vh[(*vit)->point()] - 1 << " "; - } - stream << std::endl; - } - stream.close(); - valid_ = true; - } else { - std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << - name_file << "\n"; - } - } - - /** \brief Returns if the OFF write operation was successful or not. - * - * @return OFF file write status. - */ - bool is_valid() const { - return valid_; - } - - private: - /* \brief OFF file write status. */ - bool valid_; -}; - -} // namespace Gudhi - -#endif // DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h new file mode 100644 index 00000000..d9f9a74b --- /dev/null +++ b/src/common/include/gudhi/Points_off_io.h @@ -0,0 +1,178 @@ +/* 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 Saclay (France) + * + * 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 . + */ +#ifndef POINTS_OFF_IO_H_ +#define POINTS_OFF_IO_H_ + +#include +#include +#include +#include + +#include + +namespace Gudhi { + +/** + * \brief OFF file visitor implementation according to Off_reader in order to read points from an OFF file. + */ +template +class Points_off_visitor_reader { + private: + std::vector point_cloud; + + public: + /** \brief Off_reader visitor init implementation. + * + * The init parameters are set from OFF file header. + * Dimension value is required in order to construct Alpha complex. + * + * @param[in] dim space dimension of vertices. + * @param[in] num_vertices number of vertices in the OFF file (not used). + * @param[in] num_faces number of faces in the OFF file (not used). + * @param[in] num_edges number of edges in the OFF file (not used). + */ + void init(int dim, int num_vertices, int num_faces, int num_edges) { +#ifdef DEBUG_TRACES + std::cout << "Points_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; +#endif // DEBUG_TRACES + if (num_faces > 0) { + std::cerr << "Points_off_visitor_reader::init faces are not taken into account from OFF file for Points.\n"; + } + if (num_edges > 0) { + std::cerr << "Points_off_visitor_reader::init edges are not taken into account from OFF file for Points.\n"; + } + } + + /** \brief Off_reader visitor point implementation. + * + * The point function is called on each vertex line from OFF file. + * This function inserts the vertex in the Alpha complex. + * + * @param[in] point vector of vertex coordinates. + */ + void point(const std::vector& point) { +#ifdef DEBUG_TRACES + std::cout << "Points_off_visitor_reader::point "; + for (auto coordinate : point) { + std::cout << coordinate << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + // Fill the point cloud + point_cloud.push_back(Point_d(point.size(), point.begin(), point.end())); + } + + // Off_reader visitor maximal_face implementation - Only points are read + void maximal_face(const std::vector& face) { } + + // Off_reader visitor done implementation - Only points are read + void done() { } + + /** \brief Point cloud getter. + * + * @return point_cloud. + */ + const std::vector& get_point_cloud() { + return point_cloud; + } + +}; + +/** + * \brief OFF file reader implementation in order to read points from an OFF file. + * + * This class is using the Points_off_visitor_reader to visit the OFF file according to Off_reader. + * + * Point_d must have a constructor with the following form: + * + * \code template Point_d::Point_d(int d, InputIterator first, InputIterator last) \endcode + * + * where d is the point dimension. + * + * \section Example + * + * This example loads points from an OFF file and builds a vector of CGAL points in dimension d. + * Then, it is asked to display the points. + * + * \include CGAL_points_off_reader.cpp + * + * When launching: + * + * \code $> ./cgaloffreader ../../data/points/alphacomplexdoc.off + * \endcode + * + * the program output is: + * + * \include cgaloffreader_result.txt + */ +template +class Points_off_reader { + public: + /** \brief Reads the OFF file and constructs the Alpha complex from the points + * that are in the OFF file. + * + * @param[in] name_file OFF file to read. + * + * \post Check with is_valid() function to see if read operation was successful. + */ + Points_off_reader(const std::string& name_file) + : valid_(false) { + std::ifstream stream(name_file); + if (stream.is_open()) { + Off_reader off_reader(stream); + Points_off_visitor_reader off_visitor; + valid_ = off_reader.read(off_visitor); + if (valid_) { + point_cloud = off_visitor.get_point_cloud(); + } + } else { + std::cerr << "Points_off_reader::Points_off_reader could not open file " << name_file << "\n"; + } + } + + /** \brief Returns if the OFF file read operation was successful or not. + * + * @return OFF file read status. + */ + bool is_valid() const { + return valid_; + } + + /** \brief Point cloud getter. + * + * @return point_cloud. + */ + const std::vector& get_point_cloud() { + return point_cloud; + } + + private: + /** \brief point_cloud.*/ + std::vector point_cloud; + /** \brief OFF file read status.*/ + bool valid_; +}; + +} // namespace Gudhi + +#endif // POINTS_OFF_IO_H_ diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 12eecda8..6205f0e4 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -18,22 +18,16 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - add_executable ( dtoffrw_UT dtoffrw_unit_test.cpp ) - target_link_libraries(dtoffrw_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_executable ( poffreader_UT points_off_reader_unit_test.cpp ) + target_link_libraries(poffreader_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) # Unitary tests - add_test(dtoffrw_UT ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_UT + add_test(poffreader_UT ${CMAKE_CURRENT_BINARY_DIR}/poffreader_UT # XML format for Jenkins xUnit plugin - --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/dtoffrw_UT.xml --log_level=test_suite --report_level=no) - - if (DIFF_PATH) - # Do not forget to copy test result files in current binary dir - file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - add_test(dtoffrw_diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) - endif() + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/poffreader_UT.xml --log_level=test_suite --report_level=no) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off index d1839a43..1deb8dbd 100644 --- a/src/common/test/dtoffrw_alphashapedoc_result.off +++ b/src/common/test/dtoffrw_alphashapedoc_result.off @@ -1,15 +1,7 @@ -nOFF -2 7 6 0 -9 17 -0 14 -1 1 -2 19 -4 6 -9 6 -7 0 -3 5 0 4 -3 0 1 4 -3 3 1 0 -3 4 1 2 -3 5 4 6 -3 6 4 2 +Point[0] = 1 1 +Point[1] = 7 0 +Point[2] = 4 6 +Point[3] = 9 6 +Point[4] = 0 14 +Point[5] = 2 19 +Point[6] = 9 17 diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp deleted file mode 100644 index f682df1a..00000000 --- a/src/common/test/dtoffrw_unit_test.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* 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 Saclay (France) - * - * 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 . - */ - -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" - -#include -#include - -#include - -#include -#include - -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "delaunay_triangulation_off_read_write" -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation_doc_test ) -{ - // Read the OFF file (input file name given as parameter) and triangulates points - Gudhi::Delaunay_triangulation_off_reader off_reader("alphacomplexdoc.off"); - // Check the read operation was correct - BOOST_CHECK(off_reader.is_valid()); - - // Retrieve the triangulation - T* triangulation = off_reader.get_complex(); - BOOST_CHECK(triangulation != nullptr); - // Operations on triangulation - BOOST_CHECK(triangulation->number_of_vertices() == 7); - BOOST_CHECK(triangulation->number_of_finite_full_cells() == 6); - - // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces - Gudhi::Delaunay_triangulation_off_writer off_writer("UT.off", triangulation); - - // Check the write operation was correct - BOOST_CHECK(off_writer.is_valid()); - - delete triangulation; -} - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) -{ - Gudhi::Delaunay_triangulation_off_reader off_reader("some_impossible_weird_file_name.off"); - // Check the read operation was correct - BOOST_CHECK(!off_reader.is_valid()); - T* triangulation = off_reader.get_complex(); - BOOST_CHECK(triangulation == nullptr); -} - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_write_test ) -{ - // Read the OFF file (input file name given as parameter) and triangulates points - Gudhi::Delaunay_triangulation_off_reader off_reader("alphacomplexdoc.off"); - - // Retrieve the triangulation - T* triangulation = off_reader.get_complex(); - - // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces - Gudhi::Delaunay_triangulation_off_writer off_writer("/some_impossible_weird_directory_name/another_weird_directory_name/some_impossible_weird_file_name.off", triangulation); - - // Check the write operation was correct - BOOST_CHECK(!off_writer.is_valid()); - - delete triangulation; -} - diff --git a/src/common/test/points_off_reader_unit_test.cpp b/src/common/test/points_off_reader_unit_test.cpp new file mode 100644 index 00000000..73e19cbc --- /dev/null +++ b/src/common/test/points_off_reader_unit_test.cpp @@ -0,0 +1,78 @@ +/* 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 Saclay (France) + * + * 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 . + */ + +#include + +// For CGAL points type in dimension d +// cf. http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Point__d.html +#include + +#include +#include +#include + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "points_off_read_write" +#include + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef typename Kernel::Point_d Point_d; + +BOOST_AUTO_TEST_CASE( points_doc_test ) +{ + // Read the OFF file (input file name given as parameter) and triangulates points + Gudhi::Points_off_reader off_reader("alphacomplexdoc.off"); + // Check the read operation was correct + BOOST_CHECK(off_reader.is_valid()); + + // Retrieve the triangulation + std::vector point_cloud = off_reader.get_point_cloud(); + BOOST_CHECK(point_cloud.size() == 7); + + std::vector expected_points; + std::vector point = {1.0, 1.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {7.0, 0.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {4.0, 6.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {9.0, 6.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {0.0, 14.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {2.0, 19.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {9.0, 17.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + + BOOST_CHECK(point_cloud == expected_points); +} + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) +{ + Gudhi::Points_off_reader off_reader("some_impossible_weird_file_name.off"); + // Check the read operation was correct + BOOST_CHECK(!off_reader.is_valid()); + + std::vector point_cloud = off_reader.get_point_cloud(); + BOOST_CHECK(point_cloud.size() == 0); +} -- cgit v1.2.3 From 8e76285d6d2ea35a9709117896390b718f1f15f1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 21:11:38 +0000 Subject: Marc review fix cpplint/cppcheck fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1102 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f47277da05debb56dd9a4a96bf89ec7b3ffa2e27 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 22 ++++++++-------------- .../concept/FilteredComplex.h | 2 +- src/common/example/CGAL_points_off_reader.cpp | 1 + src/common/include/gudhi/Off_reader.h | 1 + src/common/include/gudhi/Points_off_io.h | 7 +++---- 5 files changed, 14 insertions(+), 19 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 21eb5f48..753fa58a 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -33,7 +33,6 @@ #include #include // isnan, fmax -//#include #include #include #include @@ -79,7 +78,7 @@ class Alpha_complex : public Simplex_tree<> { public: // Add an int in TDS to save point index in the structure typedef CGAL::Triangulation_data_structure, + CGAL::Triangulation_vertex, CGAL::Triangulation_full_cell > TDS; /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ typedef CGAL::Delaunay_triangulation Delaunay_triangulation; @@ -111,13 +110,10 @@ class Alpha_complex : public Simplex_tree<> { // size_type type from CGAL. typedef typename Delaunay_triangulation::size_type size_type; - // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. - typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; + // Map type to switch from simplex tree vertex handle to CGAL vertex iterator. typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Vector_vertex_iterator; private: - /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ - Map_vertex_iterator_to_handle vertex_iterator_to_handle_; /** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator. * Vertex handles are inserted sequentially, starting at 0.*/ Vector_vertex_iterator vertex_handle_to_iterator_; @@ -198,15 +194,15 @@ class Alpha_complex : public Simplex_tree<> { triangulation_ = new Delaunay_triangulation(point_dimension(*first)); std::vector points(first, last); - + // Creates a vector {0, 1, ..., N-1} std::vector indices(boost::counting_iterator(0), boost::counting_iterator(points.size())); - + // Sort indices considering CGAL spatial sort typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; - spatial_sort(indices.begin(),indices.end(),Search_traits_d(&(points[0]))); - + spatial_sort(indices.begin(), indices.end(), Search_traits_d(&(points[0]))); + typename Delaunay_triangulation::Full_cell_handle hint; for (auto index : indices) { typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(points[index], hint); @@ -261,8 +257,6 @@ class Alpha_complex : public Simplex_tree<> { #ifdef DEBUG_TRACES std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES - - vertex_iterator_to_handle_.emplace(vit, vit->data()); vertex_handle_to_iterator_.emplace(vit->data(), vit); } } @@ -278,10 +272,10 @@ class Alpha_complex : public Simplex_tree<> { for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { if (*vit != nullptr) { #ifdef DEBUG_TRACES - std::cout << " " << vertex_iterator_to_handle_[*vit]; + std::cout << " " << (*vit)->data(); #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(vertex_iterator_to_handle_[*vit]); + vertexVector.push_back((*vit)->data()); } } #ifdef DEBUG_TRACES diff --git a/src/Persistent_cohomology/concept/FilteredComplex.h b/src/Persistent_cohomology/concept/FilteredComplex.h index e124d524..949aafc2 100644 --- a/src/Persistent_cohomology/concept/FilteredComplex.h +++ b/src/Persistent_cohomology/concept/FilteredComplex.h @@ -138,6 +138,6 @@ Filtration_simplex_range filtration_simplex_range(); * @todo use an enum? Just a bool? */ //int is_before_in_filtration(Simplex_handle s, Simplex_handle t); -/*************************************************/ +/*************************************************/ }; diff --git a/src/common/example/CGAL_points_off_reader.cpp b/src/common/example/CGAL_points_off_reader.cpp index 076afd5b..45e9f1e6 100644 --- a/src/common/example/CGAL_points_off_reader.cpp +++ b/src/common/example/CGAL_points_off_reader.cpp @@ -6,6 +6,7 @@ #include #include +#include typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; typedef typename Kernel::Point_d Point_d; diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index 2420ae72..4fcd2af2 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -31,6 +31,7 @@ #include #include #include +#include namespace Gudhi { diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h index d9f9a74b..79287e3c 100644 --- a/src/common/include/gudhi/Points_off_io.h +++ b/src/common/include/gudhi/Points_off_io.h @@ -22,13 +22,13 @@ #ifndef POINTS_OFF_IO_H_ #define POINTS_OFF_IO_H_ +#include + #include #include #include #include -#include - namespace Gudhi { /** @@ -87,7 +87,7 @@ class Points_off_visitor_reader { // Off_reader visitor done implementation - Only points are read void done() { } - + /** \brief Point cloud getter. * * @return point_cloud. @@ -95,7 +95,6 @@ class Points_off_visitor_reader { const std::vector& get_point_cloud() { return point_cloud; } - }; /** -- cgit v1.2.3 From dffe72221d325a446151012121a6ba069319596e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 7 Apr 2016 14:21:31 +0000 Subject: Remove insertion check for duplicate points case. Cpplint fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1103 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7ee7cf0ca7085966039d048199c35b6adf945aa2 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 753fa58a..ca2b68ca 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -126,6 +126,8 @@ class Alpha_complex : public Simplex_tree<> { /** \brief Alpha_complex constructor from an OFF file name. * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize * the Alpha_complex. + * + * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. * * @param[in] off_file_name OFF file [path and] name. * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. @@ -144,11 +146,15 @@ class Alpha_complex : public Simplex_tree<> { /** \brief Alpha_complex constructor from a list of points. * + * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. + * * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. + * + * @post Compare num_simplices with InputPointRange points number (not the same in case of duplicate points). */ template Alpha_complex(const InputPointRange& points, @@ -210,12 +216,6 @@ class Alpha_complex : public Simplex_tree<> { pos->data() = index; hint = pos->full_cell(); } - - if (triangulation_->number_of_vertices() != (last -first)) { - std::cerr << "Alpha_complex - insertion failed " << triangulation_->number_of_vertices() << " != " << - (last -first) << "\n"; - exit(-1); // ----- >> - } init(max_alpha_square); } } @@ -282,8 +282,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << std::endl; #endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, - std::numeric_limits::quiet_NaN()); + insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); } // -------------------------------------------------------------------------------------------- @@ -368,7 +367,9 @@ class Alpha_complex : public Simplex_tree<> { if (decr_dim > 1) { // insert the Tau points in a vector for is_gabriel function Vector_of_CGAL_points pointVector; +#ifdef DEBUG_TRACES Vertex_handle vertexForGabriel = Vertex_handle(); +#endif // DEBUG_TRACES for (auto vertex : simplex_vertex_range(f_boundary)) { pointVector.push_back(get_point(vertex)); } @@ -377,8 +378,10 @@ class Alpha_complex : public Simplex_tree<> { for (auto vertex : simplex_vertex_range(f_simplex)) { point_for_gabriel = get_point(vertex); if (std::find(pointVector.begin(), pointVector.end(), point_for_gabriel) == pointVector.end()) { +#ifdef DEBUG_TRACES // vertex is not found in Tau vertexForGabriel = vertex; +#endif // DEBUG_TRACES // No need to continue loop break; } -- cgit v1.2.3 From 351059be74b4f613d798ca4364a0e37202c3f378 Mon Sep 17 00:00:00 2001 From: glisse Date: Sat, 16 Apr 2016 07:24:53 +0000 Subject: Minor tweaks to alpha-complex * use the dimension of the kernel for the TDS * recycle a vector git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1134 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 590f625287629dd041afd5ce479c99b48a476b64 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index ca2b68ca..a1900cb9 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -77,7 +77,7 @@ template> class Alpha_complex : public Simplex_tree<> { public: // Add an int in TDS to save point index in the structure - typedef CGAL::Triangulation_data_structure, CGAL::Triangulation_full_cell > TDS; /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ @@ -287,13 +287,15 @@ class Alpha_complex : public Simplex_tree<> { // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- + // Will be re-used many times + Vector_of_CGAL_points pointVector; // ### For i : d -> 0 for (int decr_dim = dimension(); decr_dim >= 0; decr_dim--) { // ### Foreach Sigma of dim i for (auto f_simplex : skeleton_simplex_range(decr_dim)) { int f_simplex_dim = dimension(f_simplex); if (decr_dim == f_simplex_dim) { - Vector_of_CGAL_points pointVector; + pointVector.clear(); #ifdef DEBUG_TRACES std::cout << "Sigma of dim " << decr_dim << " is"; #endif // DEBUG_TRACES -- cgit v1.2.3 From 4308b8bc38b55053ddad94f0b9cf20095d53b81c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 9 Sep 2016 16:14:20 +0000 Subject: isnan must be preceeded by std:: git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1486 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 94adb015da0957f3b4ce3f5742f9cb0cf57b6284 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 096d2d2e..2c95ceb4 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -309,7 +309,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << std::endl; #endif // DEBUG_TRACES // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (isnan(filtration(f_simplex))) { + if (std::isnan(filtration(f_simplex))) { Filtration_value alpha_complex_filtration = 0.0; // No need to compute squared_radius on a single point - alpha is 0.0 if (f_simplex_dim > 0) { @@ -352,10 +352,10 @@ class Alpha_complex : public Simplex_tree<> { std::cout << vertex << " "; } std::cout << "is a face of Sigma\n"; - std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl; + std::cout << " | isnan(filtration(Tau)=" << std::isnan(filtration(f_boundary)) << std::endl; #endif // DEBUG_TRACES // ### If filt(Tau) is not NaN - if (!isnan(filtration(f_boundary))) { + if (!std::isnan(filtration(f_boundary))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); assign_filtration(f_boundary, alpha_complex_filtration); -- cgit v1.2.3 From 3d5bf7ed64b155894787cb356aead439977643e4 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 22 Sep 2016 14:38:46 +0000 Subject: New template function create_complex for Alpha_complex to create the simplicial complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1540 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 24e53dc58d158166b976dd09760ad0e2acaf8e36 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 36 ++- src/Alpha_complex/doc/alpha_complex_doc.ipe | 315 +-------------------- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 25554 -> 18720 bytes .../example/Alpha_complex_from_off.cpp | 40 +-- .../example/Alpha_complex_from_points.cpp | 38 +-- src/Alpha_complex/include/gudhi/Alpha_complex.h | 139 ++++----- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 116 ++++---- .../example/alpha_complex_persistence.cpp | 63 +++-- .../example/custom_persistence_sort.cpp | 89 +++--- 9 files changed, 293 insertions(+), 543 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index f3126169..4ca3271b 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -4,7 +4,7 @@ * * Author(s): Vincent Rouvreau * - * Copyright (C) 2015 INRIA Saclay (France) + * 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 @@ -39,7 +39,8 @@ namespace alpha_complex { * Alpha_complex is a simplicial complex * constructed from the finite cells of a Delaunay Triangulation. * - * The filtration value of each simplex is computed as the square of the circumradius of the simplex if the circumsphere is empty (the simplex is then said to be Gabriel), and as the minimum of the filtration + * The filtration value of each simplex is computed as the square of the circumradius of the simplex if the + * circumsphere is empty (the simplex is then said to be Gabriel), and as the minimum of the filtration * values of the codimension 1 cofaces that make it not Gabriel otherwise. * * All simplices that have a filtration value strictly greater than a given alpha squared value are not inserted into @@ -47,23 +48,24 @@ namespace alpha_complex { * * \image html "alpha_complex_representation.png" "Alpha-complex representation" * - * Alpha_complex is constructing a `Simplex_tree` using Delaunay Triangulation * \cite cgal:hdj-t-15b from CGAL (the Computational Geometry - * Algorithms Library \cite cgal:eb-15b). + * Algorithms Library \cite cgal:eb-15b) and is able to create a `Simplicial_complex_for_alpha`. * * The complex is a template class requiring an Epick_d dD Geometry Kernel * \cite cgal:s-gkd-15b from CGAL as template parameter. * - * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. + * \remark When the simplicial complex is constructed with an infinite value of alpha, the complex is a Delaunay + * complex. * * \section pointsexample Example from points * - * This example builds the Delaunay triangulation from the given points in a 2D static kernel, and initializes the - * alpha complex with it. + * This example builds the Delaunay triangulation from the given points in a 2D static kernel, and creates a + * `Simplex_tree` with it. * - * Then, it is asked to display information about the alpha complex. + * Then, it is asked to display information about the simplicial complex. * * \include Alpha_complex/Alpha_complex_from_points.cpp * @@ -76,13 +78,15 @@ namespace alpha_complex { * * \include Alpha_complex/alphaoffreader_for_doc_60.txt * - * \section algorithm Algorithm + * \section createcomplexalgorithm Create complex algorithm * * \subsection datastructure Data structure * - * In order to build the alpha complex, first, a Simplex tree is built from the cells of a Delaunay Triangulation. - * (The filtration value is set to NaN, which stands for unknown value): - * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" + * In order to create the simplicial complex, first, it is built from the cells of the Delaunay Triangulation. + * The filtration values are set to NaN, which stands for unknown value. + * + * In example, : + * \image html "alpha_complex_doc.png" "Simplicial complex structure construction example" * * \subsection filtrationcomputation Filtration value computation algorithm * @@ -129,12 +133,14 @@ namespace alpha_complex { * * \subsubsection nondecreasing Non decreasing filtration values * - * As the squared radii computed by CGAL are an approximation, it might happen that these alpha squared values do not quite define a proper filtration (i.e. non-decreasing with respect to inclusion). - * We fix that up by calling `Simplex_tree::make_filtration_non_decreasing()`. + * As the squared radii computed by CGAL are an approximation, it might happen that these alpha squared values do not + * quite define a proper filtration (i.e. non-decreasing with respect to inclusion). + * We fix that up by calling `Simplicial_complex_for_alpha::make_filtration_non_decreasing()`. * * \subsubsection pruneabove Prune above given filtration value * - * The simplex tree is pruned from the given maximum alpha squared value (cf. `Simplex_tree::prune_above_filtration()`). + * The simplex tree is pruned from the given maximum alpha squared value (cf. + * `Simplicial_complex_for_alpha::prune_above_filtration()`). * In the following example, the value is given by the user as argument of the program. * * diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe index baf0d26a..71e5ce6c 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -1,7 +1,7 @@ - + @@ -278,35 +278,7 @@ h 320 580 l 280 660 l - -4 0 0 4 320 704 e - - -322.919 706.788 m -317.189 701.058 l -317.189 701.203 l - - -317.551 706.934 m -322.629 701.058 l - - -240 620 m -220 600 l - - -240 620 m -220 640 l - -Simplex tree structure - -280 630 m -170 630 l - - -280 610 m -170 610 l - +Simplicial complex data structure : @@ -314,282 +286,11 @@ h -2 - -300 688 m -300 676 l -312 676 l -312 688 l -h - -2 - -300 688 m -300 676 l -312 676 l -312 688 l -h - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -4 -1 - -300 688 m -300 676 l -312 676 l -312 688 l -h - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -4 -3 - -300 688 m -300 676 l -312 676 l -312 688 l -h - -2 - -300 688 m -300 676 l -312 676 l -312 688 l -h - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -3 -6 - -300 688 m -300 676 l -312 676 l -312 688 l -h - -4 - -300 688 m -300 676 l -312 676 l -312 688 l -h - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -6 -6 - -300 688 m -300 676 l -312 676 l -312 688 l -h - -5 - -300 688 m -300 676 l -312 676 l -312 688 l -h - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -6 - -300 688 m -300 676 l -312 676 l -312 688 l -h - -6 - -292 716 m -292 728 l -316 728 l -316 716 l -h - - -316 716 m -316 728 l -340 728 l -340 716 l -h - - -340 716 m -340 728 l -364 728 l -364 716 l -h - - -364 716 m -364 728 l -388 728 l -388 716 l -h - - -388 716 m -388 728 l -412 728 l -412 716 l -h - - -412 716 m -412 728 l -436 728 l -436 716 l -h - - -436 716 m -436 728 l -460 728 l -460 716 l -h - -0 -1 -2 -3 -4 -5 -6 - -436 708 m -436 716 l - - -364 708 m -364 716 l - - -364 688 m -364 696 l - - -320 688 m -320 696 l - - -296 708 m -308 716 l -308 716 l - - -264 688 m -268 696 l - - -292 688 m -292 696 l - - -388 736 m -388 728 l - - -372 612 m -376 620 l - - -448 612 m -448 620 l - -3 - -300 688 m -300 676 l -312 676 l -312 688 l -h - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -6 - -364 688 m -364 696 l - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -6 - -300 688 m -300 676 l -312 676 l -312 688 l -h - -6 - -436 708 m -436 716 l - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -6 - -300 688 m -300 676 l -312 676 l -312 688 l -h - -6 - -436 708 m -436 716 l - +insert simplex and subfaces [0,1,2] +insert simplex and subfaces [1,2,3] +insert simplex and subfaces [0,2,4] +insert simplex and subfaces [2,3,6] +insert simplex and subfaces [2,4,6] +insert simplex and subfaces [4,5,6] diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index 0b6201da..170bae80 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc.png and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 7836d59a..31f8e10c 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,4 +1,7 @@ #include +// to construct a simplex_tree from alpha complex +#include + #include #include @@ -21,7 +24,7 @@ int main(int argc, char **argv) { // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name); std::streambuf* streambufffer; std::ofstream ouput_file_stream; @@ -33,23 +36,26 @@ int main(int argc, char **argv) { streambufffer = std::cout.rdbuf(); } - std::ostream output_stream(streambufffer); - - // ---------------------------------------------------------------------------- - // Display information about the alpha complex - // ---------------------------------------------------------------------------- - output_stream << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << - " - " << alpha_complex_from_file.num_simplices() << " simplices - " << - alpha_complex_from_file.num_vertices() << " vertices." << std::endl; - - output_stream << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; - for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - output_stream << " ( "; - for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { - output_stream << vertex << " "; + Gudhi::Simplex_tree<> simplex; + if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) { + std::ostream output_stream(streambufffer); + + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + output_stream << "Alpha complex is of dimension " << simplex.dimension() << + " - " << simplex.num_simplices() << " simplices - " << + simplex.num_vertices() << " vertices." << std::endl; + + output_stream << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : simplex.filtration_simplex_range()) { + output_stream << " ( "; + for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { + output_stream << vertex << " "; + } + output_stream << ") -> " << "[" << simplex.filtration(f_simplex) << "] "; + output_stream << std::endl; } - output_stream << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; - output_stream << std::endl; } ouput_file_stream.close(); return 0; diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 49f77276..fa3c1efc 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -1,5 +1,8 @@ -#include #include +// to construct a simplex_tree from alpha complex +#include + +#include #include #include @@ -40,23 +43,26 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points, alpha_square_max_value); + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); - // ---------------------------------------------------------------------------- - // Display information about the alpha complex - // ---------------------------------------------------------------------------- - std::cout << "Alpha complex is of dimension " << alpha_complex_from_points.dimension() << - " - " << alpha_complex_from_points.num_simplices() << " simplices - " << - alpha_complex_from_points.num_vertices() << " vertices." << std::endl; - - std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; - for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { - std::cout << " ( "; - for (auto vertex : alpha_complex_from_points.simplex_vertex_range(f_simplex)) { - std::cout << vertex << " "; + Gudhi::Simplex_tree<> simplex; + if (alpha_complex_from_points.create_complex(simplex, alpha_square_max_value)) { + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Alpha complex is of dimension " << simplex.dimension() << + " - " << simplex.num_simplices() << " simplices - " << + simplex.num_vertices() << " vertices." << std::endl; + + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : simplex.filtration_simplex_range()) { + std::cout << " ( "; + for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << simplex.filtration(f_simplex) << "] "; + std::cout << std::endl; } - std::cout << ") -> " << "[" << alpha_complex_from_points.filtration(f_simplex) << "] "; - std::cout << std::endl; } return 0; } diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 2c95ceb4..66a55ac7 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -4,7 +4,7 @@ * * Author(s): Vincent Rouvreau * - * Copyright (C) 2015 INRIA Saclay (France) + * 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 @@ -23,9 +23,6 @@ #ifndef ALPHA_COMPLEX_H_ #define ALPHA_COMPLEX_H_ -// to construct a simplex_tree from Delaunay_triangulation -#include -#include #include // to construct Alpha_complex from a OFF file of points #include @@ -74,7 +71,7 @@ namespace alpha_complex { * */ template> -class Alpha_complex : public Simplex_tree<> { +class Alpha_complex { public: // Add an int in TDS to save point index in the structure typedef CGAL::Triangulation_data_structure { typedef Kernel Geom_traits; private: - // From Simplex_tree - // Type required to insert into a simplex_tree (with or without subfaces). - typedef std::vector Vector_vertex; - - // Simplex_result is the type returned from simplex_tree insert function. - typedef typename std::pair Simplex_result; - typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; typedef typename Kernel::Point_dimension_d Point_Dimension; @@ -111,7 +101,7 @@ class Alpha_complex : public Simplex_tree<> { typedef typename Delaunay_triangulation::size_type size_type; // Map type to switch from simplex tree vertex handle to CGAL vertex iterator. - typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Vector_vertex_iterator; + typedef typename std::map< std::size_t, CGAL_vertex_iterator > Vector_vertex_iterator; private: /** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator. @@ -130,10 +120,8 @@ class Alpha_complex : public Simplex_tree<> { * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. * * @param[in] off_file_name OFF file [path and] name. - * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. */ - Alpha_complex(const std::string& off_file_name, - Filtration_value max_alpha_square = std::numeric_limits::infinity()) + Alpha_complex(const std::string& off_file_name) : triangulation_(nullptr) { Gudhi::Points_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { @@ -141,7 +129,7 @@ class Alpha_complex : public Simplex_tree<> { exit(-1); // ----- >> } - init_from_range(off_reader.get_point_cloud(), max_alpha_square); + init_from_range(off_reader.get_point_cloud()); } /** \brief Alpha_complex constructor from a list of points. @@ -149,7 +137,6 @@ class Alpha_complex : public Simplex_tree<> { * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. * * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d - * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. @@ -157,10 +144,9 @@ class Alpha_complex : public Simplex_tree<> { * @post Compare num_simplices with InputPointRange points number (not the same in case of duplicate points). */ template - Alpha_complex(const InputPointRange& points, - Filtration_value max_alpha_square = std::numeric_limits::infinity()) + Alpha_complex(const InputPointRange& points) : triangulation_(nullptr) { - init_from_range(points, max_alpha_square); + init_from_range(points); } /** \brief Alpha_complex destructor. @@ -183,13 +169,13 @@ class Alpha_complex : public Simplex_tree<> { * @return The point found. * @exception std::out_of_range In case vertex is not found (cf. std::vector::at). */ - Point_d get_point(Vertex_handle vertex) const { + Point_d get_point(std::size_t vertex) const { return vertex_handle_to_iterator_.at(vertex)->point(); } private: template - void init_from_range(const InputPointRange& points, Filtration_value max_alpha_square) { + void init_from_range(const InputPointRange& points) { auto first = std::begin(points); auto last = std::end(points); if (first != last) { @@ -216,38 +202,54 @@ class Alpha_complex : public Simplex_tree<> { pos->data() = index; hint = pos->full_cell(); } - init(max_alpha_square); } } - /** \brief Initialize the Alpha_complex from the Delaunay triangulation. + public: + template + bool create_complex(Simplicial_complex& complex) { + typedef typename Simplicial_complex::Filtration_value Filtration_value; + return create_complex(complex, std::numeric_limits::infinity()); + } + + /** \brief Initialize the simplicial complex from the Delaunay triangulation. * - * @param[in] max_alpha_square maximum for alpha square value. + * \tparam Simplicial_complex must meet Simplicial_complex_for_alpha concept. + * + * @param[in] complex Simplicial_complex to be created. + * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. + * + * @return true if creation succeeds, false otherwise. * * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more * than 0. * * Initialization can be launched once. */ - void init(Filtration_value max_alpha_square) { + template + bool create_complex(Simplicial_complex& complex, Filtration_value max_alpha_square) { + // From Simplicial_complex type required to insert into a simplicial complex (with or without subfaces). + typedef typename Simplicial_complex::Vertex_handle Vertex_handle; + typedef std::vector Vector_vertex; + if (triangulation_ == nullptr) { - std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation\n"; - return; // ----- >> + std::cerr << "Alpha_complex cannot create_complex from a NULL triangulation\n"; + return false; // ----- >> } if (triangulation_->number_of_vertices() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices\n"; - return; // ----- >> + std::cerr << "Alpha_complex cannot create_complex from a triangulation without vertices\n"; + return false; // ----- >> } if (triangulation_->maximal_dimension() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation\n"; - return; // ----- >> + std::cerr << "Alpha_complex cannot create_complex from a zero-dimension triangulation\n"; + return false; // ----- >> } - if (num_vertices() > 0) { - std::cerr << "Alpha_complex init - Cannot init twice\n"; - return; // ----- >> + if (complex.num_vertices() > 0) { + std::cerr << "Alpha_complex create_complex - complex is not empty\n"; + return false; // ----- >> } - - set_dimension(triangulation_->maximal_dimension()); + + complex.set_dimension(triangulation_->maximal_dimension()); // -------------------------------------------------------------------------------------------- // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa @@ -282,7 +284,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << std::endl; #endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); + complex.insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); } // -------------------------------------------------------------------------------------------- @@ -290,16 +292,16 @@ class Alpha_complex : public Simplex_tree<> { // Will be re-used many times Vector_of_CGAL_points pointVector; // ### For i : d -> 0 - for (int decr_dim = dimension(); decr_dim >= 0; decr_dim--) { + for (int decr_dim = complex.dimension(); decr_dim >= 0; decr_dim--) { // ### Foreach Sigma of dim i - for (auto f_simplex : skeleton_simplex_range(decr_dim)) { - int f_simplex_dim = dimension(f_simplex); + for (auto f_simplex : complex.skeleton_simplex_range(decr_dim)) { + int f_simplex_dim = complex.dimension(f_simplex); if (decr_dim == f_simplex_dim) { pointVector.clear(); #ifdef DEBUG_TRACES std::cout << "Sigma of dim " << decr_dim << " is"; #endif // DEBUG_TRACES - for (auto vertex : simplex_vertex_range(f_simplex)) { + for (auto vertex : complex.simplex_vertex_range(f_simplex)) { pointVector.push_back(get_point(vertex)); #ifdef DEBUG_TRACES std::cout << " " << vertex; @@ -309,7 +311,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << std::endl; #endif // DEBUG_TRACES // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (std::isnan(filtration(f_simplex))) { + if (std::isnan(complex.filtration(f_simplex))) { Filtration_value alpha_complex_filtration = 0.0; // No need to compute squared_radius on a single point - alpha is 0.0 if (f_simplex_dim > 0) { @@ -318,12 +320,12 @@ class Alpha_complex : public Simplex_tree<> { alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } - assign_filtration(f_simplex, alpha_complex_filtration); + complex.assign_filtration(f_simplex, alpha_complex_filtration); #ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl; + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << complex.filtration(f_simplex) << std::endl; #endif // DEBUG_TRACES } - propagate_alpha_filtration(f_simplex, decr_dim); + propagate_alpha_filtration(complex, f_simplex, decr_dim); } } } @@ -331,36 +333,45 @@ class Alpha_complex : public Simplex_tree<> { // -------------------------------------------------------------------------------------------- // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension - bool modified_filt = make_filtration_non_decreasing(); + bool modified_filt = complex.make_filtration_non_decreasing(); // Remove all simplices that have a filtration value greater than max_alpha_square // Remark: prune_above_filtration does not require initialize_filtration to be done before. - modified_filt |= prune_above_filtration(max_alpha_square); + modified_filt |= complex.prune_above_filtration(max_alpha_square); if (modified_filt) { - initialize_filtration(); + complex.initialize_filtration(); } // -------------------------------------------------------------------------------------------- + return true; } - template - void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { + private: + template + void propagate_alpha_filtration(Simplicial_complex& complex, Simplex_handle f_simplex, int decr_dim) { + // From Simplicial_complex type required to assign filtration values. + typedef typename Simplicial_complex::Filtration_value Filtration_value; +#ifdef DEBUG_TRACES + typedef typename Simplicial_complex::Vertex_handle Vertex_handle; +#endif // DEBUG_TRACES + // ### Foreach Tau face of Sigma - for (auto f_boundary : boundary_simplex_range(f_simplex)) { + for (auto f_boundary : complex.boundary_simplex_range(f_simplex)) { #ifdef DEBUG_TRACES std::cout << " | --------------------------------------------------\n"; std::cout << " | Tau "; - for (auto vertex : simplex_vertex_range(f_boundary)) { + for (auto vertex : complex.simplex_vertex_range(f_boundary)) { std::cout << vertex << " "; } std::cout << "is a face of Sigma\n"; - std::cout << " | isnan(filtration(Tau)=" << std::isnan(filtration(f_boundary)) << std::endl; + std::cout << " | isnan(complex.filtration(Tau)=" << std::isnan(complex.filtration(f_boundary)) << std::endl; #endif // DEBUG_TRACES // ### If filt(Tau) is not NaN - if (!std::isnan(filtration(f_boundary))) { + if (!std::isnan(complex.filtration(f_boundary))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) - Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); - assign_filtration(f_boundary, alpha_complex_filtration); + Filtration_value alpha_complex_filtration = fmin(complex.filtration(f_boundary), + complex.filtration(f_simplex)); + complex.assign_filtration(f_boundary, alpha_complex_filtration); #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << complex.filtration(f_boundary) << std::endl; #endif // DEBUG_TRACES // ### Else } else { @@ -372,12 +383,12 @@ class Alpha_complex : public Simplex_tree<> { #ifdef DEBUG_TRACES Vertex_handle vertexForGabriel = Vertex_handle(); #endif // DEBUG_TRACES - for (auto vertex : simplex_vertex_range(f_boundary)) { + for (auto vertex : complex.simplex_vertex_range(f_boundary)) { pointVector.push_back(get_point(vertex)); } // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function Point_d point_for_gabriel; - for (auto vertex : simplex_vertex_range(f_simplex)) { + for (auto vertex : complex.simplex_vertex_range(f_simplex)) { point_for_gabriel = get_point(vertex); if (std::find(pointVector.begin(), pointVector.end(), point_for_gabriel) == pointVector.end()) { #ifdef DEBUG_TRACES @@ -398,10 +409,10 @@ class Alpha_complex : public Simplex_tree<> { // ### If Tau is not Gabriel of Sigma if (false == is_gab) { // ### filt(Tau) = filt(Sigma) - Filtration_value alpha_complex_filtration = filtration(f_simplex); - assign_filtration(f_boundary, alpha_complex_filtration); + Filtration_value alpha_complex_filtration = complex.filtration(f_simplex); + complex.assign_filtration(f_boundary, alpha_complex_filtration); #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = filt(Sigma) = " << complex.filtration(f_boundary) << std::endl; #endif // DEBUG_TRACES } } diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 4d7bf622..0d4132f8 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -33,6 +33,9 @@ #include #include +// to construct a simplex_tree from Delaunay_triangulation +#include +#include // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d; @@ -49,47 +52,35 @@ BOOST_AUTO_TEST_CASE(ALPHA_DOC_OFF_file) { std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << max_alpha_square_value << "==========" << std::endl; - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name); - const int DIMENSION = 2; - std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; - BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); + Gudhi::Simplex_tree<> simplex_tree_60; + BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_60, max_alpha_square_value)); - const int NUMBER_OF_VERTICES = 7; - std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; - BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); + std::cout << "simplex_tree_60.dimension()=" << simplex_tree_60.dimension() << std::endl; + BOOST_CHECK(simplex_tree_60.dimension() == 2); - const int NUMBER_OF_SIMPLICES = 25; - std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + std::cout << "simplex_tree_60.num_vertices()=" << simplex_tree_60.num_vertices() << std::endl; + BOOST_CHECK(simplex_tree_60.num_vertices() == 7); -} + std::cout << "simplex_tree_60.num_simplices()=" << simplex_tree_60.num_simplices() << std::endl; + BOOST_CHECK(simplex_tree_60.num_simplices() == 25); -BOOST_AUTO_TEST_CASE(ALPHA_DOC_OFF_file_filtered) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-complex from a OFF file - // - // ---------------------------------------------------------------------------- - std::string off_file_name("alphacomplexdoc.off"); - double max_alpha_square_value = 59.0; + max_alpha_square_value = 59.0; std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << max_alpha_square_value << "==========" << std::endl; - // Use of the default dynamic kernel - Gudhi::alpha_complex::Alpha_complex<> alpha_complex_from_file(off_file_name, max_alpha_square_value); - - const int DIMENSION = 2; - std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; - BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); + Gudhi::Simplex_tree<> simplex_tree_59; + BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_59, max_alpha_square_value)); + + std::cout << "simplex_tree_59.dimension()=" << simplex_tree_59.dimension() << std::endl; + BOOST_CHECK(simplex_tree_59.dimension() == 2); - const int NUMBER_OF_VERTICES = 7; - std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; - BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); + std::cout << "simplex_tree_59.num_vertices()=" << simplex_tree_59.num_vertices() << std::endl; + BOOST_CHECK(simplex_tree_59.num_vertices() == 7); - const int NUMBER_OF_SIMPLICES = 23; - std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + std::cout << "simplex_tree_59.num_simplices()=" << simplex_tree_59.num_simplices() << std::endl; + BOOST_CHECK(simplex_tree_59.num_simplices() == 23); } bool are_almost_the_same(float a, float b) { @@ -132,40 +123,43 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { std::cout << "========== Alpha_complex_from_points ==========" << std::endl; + Gudhi::Simplex_tree<> simplex_tree; + BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree)); + // Another way to check num_simplices std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; int num_simplices = 0; - for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + for (auto f_simplex : simplex_tree.filtration_simplex_range()) { num_simplices++; std::cout << " ( "; - for (auto vertex : alpha_complex_from_points.simplex_vertex_range(f_simplex)) { + for (auto vertex : simplex_tree.simplex_vertex_range(f_simplex)) { std::cout << vertex << " "; } - std::cout << ") -> " << "[" << alpha_complex_from_points.filtration(f_simplex) << "] "; + std::cout << ") -> " << "[" << simplex_tree.filtration(f_simplex) << "] "; std::cout << std::endl; } BOOST_CHECK(num_simplices == 15); - std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_points.num_simplices() == 15); + std::cout << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl; + BOOST_CHECK(simplex_tree.num_simplices() == 15); - std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; - BOOST_CHECK(alpha_complex_from_points.dimension() == 4); - std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; - BOOST_CHECK(alpha_complex_from_points.num_vertices() == 4); + std::cout << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl; + BOOST_CHECK(simplex_tree.dimension() == 4); + std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; + BOOST_CHECK(simplex_tree.num_vertices() == 4); - for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { - switch (alpha_complex_from_points.dimension(f_simplex)) { + for (auto f_simplex : simplex_tree.filtration_simplex_range()) { + switch (simplex_tree.dimension(f_simplex)) { case 0: - BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 0.0)); + BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 0.0)); break; case 1: - BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 1.0/2.0)); + BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 1.0/2.0)); break; case 2: - BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 2.0/3.0)); + BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 2.0/3.0)); break; case 3: - BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 3.0/4.0)); + BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 3.0/4.0)); break; default: BOOST_CHECK(false); // Shall not happen @@ -199,40 +193,40 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { BOOST_CHECK_THROW (alpha_complex_from_points.get_point(1234), std::out_of_range); // Test after prune_above_filtration - bool modified = alpha_complex_from_points.prune_above_filtration(0.6); + bool modified = simplex_tree.prune_above_filtration(0.6); if (modified) { - alpha_complex_from_points.initialize_filtration(); + simplex_tree.initialize_filtration(); } BOOST_CHECK(modified); // Another way to check num_simplices std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; num_simplices = 0; - for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + for (auto f_simplex : simplex_tree.filtration_simplex_range()) { num_simplices++; std::cout << " ( "; - for (auto vertex : alpha_complex_from_points.simplex_vertex_range(f_simplex)) { + for (auto vertex : simplex_tree.simplex_vertex_range(f_simplex)) { std::cout << vertex << " "; } - std::cout << ") -> " << "[" << alpha_complex_from_points.filtration(f_simplex) << "] "; + std::cout << ") -> " << "[" << simplex_tree.filtration(f_simplex) << "] "; std::cout << std::endl; } BOOST_CHECK(num_simplices == 10); - std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_points.num_simplices() == 10); + std::cout << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl; + BOOST_CHECK(simplex_tree.num_simplices() == 10); - std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; - BOOST_CHECK(alpha_complex_from_points.dimension() == 4); - std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; - BOOST_CHECK(alpha_complex_from_points.num_vertices() == 4); + std::cout << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl; + BOOST_CHECK(simplex_tree.dimension() == 4); + std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; + BOOST_CHECK(simplex_tree.num_vertices() == 4); - for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { - switch (alpha_complex_from_points.dimension(f_simplex)) { + for (auto f_simplex : simplex_tree.filtration_simplex_range()) { + switch (simplex_tree.dimension(f_simplex)) { case 0: - BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 0.0)); + BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 0.0)); break; case 1: - BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 1.0/2.0)); + BOOST_CHECK(are_almost_the_same(simplex_tree.filtration(f_simplex), 1.0/2.0)); break; default: BOOST_CHECK(false); // Shall not happen diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp index cb181936..44eda6aa 100644 --- a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -4,6 +4,8 @@ #include #include +// to construct a simplex_tree from alpha complex +#include #include #include @@ -30,35 +32,38 @@ int main(int argc, char **argv) { // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- using Kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_points, alpha_square_max_value); - - // ---------------------------------------------------------------------------- - // Display information about the alpha complex - // ---------------------------------------------------------------------------- - std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << - " - " << alpha_complex_from_file.num_simplices() << " simplices - " << - alpha_complex_from_file.num_vertices() << " vertices." << std::endl; - - // Sort the simplices in the order of the filtration - alpha_complex_from_file.initialize_filtration(); - - std::cout << "Simplex_tree dim: " << alpha_complex_from_file.dimension() << std::endl; - // Compute the persistence diagram of the complex - Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::alpha_complex::Alpha_complex, - Gudhi::persistent_cohomology::Field_Zp > pcoh(alpha_complex_from_file); - // initializes the coefficient field for homology - pcoh.init_coefficients(coeff_field_characteristic); - - pcoh.compute_persistent_cohomology(min_persistence); - - // Output the diagram in filediag - if (output_file_diag.empty()) { - pcoh.output_diagram(); - } else { - std::cout << "Result in file: " << output_file_diag << std::endl; - std::ofstream out(output_file_diag); - pcoh.output_diagram(out); - out.close(); + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_points); + + Gudhi::Simplex_tree<> simplex; + if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) { + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Simplicial complex is of dimension " << simplex.dimension() << + " - " << simplex.num_simplices() << " simplices - " << + simplex.num_vertices() << " vertices." << std::endl; + + // Sort the simplices in the order of the filtration + simplex.initialize_filtration(); + + std::cout << "Simplex_tree dim: " << simplex.dimension() << std::endl; + // Compute the persistence diagram of the complex + Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::Simplex_tree<>, + Gudhi::persistent_cohomology::Field_Zp > pcoh(simplex); + // initializes the coefficient field for homology + pcoh.init_coefficients(coeff_field_characteristic); + + pcoh.compute_persistent_cohomology(min_persistence); + + // Output the diagram in filediag + if (output_file_diag.empty()) { + pcoh.output_diagram(); + } else { + std::cout << "Result in file: " << output_file_diag << std::endl; + std::ofstream out(output_file_diag); + pcoh.output_diagram(out); + out.close(); + } } return 0; diff --git a/src/Persistent_cohomology/example/custom_persistence_sort.cpp b/src/Persistent_cohomology/example/custom_persistence_sort.cpp index 9af38611..8e254700 100644 --- a/src/Persistent_cohomology/example/custom_persistence_sort.cpp +++ b/src/Persistent_cohomology/example/custom_persistence_sort.cpp @@ -27,6 +27,8 @@ #include #include +// to construct a simplex_tree from alpha complex +#include #include #include @@ -38,6 +40,9 @@ using Kernel = CGAL::Epick_d< CGAL::Dimension_tag<3> >; using Point = Kernel::Point_d; using Alpha_complex = Gudhi::alpha_complex::Alpha_complex; +using Simplex_tree = Gudhi::Simplex_tree<>; +using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology< Simplex_tree, + Gudhi::persistent_cohomology::Field_Zp >; std::vector random_points() { // Instanciate a random point generator @@ -60,7 +65,7 @@ std::vector random_points() { * Compare two intervals by dimension, then by length. */ struct cmp_intervals_by_dim_then_length { - explicit cmp_intervals_by_dim_then_length(Alpha_complex * sc) + explicit cmp_intervals_by_dim_then_length(Simplex_tree * sc) : sc_(sc) { } template @@ -71,46 +76,62 @@ struct cmp_intervals_by_dim_then_length { else return (sc_->dimension(get < 0 > (p1)) > sc_->dimension(get < 0 > (p2))); } - Alpha_complex* sc_; + Simplex_tree* sc_; }; int main(int argc, char **argv) { std::vector points = random_points(); + std::cout << "Points size=" << points.size() << std::endl; // Alpha complex persistence computation from generated points - Alpha_complex alpha_complex_from_points(points, 0.6); - - using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology< Alpha_complex, - Gudhi::persistent_cohomology::Field_Zp >; - Persistent_cohomology pcoh(alpha_complex_from_points); - - // initializes the coefficient field for homology - Z/3Z - pcoh.init_coefficients(3); - pcoh.compute_persistent_cohomology(0.2); - - // Custom sort and output persistence - cmp_intervals_by_dim_then_length cmp(&alpha_complex_from_points); - auto persistent_pairs = pcoh.get_persistent_pairs(); - std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp); - for (auto pair : persistent_pairs) { - std::cout << alpha_complex_from_points.dimension(get<0>(pair)) << " " - << alpha_complex_from_points.filtration(get<0>(pair)) << " " - << alpha_complex_from_points.filtration(get<1>(pair)) << std::endl; + Alpha_complex alpha_complex_from_points(points); + std::cout << "alpha_complex_from_points" << std::endl; + + Simplex_tree simplex; + std::cout << "simplex" << std::endl; + if (alpha_complex_from_points.create_complex(simplex, 0.6)) { + std::cout << "simplex" << std::endl; + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Simplicial complex is of dimension " << simplex.dimension() << + " - " << simplex.num_simplices() << " simplices - " << + simplex.num_vertices() << " vertices." << std::endl; + + // Sort the simplices in the order of the filtration + simplex.initialize_filtration(); + + std::cout << "Simplex_tree dim: " << simplex.dimension() << std::endl; + + Persistent_cohomology pcoh(simplex); + + // initializes the coefficient field for homology - Z/3Z + pcoh.init_coefficients(3); + pcoh.compute_persistent_cohomology(0.2); + + // Custom sort and output persistence + cmp_intervals_by_dim_then_length cmp(&simplex); + auto persistent_pairs = pcoh.get_persistent_pairs(); + std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp); + for (auto pair : persistent_pairs) { + std::cout << simplex.dimension(get<0>(pair)) << " " + << simplex.filtration(get<0>(pair)) << " " + << simplex.filtration(get<1>(pair)) << std::endl; + } + + // Persistent Betti numbers + std::cout << "The persistent Betti numbers in interval [0.40, 0.41] are : "; + for (int dim = 0; dim < simplex.dimension(); dim++) + std::cout << "b" << dim << " = " << pcoh.persistent_betti_number(dim, 0.40, 0.41) << " ; "; + std::cout << std::endl; + + // Betti numbers + std::vector betti_numbers = pcoh.betti_numbers(); + std::cout << "The Betti numbers are : "; + for (std::size_t i = 0; i < betti_numbers.size(); i++) + std::cout << "b" << i << " = " << betti_numbers[i] << " ; "; + std::cout << std::endl; } - - // Persistent Betti numbers - std::cout << "The persistent Betti numbers in interval [0.40, 0.41] are : "; - for (int dim = 0; dim < alpha_complex_from_points.dimension(); dim++) - std::cout << "b" << dim << " = " << pcoh.persistent_betti_number(dim, 0.40, 0.41) << " ; "; - std::cout << std::endl; - - // Betti numbers - std::vector betti_numbers = pcoh.betti_numbers(); - std::cout << "The Betti numbers are : "; - for (std::size_t i = 0; i < betti_numbers.size(); i++) - std::cout << "b" << i << " = " << betti_numbers[i] << " ; "; - std::cout << std::endl; - return 0; } -- cgit v1.2.3 From 6b1843bc5f19800433eedd288f2d966a985bcc16 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 23 Sep 2016 07:26:41 +0000 Subject: Modify the Alpha complex doc wit a concept to create a simplicial complex from alpha complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1546 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d8083c3b0e03e1cf0033e5c7c1ba6f95618efdc1 --- .../concept/Simplicial_complex_for_alpha.h | 98 ++++++++++++++++++++++ src/Alpha_complex/doc/Intro_alpha_complex.h | 6 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 31 +++---- 3 files changed, 117 insertions(+), 18 deletions(-) create mode 100644 src/Alpha_complex/concept/Simplicial_complex_for_alpha.h (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h new file mode 100644 index 00000000..2fd5dc03 --- /dev/null +++ b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h @@ -0,0 +1,98 @@ +/* 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) 2016 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 . + */ + +#ifndef CONCEPT_ALPHA_COMPLEX_SIMPLICIAL_COMPLEX_FOR_ALPHA_H_ +#define CONCEPT_ALPHA_COMPLEX_SIMPLICIAL_COMPLEX_FOR_ALPHA_H_ + +namespace Gudhi { + +namespace alpha_complex { + +/** \brief The concept SimplicialComplexForAlpha describes the requirements for a type to implement a simplicial + * complex, that can be created from a `Alpha_complex`. + */ +struct SimplicialComplexForAlpha { + /** Handle to specify a simplex. */ + typedef unspecified Simplex_handle; + /** Handle to specify a vertex. Must be a non-negative integer. */ + typedef unspecified Vertex_handle; + /** Handle to specify the simplex filtration value. */ + typedef unspecified Filtration_value; + + /** Returns the number of vertices in the simplicial complex. */ + std::size_t num_vertices(); + + /** Gets the simplicial complex dimension. */ + int dimension(); + + /** Sets the simplicial complex dimension. */ + void set_dimension(int dimension); + + /** Gets the 'simplex' dimension. */ + int dimension(Simplex_handle simplex); + + /** Assigns the 'simplex' with the given 'filtration' value. */ + int assign_filtration(Simplex_handle simplex, Filtration_value filtration); + + /** \brief Inserts a simplex with vertices from a given range 'vertex_range' in the simplicial complex with the given + * 'filtration' value. */ + template< typedef Input_vertex_range > + Insertion_result_type insert_simplex_and_subfaces(Input_vertex_range const & vertex_range, + Filtration_value filtration); + + /** Browses the simplicial complex to make the filtration non-decreasing. */ + void make_filtration_non_decreasing(); + + /** Prune the simplicial complex above 'filtration' value given as parameter. */ + void prune_above_filtration(Filtration_value filtration); + + /** Sorts the filtration values in the simplicial complex. */ + void initialize_filtration(); + + /** \brief Iterator over vertices of a simplex. + * + * 'value type' must be 'Vertex_handle'.*/ + typedef unspecified Simplex_vertex_range; + + /** \brief Returns a range over vertices of a given + * simplex. */ + Simplex_vertex_range simplex_vertex_range(Simplex_handle const & simplex); + + /** \brief Iterator over the boundaries of the complex, in an arbitrary order. + * + * 'value_type' must be 'Simplex_handle'.*/ + typedef unspecified Boundary_simplex_range; + + /** \brief Returns a range over boundaries of a given simplex. */ + Boundary_simplex_range boundary_simplex_range(Simplex_handle const & simplex); + + /** \brief Return type of an insertion of a simplex + */ + typedef unspecified Insertion_result_type; + +}; + +} // namespace alpha_complex + +} // namespace Gudhi + +#endif // CONCEPT_ALPHA_COMPLEX_SIMPLICIAL_COMPLEX_FOR_ALPHA_H_ diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 4ca3271b..3ffdae7f 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -51,7 +51,7 @@ namespace alpha_complex { * Alpha_complex is constructing a Delaunay Triangulation * \cite cgal:hdj-t-15b from CGAL (the Computational Geometry - * Algorithms Library \cite cgal:eb-15b) and is able to create a `Simplicial_complex_for_alpha`. + * Algorithms Library \cite cgal:eb-15b) and is able to create a `SimplicialComplexForAlpha`. * * The complex is a template class requiring an Epick_d dD Geometry Kernel @@ -135,12 +135,12 @@ namespace alpha_complex { * * As the squared radii computed by CGAL are an approximation, it might happen that these alpha squared values do not * quite define a proper filtration (i.e. non-decreasing with respect to inclusion). - * We fix that up by calling `Simplicial_complex_for_alpha::make_filtration_non_decreasing()`. + * We fix that up by calling `SimplicialComplexForAlpha::make_filtration_non_decreasing()`. * * \subsubsection pruneabove Prune above given filtration value * * The simplex tree is pruned from the given maximum alpha squared value (cf. - * `Simplicial_complex_for_alpha::prune_above_filtration()`). + * `SimplicialComplexForAlpha::prune_above_filtration()`). * In the following example, the value is given by the user as argument of the program. * * diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 66a55ac7..ab96531f 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -206,17 +206,17 @@ class Alpha_complex { } public: - template - bool create_complex(Simplicial_complex& complex) { - typedef typename Simplicial_complex::Filtration_value Filtration_value; + template + bool create_complex(SimplicialComplexForAlpha& complex) { + typedef typename SimplicialComplexForAlpha::Filtration_value Filtration_value; return create_complex(complex, std::numeric_limits::infinity()); } /** \brief Initialize the simplicial complex from the Delaunay triangulation. * - * \tparam Simplicial_complex must meet Simplicial_complex_for_alpha concept. + * \tparam SimplicialComplexForAlpha must meet `SimplicialComplexForAlpha` concept. * - * @param[in] complex Simplicial_complex to be created. + * @param[in] complex SimplicialComplexForAlpha to be created. * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. * * @return true if creation succeeds, false otherwise. @@ -226,10 +226,11 @@ class Alpha_complex { * * Initialization can be launched once. */ - template - bool create_complex(Simplicial_complex& complex, Filtration_value max_alpha_square) { - // From Simplicial_complex type required to insert into a simplicial complex (with or without subfaces). - typedef typename Simplicial_complex::Vertex_handle Vertex_handle; + template + bool create_complex(SimplicialComplexForAlpha& complex, Filtration_value max_alpha_square) { + // From SimplicialComplexForAlpha type required to insert into a simplicial complex (with or without subfaces). + typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle; + typedef typename SimplicialComplexForAlpha::Simplex_handle Simplex_handle; typedef std::vector Vector_vertex; if (triangulation_ == nullptr) { @@ -294,7 +295,7 @@ class Alpha_complex { // ### For i : d -> 0 for (int decr_dim = complex.dimension(); decr_dim >= 0; decr_dim--) { // ### Foreach Sigma of dim i - for (auto f_simplex : complex.skeleton_simplex_range(decr_dim)) { + for (Simplex_handle f_simplex : complex.skeleton_simplex_range(decr_dim)) { int f_simplex_dim = complex.dimension(f_simplex); if (decr_dim == f_simplex_dim) { pointVector.clear(); @@ -345,12 +346,12 @@ class Alpha_complex { } private: - template - void propagate_alpha_filtration(Simplicial_complex& complex, Simplex_handle f_simplex, int decr_dim) { - // From Simplicial_complex type required to assign filtration values. - typedef typename Simplicial_complex::Filtration_value Filtration_value; + template + void propagate_alpha_filtration(SimplicialComplexForAlpha& complex, Simplex_handle f_simplex, int decr_dim) { + // From SimplicialComplexForAlpha type required to assign filtration values. + typedef typename SimplicialComplexForAlpha::Filtration_value Filtration_value; #ifdef DEBUG_TRACES - typedef typename Simplicial_complex::Vertex_handle Vertex_handle; + typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle; #endif // DEBUG_TRACES // ### Foreach Tau face of Sigma -- cgit v1.2.3 From 0101a149fc124d62f8a4966654fa30e01f57d424 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 23 Sep 2016 09:37:35 +0000 Subject: Fix cpplints git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1548 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b8d7d5b4bde8aeec92d6bfc79b8c146c551317c0 --- src/Alpha_complex/concept/Simplicial_complex_for_alpha.h | 7 +++---- src/Alpha_complex/example/Alpha_complex_from_off.cpp | 7 ++++--- src/Alpha_complex/example/Alpha_complex_from_points.cpp | 2 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +++--- .../example/alpha_complex_persistence.cpp | 8 ++++---- .../example/custom_persistence_sort.cpp | 14 +++++++------- 6 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h index 2fd5dc03..384ac2eb 100644 --- a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h +++ b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h @@ -40,7 +40,7 @@ struct SimplicialComplexForAlpha { /** Returns the number of vertices in the simplicial complex. */ std::size_t num_vertices(); - + /** Gets the simplicial complex dimension. */ int dimension(); @@ -61,10 +61,10 @@ struct SimplicialComplexForAlpha { /** Browses the simplicial complex to make the filtration non-decreasing. */ void make_filtration_non_decreasing(); - + /** Prune the simplicial complex above 'filtration' value given as parameter. */ void prune_above_filtration(Filtration_value filtration); - + /** Sorts the filtration values in the simplicial complex. */ void initialize_filtration(); @@ -88,7 +88,6 @@ struct SimplicialComplexForAlpha { /** \brief Return type of an insertion of a simplex */ typedef unspecified Insertion_result_type; - }; } // namespace alpha_complex diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 31f8e10c..32bef1cd 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -39,15 +39,16 @@ int main(int argc, char **argv) { Gudhi::Simplex_tree<> simplex; if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) { std::ostream output_stream(streambufffer); - + // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- output_stream << "Alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; - - output_stream << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + + output_stream << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << + std::endl; for (auto f_simplex : simplex.filtration_simplex_range()) { output_stream << " ( "; for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index fa3c1efc..491b7e6d 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -53,7 +53,7 @@ int main(int argc, char **argv) { std::cout << "Alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; - + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : simplex.filtration_simplex_range()) { std::cout << " ( "; diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index ab96531f..8bb6af1f 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -232,7 +232,7 @@ class Alpha_complex { typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle; typedef typename SimplicialComplexForAlpha::Simplex_handle Simplex_handle; typedef std::vector Vector_vertex; - + if (triangulation_ == nullptr) { std::cerr << "Alpha_complex cannot create_complex from a NULL triangulation\n"; return false; // ----- >> @@ -249,7 +249,7 @@ class Alpha_complex { std::cerr << "Alpha_complex create_complex - complex is not empty\n"; return false; // ----- >> } - + complex.set_dimension(triangulation_->maximal_dimension()); // -------------------------------------------------------------------------------------------- @@ -353,7 +353,7 @@ class Alpha_complex { #ifdef DEBUG_TRACES typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle; #endif // DEBUG_TRACES - + // ### Foreach Tau face of Sigma for (auto f_boundary : complex.boundary_simplex_range(f_simplex)) { #ifdef DEBUG_TRACES diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp index 44eda6aa..2412569a 100644 --- a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -42,19 +42,19 @@ int main(int argc, char **argv) { std::cout << "Simplicial complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; - + // Sort the simplices in the order of the filtration simplex.initialize_filtration(); - + std::cout << "Simplex_tree dim: " << simplex.dimension() << std::endl; // Compute the persistence diagram of the complex Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::Simplex_tree<>, Gudhi::persistent_cohomology::Field_Zp > pcoh(simplex); // initializes the coefficient field for homology pcoh.init_coefficients(coeff_field_characteristic); - + pcoh.compute_persistent_cohomology(min_persistence); - + // Output the diagram in filediag if (output_file_diag.empty()) { pcoh.output_diagram(); diff --git a/src/Persistent_cohomology/example/custom_persistence_sort.cpp b/src/Persistent_cohomology/example/custom_persistence_sort.cpp index 8e254700..64f2a4dc 100644 --- a/src/Persistent_cohomology/example/custom_persistence_sort.cpp +++ b/src/Persistent_cohomology/example/custom_persistence_sort.cpp @@ -97,18 +97,18 @@ int main(int argc, char **argv) { std::cout << "Simplicial complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; - + // Sort the simplices in the order of the filtration simplex.initialize_filtration(); - + std::cout << "Simplex_tree dim: " << simplex.dimension() << std::endl; - + Persistent_cohomology pcoh(simplex); - + // initializes the coefficient field for homology - Z/3Z pcoh.init_coefficients(3); pcoh.compute_persistent_cohomology(0.2); - + // Custom sort and output persistence cmp_intervals_by_dim_then_length cmp(&simplex); auto persistent_pairs = pcoh.get_persistent_pairs(); @@ -118,13 +118,13 @@ int main(int argc, char **argv) { << simplex.filtration(get<0>(pair)) << " " << simplex.filtration(get<1>(pair)) << std::endl; } - + // Persistent Betti numbers std::cout << "The persistent Betti numbers in interval [0.40, 0.41] are : "; for (int dim = 0; dim < simplex.dimension(); dim++) std::cout << "b" << dim << " = " << pcoh.persistent_betti_number(dim, 0.40, 0.41) << " ; "; std::cout << std::endl; - + // Betti numbers std::vector betti_numbers = pcoh.betti_numbers(); std::cout << "The Betti numbers are : "; -- cgit v1.2.3 From ad0a044bbb906d553ae3f7931d7f4074c503ede2 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 3 Oct 2016 12:48:26 +0000 Subject: Rephrase the alpha complex data structure git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1604 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b9d99909027944d2a98096830646bda36b18ec9b --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 8bb6af1f..edc5ad25 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -54,9 +54,9 @@ namespace alpha_complex { * \ingroup alpha_complex * * \details - * The data structure can be constructed from a CGAL Delaunay triangulation (for more informations on CGAL Delaunay - * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) or from - * an OFF file (cf. Points_off_reader). + * The data structure is constructing a CGAL Delaunay triangulation (for more informations 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). * * Please refer to \ref alpha_complex for examples. * -- cgit v1.2.3 From f9b1bc43d775a9d3a608fb62fe40b559a2cb5d25 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 3 Oct 2016 12:54:38 +0000 Subject: Remove confusing post condition of ctor git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1605 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8ba221d495b3ab167e3e151af07e68bfcfa015e4 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index edc5ad25..b0c09b88 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -114,7 +114,8 @@ class Alpha_complex { public: /** \brief Alpha_complex constructor from an OFF file name. - * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize + * + * Uses the Points_off_reader to construct the Delaunay triangulation required to initialize * the Alpha_complex. * * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. @@ -140,8 +141,6 @@ class Alpha_complex { * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. - * - * @post Compare num_simplices with InputPointRange points number (not the same in case of duplicate points). */ template Alpha_complex(const InputPointRange& points) -- cgit v1.2.3 From 8b1e2bed3fe242003cb7200ab6099925537d8bab Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 3 Oct 2016 13:21:28 +0000 Subject: get_point can return a const Point& git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1606 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 44cec97d381409fdc2a707300c2fe93c67428e09 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index b0c09b88..cda40021 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -168,7 +168,7 @@ class Alpha_complex { * @return The point found. * @exception std::out_of_range In case vertex is not found (cf. std::vector::at). */ - Point_d get_point(std::size_t vertex) const { + const Point_d& get_point(std::size_t vertex) const { return vertex_handle_to_iterator_.at(vertex)->point(); } -- cgit v1.2.3 From 66cdca82e9ca86fcdfa2a08c6003a5661d802cf3 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 3 Oct 2016 13:39:50 +0000 Subject: No need of complex.dimension(void). It reduces the concept. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1608 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 95cf6a9b453349e032c1d553bb9b5c3981c92b0a --- src/Alpha_complex/concept/Simplicial_complex_for_alpha.h | 3 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h index 24aab215..0cbf1769 100644 --- a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h +++ b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h @@ -41,9 +41,6 @@ struct SimplicialComplexForAlpha { /** Returns the number of vertices in the simplicial complex. */ std::size_t num_vertices(); - /** Gets the simplicial complex dimension. */ - int dimension(); - /** Sets the simplicial complex dimension. */ void set_dimension(int dimension); diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index cda40021..0613ca7c 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -292,7 +292,7 @@ class Alpha_complex { // Will be re-used many times Vector_of_CGAL_points pointVector; // ### For i : d -> 0 - for (int decr_dim = complex.dimension(); decr_dim >= 0; decr_dim--) { + for (int decr_dim = triangulation_->maximal_dimension(); decr_dim >= 0; decr_dim--) { // ### Foreach Sigma of dim i for (Simplex_handle f_simplex : complex.skeleton_simplex_range(decr_dim)) { int f_simplex_dim = complex.dimension(f_simplex); -- cgit v1.2.3 From 3950bb33f65f4831060f10a73c7e88cdfe9717bf Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 3 Oct 2016 14:03:50 +0000 Subject: Rephrase create_complex. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1609 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8e21ddb519ab3dc87f6de08f6f7fcb38848bfc78 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 0613ca7c..ffcd26a3 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -148,9 +148,7 @@ class Alpha_complex { init_from_range(points); } - /** \brief Alpha_complex destructor. - * - * @warning Deletes the Delaunay triangulation. + /** \brief Alpha_complex destructor deletes the Delaunay triangulation. */ ~Alpha_complex() { delete triangulation_; @@ -211,7 +209,8 @@ class Alpha_complex { return create_complex(complex, std::numeric_limits::infinity()); } - /** \brief Initialize the simplicial complex from the Delaunay triangulation. + /** \brief Inserts all Delaunay triangulation into the simplicial complex. + * It also computes the filtration values accordingly to the \ref createcomplexalgorithm * * \tparam SimplicialComplexForAlpha must meet `SimplicialComplexForAlpha` concept. * @@ -220,8 +219,9 @@ class Alpha_complex { * * @return true if creation succeeds, false otherwise. * - * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more + * @pre Delaunay triangulation must be already constructed with at least one vertex and dimension must be more * than 0. + * @pre The simplicial complex must be empty (no vertices) * * Initialization can be launched once. */ -- cgit v1.2.3 From 1693786349ba3a3c7ca003d8a2e8afd6f0556539 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 5 Oct 2016 20:57:19 +0000 Subject: Fix review comments git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1648 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: de0b4f12b6eb814224df13c5cec1069310115efa --- .../concept/Simplicial_complex_for_alpha.h | 3 - src/Alpha_complex/include/gudhi/Alpha_complex.h | 77 ++++++++++------------ src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 29 ++++++++ 3 files changed, 63 insertions(+), 46 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h index 0cbf1769..2b8bff94 100644 --- a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h +++ b/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h @@ -60,9 +60,6 @@ struct SimplicialComplexForAlpha { /** Prune the simplicial complex above 'filtration' value given as parameter. */ void prune_above_filtration(Filtration_value filtration); - /** Sorts the filtration values in the simplicial complex. */ - void initialize_filtration(); - /** \brief Iterator over vertices of a simplex. * * 'value type' must be 'Vertex_handle'.*/ diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index ffcd26a3..69142a58 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -175,30 +175,28 @@ class Alpha_complex { void init_from_range(const InputPointRange& points) { auto first = std::begin(points); auto last = std::end(points); - if (first != last) { - // point_dimension function initialization - Point_Dimension point_dimension = kernel_.point_dimension_d_object(); + // point_dimension function initialization + Point_Dimension point_dimension = kernel_.point_dimension_d_object(); - // Delaunay triangulation is point dimension. - triangulation_ = new Delaunay_triangulation(point_dimension(*first)); + // Delaunay triangulation is point dimension. + triangulation_ = new Delaunay_triangulation(point_dimension(*first)); - std::vector points(first, last); + std::vector point_cloud(first, last); - // Creates a vector {0, 1, ..., N-1} - std::vector indices(boost::counting_iterator(0), - boost::counting_iterator(points.size())); + // Creates a vector {0, 1, ..., N-1} + std::vector indices(boost::counting_iterator(0), + boost::counting_iterator(point_cloud.size())); - // Sort indices considering CGAL spatial sort - typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; - spatial_sort(indices.begin(), indices.end(), Search_traits_d(&(points[0]))); + // Sort indices considering CGAL spatial sort + typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; + spatial_sort(indices.begin(), indices.end(), Search_traits_d(&(point_cloud[0]))); - typename Delaunay_triangulation::Full_cell_handle hint; - for (auto index : indices) { - typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(points[index], hint); - // Save index value as data to retrieve it after insertion - pos->data() = index; - hint = pos->full_cell(); - } + typename Delaunay_triangulation::Full_cell_handle hint; + for (auto index : indices) { + typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(point_cloud[index], hint); + // Save index value as data to retrieve it after insertion + pos->data() = index; + hint = pos->full_cell(); } } @@ -219,8 +217,7 @@ class Alpha_complex { * * @return true if creation succeeds, false otherwise. * - * @pre Delaunay triangulation must be already constructed with at least one vertex and dimension must be more - * than 0. + * @pre Delaunay triangulation must be already constructed with dimension strictly greater than 0. * @pre The simplicial complex must be empty (no vertices) * * Initialization can be launched once. @@ -236,10 +233,6 @@ class Alpha_complex { std::cerr << "Alpha_complex cannot create_complex from a NULL triangulation\n"; return false; // ----- >> } - if (triangulation_->number_of_vertices() < 1) { - std::cerr << "Alpha_complex cannot create_complex from a triangulation without vertices\n"; - return false; // ----- >> - } if (triangulation_->maximal_dimension() < 1) { std::cerr << "Alpha_complex cannot create_complex from a zero-dimension triangulation\n"; return false; // ----- >> @@ -266,25 +259,27 @@ class Alpha_complex { // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list - for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { - Vector_vertex vertexVector; + if (triangulation_->number_of_vertices() > 0) { + for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { + Vector_vertex vertexVector; #ifdef DEBUG_TRACES - std::cout << "Simplex_tree insertion "; + std::cout << "Simplex_tree insertion "; #endif // DEBUG_TRACES - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - if (*vit != nullptr) { + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + if (*vit != nullptr) { #ifdef DEBUG_TRACES - std::cout << " " << (*vit)->data(); + std::cout << " " << (*vit)->data(); #endif // DEBUG_TRACES - // Vector of vertex construction for simplex_tree structure - vertexVector.push_back((*vit)->data()); + // Vector of vertex construction for simplex_tree structure + vertexVector.push_back((*vit)->data()); + } } - } #ifdef DEBUG_TRACES - std::cout << std::endl; + std::cout << std::endl; #endif // DEBUG_TRACES - // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - complex.insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); + // Insert each simplex and its subfaces in the simplex tree - filtration is NaN + complex.insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); + } } // -------------------------------------------------------------------------------------------- @@ -333,13 +328,9 @@ class Alpha_complex { // -------------------------------------------------------------------------------------------- // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension - bool modified_filt = complex.make_filtration_non_decreasing(); + complex.make_filtration_non_decreasing(); // Remove all simplices that have a filtration value greater than max_alpha_square - // Remark: prune_above_filtration does not require initialize_filtration to be done before. - modified_filt |= complex.prune_above_filtration(max_alpha_square); - if (modified_filt) { - complex.initialize_filtration(); - } + complex.prune_above_filtration(max_alpha_square); // -------------------------------------------------------------------------------------------- return true; } diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 0d4132f8..b03851d1 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -235,3 +235,32 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { } } + +BOOST_AUTO_TEST_CASE(Alpha_complex_from_empty_points) { + // ---------------------------------------------------------------------------- + // Init of a list of points + // ---------------------------------------------------------------------------- + Vector_of_points points; + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from the list of points + // ---------------------------------------------------------------------------- + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); + + std::cout << "========== Alpha_complex_from_empty_points ==========" << std::endl; + + Gudhi::Simplex_tree<> simplex_tree; + BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree)); + + std::cout << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl; + BOOST_CHECK(simplex_tree.num_simplices() == 0); + + std::cout << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl; + BOOST_CHECK(simplex_tree.dimension() == 4); + + std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; + BOOST_CHECK(simplex_tree.num_vertices() == 0); + + // Test to the limit + BOOST_CHECK_THROW (alpha_complex_from_points.get_point(0), std::out_of_range); +} -- cgit v1.2.3 From 9f2b8a393a19dad35db964d0f6ee78e8b15cafa5 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 12 Oct 2016 20:27:08 +0000 Subject: Using a pointer as a property map is deprecated in boost. Fixes the review git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alpha_complex_create_complex@1714 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 09c2eb41ce80813afb950e5712e5aefa5c6bfd34 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 8 +++++--- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 69142a58..0c0dfc59 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -187,9 +187,11 @@ class Alpha_complex { std::vector indices(boost::counting_iterator(0), boost::counting_iterator(point_cloud.size())); - // Sort indices considering CGAL spatial sort - typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; - spatial_sort(indices.begin(), indices.end(), Search_traits_d(&(point_cloud[0]))); + typedef boost::iterator_property_map::iterator, + CGAL::Identity_property_map> Point_property_map; + typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; + + CGAL::spatial_sort(indices.begin(), indices.end(), Search_traits_d(std::begin(point_cloud))); typename Delaunay_triangulation::Full_cell_handle hint; for (auto index : indices) { diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index b03851d1..fc53eeeb 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -4,7 +4,7 @@ * * Author(s): Vincent Rouvreau * - * Copyright (C) 2015 INRIA Saclay (France) + * 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 -- cgit v1.2.3 From 30e538a98919004e36b3b382017884486919cb6e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 13 Oct 2016 06:48:12 +0000 Subject: Add CGAL::Identity_property_map proper include. Was not working with CGAL < 4.9 git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1718 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8a42c2cfe003e18066f49e526048c020da8d7269 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 0c0dfc59..f2a222c1 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -33,6 +33,7 @@ #include #include #include +#include // for CGAL::Identity_property_map #include #include -- cgit v1.2.3 From 7afd5cfa01045e52f2b69935b61418beee19f2db Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 13 Oct 2016 08:25:56 +0000 Subject: Fix cpplint git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1725 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d56056e39c28b013ef71b87aae055502bd86314e --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index f2a222c1..1ce6267d 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -191,7 +191,7 @@ class Alpha_complex { typedef boost::iterator_property_map::iterator, CGAL::Identity_property_map> Point_property_map; typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; - + CGAL::spatial_sort(indices.begin(), indices.end(), Search_traits_d(std::begin(point_cloud))); typename Delaunay_triangulation::Full_cell_handle hint; -- cgit v1.2.3 From 1839d09009b10ce3c62770e082a4d7816d991e14 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 14 Oct 2016 08:51:18 +0000 Subject: Fix Alpha complex UT for limit case git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1727 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2c5c93e0a4d78fc2441de966aebac72ba9419da8 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 82 ++++++++++++---------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 79 +++++++++++++-------- 2 files changed, 94 insertions(+), 67 deletions(-) (limited to 'src/Alpha_complex/include/gudhi/Alpha_complex.h') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 1ce6267d..9d5a9bad 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -171,35 +171,58 @@ class Alpha_complex { return vertex_handle_to_iterator_.at(vertex)->point(); } + /** \brief number_of_vertices returns the number of vertices (same as the number of points). + * + * @return The number of vertices. + */ + const std::size_t number_of_vertices() const { + return vertex_handle_to_iterator_.size(); + } + private: template void init_from_range(const InputPointRange& points) { auto first = std::begin(points); auto last = std::end(points); - // point_dimension function initialization - Point_Dimension point_dimension = kernel_.point_dimension_d_object(); - - // Delaunay triangulation is point dimension. - triangulation_ = new Delaunay_triangulation(point_dimension(*first)); - - std::vector point_cloud(first, last); - // Creates a vector {0, 1, ..., N-1} - std::vector indices(boost::counting_iterator(0), - boost::counting_iterator(point_cloud.size())); - - typedef boost::iterator_property_map::iterator, - CGAL::Identity_property_map> Point_property_map; - typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; - - CGAL::spatial_sort(indices.begin(), indices.end(), Search_traits_d(std::begin(point_cloud))); - - typename Delaunay_triangulation::Full_cell_handle hint; - for (auto index : indices) { - typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(point_cloud[index], hint); - // Save index value as data to retrieve it after insertion - pos->data() = index; - hint = pos->full_cell(); + if (first != last) { + // point_dimension function initialization + Point_Dimension point_dimension = kernel_.point_dimension_d_object(); + + // Delaunay triangulation is point dimension. + triangulation_ = new Delaunay_triangulation(point_dimension(*first)); + + std::vector point_cloud(first, last); + + // Creates a vector {0, 1, ..., N-1} + std::vector indices(boost::counting_iterator(0), + boost::counting_iterator(point_cloud.size())); + + typedef boost::iterator_property_map::iterator, + CGAL::Identity_property_map> Point_property_map; + typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; + + CGAL::spatial_sort(indices.begin(), indices.end(), Search_traits_d(std::begin(point_cloud))); + + typename Delaunay_triangulation::Full_cell_handle hint; + for (auto index : indices) { + typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(point_cloud[index], hint); + // Save index value as data to retrieve it after insertion + pos->data() = index; + hint = pos->full_cell(); + } + // -------------------------------------------------------------------------------------------- + // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa + // Loop on triangulation vertices list + for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { + if (!triangulation_->is_infinite(*vit)) { +#ifdef DEBUG_TRACES + std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl; +#endif // DEBUG_TRACES + vertex_handle_to_iterator_.emplace(vit->data(), vit); + } + } + // -------------------------------------------------------------------------------------------- } } @@ -247,19 +270,6 @@ class Alpha_complex { complex.set_dimension(triangulation_->maximal_dimension()); - // -------------------------------------------------------------------------------------------- - // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa - // Loop on triangulation vertices list - for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { - if (!triangulation_->is_infinite(*vit)) { -#ifdef DEBUG_TRACES - std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl; -#endif // DEBUG_TRACES - vertex_handle_to_iterator_.emplace(vit->data(), vit); - } - } - // -------------------------------------------------------------------------------------------- - // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list if (triangulation_->number_of_vertices() > 0) { diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index c3be0715..7380547f 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -36,12 +36,17 @@ // to construct a simplex_tree from Delaunay_triangulation #include #include +#include // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d; +// Use static dimension_tag for the user not to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel_s; // The triangulation uses the default instantiation of the TriangulationDataStructure template parameter -BOOST_AUTO_TEST_CASE(ALPHA_DOC_OFF_file) { +typedef boost::mpl::list 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 @@ -52,7 +57,11 @@ BOOST_AUTO_TEST_CASE(ALPHA_DOC_OFF_file) { std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << max_alpha_square_value << "==========" << std::endl; - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name); + + std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_file.number_of_vertices() + << std::endl; + BOOST_CHECK(alpha_complex_from_file.number_of_vertices() == 7); Gudhi::Simplex_tree<> simplex_tree_60; BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_60, max_alpha_square_value)); @@ -60,6 +69,10 @@ BOOST_AUTO_TEST_CASE(ALPHA_DOC_OFF_file) { std::cout << "simplex_tree_60.dimension()=" << simplex_tree_60.dimension() << std::endl; BOOST_CHECK(simplex_tree_60.dimension() == 2); + std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_file.number_of_vertices() + << std::endl; + BOOST_CHECK(alpha_complex_from_file.number_of_vertices() == 7); + std::cout << "simplex_tree_60.num_vertices()=" << simplex_tree_60.num_vertices() << std::endl; BOOST_CHECK(simplex_tree_60.num_vertices() == 7); @@ -87,13 +100,12 @@ bool are_almost_the_same(float a, float b) { return std::fabs(a - b) < std::numeric_limits::epsilon(); } -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Kernel_s; -typedef Kernel_s::Point_d Point; -typedef std::vector Vector_of_points; - +// Use static dimension_tag for the user not to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Kernel_4; +typedef Kernel_4::Point_d Point_4; +typedef std::vector Vector_4_Points; -bool is_point_in_list(Vector_of_points points_list, Point point) { +bool is_point_in_list(Vector_4_Points points_list, Point_4 point) { for (auto& point_in_list : points_list) { if (point_in_list == point) { return true; // point found @@ -106,26 +118,30 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // ---------------------------------------------------------------------------- // Init of a list of points // ---------------------------------------------------------------------------- - Vector_of_points points; + Vector_4_Points points; std::vector coords = { 0.0, 0.0, 0.0, 1.0 }; - points.push_back(Point(coords.begin(), coords.end())); + points.push_back(Point_4(coords.begin(), coords.end())); coords = { 0.0, 0.0, 1.0, 0.0 }; - points.push_back(Point(coords.begin(), coords.end())); + points.push_back(Point_4(coords.begin(), coords.end())); coords = { 0.0, 1.0, 0.0, 0.0 }; - points.push_back(Point(coords.begin(), coords.end())); + points.push_back(Point_4(coords.begin(), coords.end())); coords = { 1.0, 0.0, 0.0, 0.0 }; - points.push_back(Point(coords.begin(), coords.end())); + points.push_back(Point_4(coords.begin(), coords.end())); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); std::cout << "========== Alpha_complex_from_points ==========" << std::endl; Gudhi::Simplex_tree<> simplex_tree; BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree)); + std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_points.number_of_vertices() + << std::endl; + BOOST_CHECK(alpha_complex_from_points.number_of_vertices() == points.size()); + // Another way to check num_simplices std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; int num_simplices = 0; @@ -167,22 +183,22 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { } } - Point p0 = alpha_complex_from_points.get_point(0); + Point_4 p0 = alpha_complex_from_points.get_point(0); std::cout << "alpha_complex_from_points.get_point(0)=" << p0 << std::endl; BOOST_CHECK(4 == p0.dimension()); BOOST_CHECK(is_point_in_list(points, p0)); - Point p1 = alpha_complex_from_points.get_point(1); + Point_4 p1 = alpha_complex_from_points.get_point(1); std::cout << "alpha_complex_from_points.get_point(1)=" << p1 << std::endl; BOOST_CHECK(4 == p1.dimension()); BOOST_CHECK(is_point_in_list(points, p1)); - Point p2 = alpha_complex_from_points.get_point(2); + Point_4 p2 = alpha_complex_from_points.get_point(2); std::cout << "alpha_complex_from_points.get_point(2)=" << p2 << std::endl; BOOST_CHECK(4 == p2.dimension()); BOOST_CHECK(is_point_in_list(points, p2)); - Point p3 = alpha_complex_from_points.get_point(3); + Point_4 p3 = alpha_complex_from_points.get_point(3); std::cout << "alpha_complex_from_points.get_point(3)=" << p3 << std::endl; BOOST_CHECK(4 == p3.dimension()); BOOST_CHECK(is_point_in_list(points, p3)); @@ -236,34 +252,35 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { } -// This test crashes on Windows (32 and 64)) -#ifndef _WIN32 -BOOST_AUTO_TEST_CASE(Alpha_complex_from_empty_points) { +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_empty_points, TestedKernel, list_of_kernel_variants) { + std::cout << "========== Alpha_complex_from_empty_points ==========" << std::endl; + // ---------------------------------------------------------------------------- - // Init of a list of points + // Init of an empty list of points // ---------------------------------------------------------------------------- - Vector_of_points points; + std::vector points; // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); - std::cout << "========== Alpha_complex_from_empty_points ==========" << std::endl; + // 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)); + BOOST_CHECK(!alpha_complex_from_points.create_complex(simplex_tree)); + std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_points.number_of_vertices() + << std::endl; + BOOST_CHECK(alpha_complex_from_points.number_of_vertices() == points.size()); + std::cout << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl; BOOST_CHECK(simplex_tree.num_simplices() == 0); std::cout << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl; - BOOST_CHECK(simplex_tree.dimension() == 4); + BOOST_CHECK(simplex_tree.dimension() == -1); std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; BOOST_CHECK(simplex_tree.num_vertices() == 0); - - // Test to the limit - BOOST_CHECK_THROW (alpha_complex_from_points.get_point(0), std::out_of_range); } -#endif -- cgit v1.2.3