From f9c64afdd4c0fcfa291e59ea179b7272ec5932af Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 3 Apr 2015 08:43:14 +0000 Subject: Build was failed (no propagation of -std=c++11) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@541 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0848ecde6740c37ba0f2e8a69890908a065b5228 --- src/Alpha_shapes/example/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Alpha_shapes/example/CMakeLists.txt b/src/Alpha_shapes/example/CMakeLists.txt index fb94ca05..dab3861c 100644 --- a/src/Alpha_shapes/example/CMakeLists.txt +++ b/src/Alpha_shapes/example/CMakeLists.txt @@ -13,7 +13,6 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - include_directories (BEFORE "../../include") add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) -- cgit v1.2.3 From 7f8b2a07a463fdcec12430abe2119d4f86a72517 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 29 May 2015 10:34:14 +0000 Subject: Alpha_shapes filtration value git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@599 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 303ed34da0718312e4bab3f50b7196acded94cec --- src/Alpha_shapes/example/CMakeLists.txt | 9 +- .../example/Delaunay_triangulation_off_rw.cpp | 2 +- .../Simplex_tree_from_delaunay_triangulation.cpp | 32 +----- src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 89 +++++++++++----- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 113 +++++++-------------- src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp | 2 +- src/Alpha_shapes/test/CMakeLists.txt | 6 +- 7 files changed, 112 insertions(+), 141 deletions(-) diff --git a/src/Alpha_shapes/example/CMakeLists.txt b/src/Alpha_shapes/example/CMakeLists.txt index dab3861c..582a9322 100644 --- a/src/Alpha_shapes/example/CMakeLists.txt +++ b/src/Alpha_shapes/example/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIAlphaShapesExample) -# need CGAL 4.6 -# cmake -DCGAL_DIR=~/workspace/CGAL-4.6-beta1 ../../.. +# need CGAL 4.7 +# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) message(STATUS "CGAL version: ${CGAL_VERSION}.") include( ${CGAL_USE_FILE} ) @@ -13,12 +13,13 @@ if(CGAL_FOUND) if (EIGEN3_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}) else() diff --git a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp index 03f6440d..a31c44ab 100644 --- a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp +++ b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp @@ -63,7 +63,7 @@ int main(int argc, char **argv) { T dt(dimension); std::string offFileName(argv[1]); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(offFileName, dt, true, true); + Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(offFileName, dt); if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << offFileName << std::endl; exit(-1); // ----- >> diff --git a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp index 3a17b519..11079a03 100644 --- a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -48,50 +48,24 @@ typedef CGAL::Delaunay_triangulation T; // TriangulationDataStructure template parameter void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off dimension" << std::endl; + std::cerr << "Usage: " << progName << " filename.off" << std::endl; exit(-1); // ----- >> } int main(int argc, char **argv) { - if (argc != 3) { + if (argc != 2) { 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]); - } - - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a Delaunay triangulation - // - // ---------------------------------------------------------------------------- - T dt(dimension); std::string off_file_name(argv[1]); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt, false, false); - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << off_file_name << std::endl; - exit(-1); // ----- >> - } - - std::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; - std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; - - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_dt(dt); - //std::cout << alpha_shapes_from_dt << std::endl; - // ---------------------------------------------------------------------------- // // Init of an alpha-shape from a OFF file // // ---------------------------------------------------------------------------- - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name, dimension); + Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); //std::cout << alpha_shapes_from_file << std::endl; std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index b8efdb4d..6f290938 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -47,6 +47,8 @@ namespace Gudhi { namespace alphashapes { +#define Kinit(f) =k.f() + /** \defgroup alpha_shapes Alpha shapes in dimension N *
Implementations:
@@ -86,16 +88,22 @@ class Alpha_shapes { */ 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 typeVectorPoint; + private: /** \brief Upper bound on the simplex tree of the simplicial complex.*/ Gudhi::Simplex_tree<> _st; public: - Alpha_shapes(std::string off_file_name, int dimension) { - Delaunay_triangulation dt(dimension); - Gudhi::alphashapes::Delaunay_triangulation_off_reader - off_reader(off_file_name, dt, true, true); + Alpha_shapes(std::string off_file_name) { + // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function + Delaunay_triangulation dt(3); + Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << off_file_name << std::endl; exit(-1); // ----- >> @@ -120,45 +128,70 @@ class Alpha_shapes { template void init(T triangulation) { _st.set_dimension(triangulation.maximal_dimension()); - _st.set_filtration(0.0); - // triangulation points list - for (auto vit = triangulation.finite_vertices_begin(); - vit != triangulation.finite_vertices_end(); ++vit) { - typeVectorVertex vertexVector; - Vertex_handle vertexHdl = std::distance(triangulation.finite_vertices_begin(), vit); - vertexVector.push_back(vertexHdl); + Filtration_value filtration_max = 0.0; - // Insert each point in the simplex tree - _st.insert_simplex(vertexVector, 0.0); + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + // triangulation full cells list + for (auto cit = triangulation.full_cells_begin(); cit != triangulation.full_cells_end(); ++cit) { + typeVectorVertex vertexVector; + typeVectorPoint pointVector; + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + if (!triangulation.is_infinite(*vit)) { + // Vector of vertex construction for simplex_tree structure + // Vertex handle is distance - 1 + Vertex_handle vertexHdl = std::distance(triangulation.vertices_begin(), *vit) - 1; + // infinite cell is -1 for infinite + vertexVector.push_back(vertexHdl); + // Vector of points for alpha_shapes filtration value computation + pointVector.push_back((*vit)->point()); #ifdef DEBUG_TRACES - std::cout << "P" << vertexHdl << ":"; - for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { - std::cout << *Coord << " "; + std::cout << "Point "; + for (auto Coord = (*vit)->point().cartesian_begin(); Coord != (*vit)->point().cartesian_end(); ++Coord) { + std::cout << *Coord << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + } } - std::cout << std::endl; + Filtration_value alpha_shapes_filtration = 0.0; + + if (!triangulation.is_infinite(cit)) { + alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); +#ifdef DEBUG_TRACES + std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; #endif // DEBUG_TRACES - } - // triangulation finite full cells list - for (auto cit = triangulation.finite_full_cells_begin(); - cit != triangulation.finite_full_cells_end(); ++cit) { - typeVectorVertex vertexVector; - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - // Vertex handle is distance - 1 - Vertex_handle vertexHdl = std::distance(triangulation.vertices_begin(), *vit) - 1; - vertexVector.push_back(vertexHdl); + } else { + Filtration_value tmp_filtration = 0.0; + bool is_gab = true; + for (auto vit = triangulation.finite_vertices_begin(); vit != triangulation.finite_vertices_end(); ++vit) { + if (CGAL::ON_UNBOUNDED_SIDE != is_gabriel(pointVector.begin(), pointVector.end(), vit->point())) { + is_gab = false; + // TODO(VR) : Compute minimum + + } + } + if (true == is_gab) { + alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); +#ifdef DEBUG_TRACES + std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; +#endif // DEBUG_TRACES + } } // Insert each point in the simplex tree - _st.insert_simplex_and_subfaces(vertexVector, 0.0); + _st.insert_simplex_and_subfaces(vertexVector, alpha_shapes_filtration); #ifdef DEBUG_TRACES - std::cout << "C" << std::distance(triangulation.finite_full_cells_begin(), cit) << ":"; + std::cout << "C" << std::distance(triangulation.full_cells_begin(), cit) << ":"; for (auto value : vertexVector) { std::cout << value << ' '; } std::cout << std::endl; #endif // DEBUG_TRACES } + _st.set_filtration(filtration_max); } public: diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h index 693b393e..3215c8f6 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h @@ -36,27 +36,35 @@ namespace alphashapes { *@brief Off reader visitor with flag that can be passed to Off_reader to read a Delaunay_triangulation_complex. */ template -class Delaunay_triangulation_off_flag_visitor_reader { +class Delaunay_triangulation_off_visitor_reader { Complex& complex_; typedef typename Complex::Point Point; - const bool load_only_points_; - public: - explicit Delaunay_triangulation_off_flag_visitor_reader(Complex& complex, bool load_only_points = false) : - complex_(complex), - load_only_points_(load_only_points) { } + + explicit Delaunay_triangulation_off_visitor_reader(Complex& complex) : + complex_(complex) { } void init(int dim, int num_vertices, int num_faces, int num_edges) { #ifdef DEBUG_TRACES - std::cout << "init" << std::endl; + 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_.set_current_dimension(dim); } void point(const std::vector& point) { #ifdef DEBUG_TRACES - std::cout << "p "; - for (auto coordinate: point) { + std::cout << "Delaunay_triangulation_off_visitor_reader::point "; + for (auto coordinate : point) { std::cout << coordinate << " | "; } std::cout << std::endl; @@ -65,62 +73,19 @@ class Delaunay_triangulation_off_flag_visitor_reader { } void maximal_face(const std::vector& face) { - // For alpha shapes, only points are read - } - - void done() { + // For Delaunay Triangulation, only points are read #ifdef DEBUG_TRACES - std::cout << "done" << std::endl; -#endif // DEBUG_TRACES - } -}; - -/** - *@brief Off reader visitor that can be passed to Off_reader to read a Delaunay_triangulation_complex. - */ -template -class Delaunay_triangulation_off_visitor_reader { - Complex& complex_; - // typedef typename Complex::Vertex_handle Vertex_handle; - // typedef typename Complex::Simplex_handle Simplex_handle; - typedef typename Complex::Point Point; - - const bool load_only_points_; - std::vector points_; - // std::vector maximal_faces_; - - public: - explicit Delaunay_triangulation_off_visitor_reader(Complex& complex, bool load_only_points = false) : - complex_(complex), - load_only_points_(load_only_points) { } - - void init(int dim, int num_vertices, int num_faces, int num_edges) { -#ifdef DEBUG_TRACES - std::cout << "init - " << num_vertices << std::endl; -#endif // DEBUG_TRACES - // maximal_faces_.reserve(num_faces); - points_.reserve(num_vertices); - } - - void point(const std::vector& point) { -#ifdef DEBUG_TRACES - std::cout << "p "; - for (auto coordinate: point) { - std::cout << coordinate << " | "; + std::cout << "Delaunay_triangulation_off_visitor_reader::face "; + for (auto vertex : face) { + std::cout << vertex << " | "; } std::cout << std::endl; #endif // DEBUG_TRACES - points_.emplace_back(Point(point.size(), point.begin(), point.end())); - } - - void maximal_face(const std::vector& face) { - // For alpha shapes, only points are read } void done() { - complex_.insert(points_.begin(), points_.end()); #ifdef DEBUG_TRACES - std::cout << "done" << std::endl; + std::cout << "Delaunay_triangulation_off_visitor_reader::done" << std::endl; #endif // DEBUG_TRACES } }; @@ -131,27 +96,23 @@ class Delaunay_triangulation_off_visitor_reader { 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, Complex& read_complex, bool read_only_points = false, - bool is_flag = false) : valid_(false) { + Delaunay_triangulation_off_reader(const std::string & name_file, Complex& read_complex) : valid_(false) { std::ifstream stream(name_file); if (stream.is_open()) { - if (is_flag) { - // For alpha shapes, only points are read - Delaunay_triangulation_off_flag_visitor_reader off_visitor(read_complex, true); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - } else { - // For alpha shapes, only points are read - Delaunay_triangulation_off_visitor_reader off_visitor(read_complex, true); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - } + Delaunay_triangulation_off_visitor_reader off_visitor(read_complex); + Off_reader off_reader(stream); + valid_ = off_reader.read(off_visitor); + } else { + std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << + name_file << std::endl; } + } /** @@ -160,7 +121,7 @@ class Delaunay_triangulation_off_reader { bool is_valid() const { return valid_; } - + private: bool valid_; }; @@ -168,6 +129,7 @@ class Delaunay_triangulation_off_reader { template class Delaunay_triangulation_off_writer { public: + /** * name_file : file where the off will be written * save_complex : complex that be outputted in the file @@ -191,7 +153,7 @@ class Delaunay_triangulation_off_writer { // Finite cells list for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.finite_full_cells_end(); ++cit) { - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension + stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { auto vertexHdl = *vit; // auto vertexHdl = std::distance(save_complex.vertices_begin(), *vit) - 1; @@ -201,13 +163,14 @@ class Delaunay_triangulation_off_writer { } stream.close(); } else { - std::cerr << "could not open file " << name_file << std::endl; + std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << + name_file << std::endl; } } }; -} // namespace alphashapes +} // namespace alphashapes -} // namespace Gudhi +} // namespace Gudhi #endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp b/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp index a90704b6..d5db3bfa 100644 --- a/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp +++ b/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { std::string off_file_name("S8_10.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt, true, true); + Gudhi::alphashapes::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()); diff --git a/src/Alpha_shapes/test/CMakeLists.txt b/src/Alpha_shapes/test/CMakeLists.txt index a48c1a8f..3cf97b71 100644 --- a/src/Alpha_shapes/test/CMakeLists.txt +++ b/src/Alpha_shapes/test/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIAlphaShapesTest) -# need CGAL 4.6 -# cmake -DCGAL_DIR=~/workspace/CGAL-4.6-beta1 ../../.. +# need CGAL 4.7 +# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) message(STATUS "CGAL version: ${CGAL_VERSION}.") include( ${CGAL_USE_FILE} ) -- cgit v1.2.3 From 2445eaa9d34272832a8edd680e30c2b8b3298242 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 9 Jun 2015 11:20:14 +0000 Subject: Checkin for rollback purpose. Compiles but do not work. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@607 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e163ca16ebc76a13cec21bf881fe3b03e0617711 --- .../example/Delaunay_triangulation_off_rw.cpp | 4 +- .../Simplex_tree_from_delaunay_triangulation.cpp | 2 +- src/Alpha_shapes/example/alphashapedoc.off | 10 ++++ src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 45 ++++++++++-------- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 54 +++++++++++++++++----- 5 files changed, 80 insertions(+), 35 deletions(-) create mode 100755 src/Alpha_shapes/example/alphashapedoc.off diff --git a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp index a31c44ab..6c9fcdab 100644 --- a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp +++ b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp @@ -82,7 +82,7 @@ int main(int argc, char **argv) { } std::cout << std::endl;*/ - int i = 0, j = 0; + /*int i = 0, j = 0; typedef T::Full_cell_iterator Full_cell_iterator; typedef T::Facet Facet; @@ -96,7 +96,7 @@ int main(int argc, char **argv) { } std::cout << "There are " << i << " facets on the convex hull." << std::endl; std::cout << "There are " << j << " facets not on the convex hull." << std::endl; - +*/ std::string offOutputFile("out.off"); Gudhi::alphashapes::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); diff --git a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp index 11079a03..0a24fb56 100644 --- a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -66,12 +66,12 @@ int main(int argc, char **argv) { // // ---------------------------------------------------------------------------- Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); - //std::cout << alpha_shapes_from_file << std::endl; std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; + //std::cout << alpha_shapes_from_file << std::endl; return 0; } \ No newline at end of file diff --git a/src/Alpha_shapes/example/alphashapedoc.off b/src/Alpha_shapes/example/alphashapedoc.off new file mode 100755 index 00000000..bb790193 --- /dev/null +++ b/src/Alpha_shapes/example/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_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index 6f290938..6de675f6 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -96,13 +96,13 @@ class Alpha_shapes { private: /** \brief Upper bound on the simplex tree of the simplicial complex.*/ - Gudhi::Simplex_tree<> _st; + Gudhi::Simplex_tree<> st_; public: - Alpha_shapes(std::string off_file_name) { + Alpha_shapes(std::string& off_file_name) { // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function - Delaunay_triangulation dt(3); + Delaunay_triangulation dt(2); Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << off_file_name << std::endl; @@ -117,7 +117,7 @@ class Alpha_shapes { } template - Alpha_shapes(T triangulation) { + Alpha_shapes(T& triangulation) { init(triangulation); } @@ -126,8 +126,8 @@ class Alpha_shapes { private: template - void init(T triangulation) { - _st.set_dimension(triangulation.maximal_dimension()); + void init(T& triangulation) { + st_.set_dimension(triangulation.maximal_dimension()); Filtration_value filtration_max = 0.0; Kernel k; @@ -148,11 +148,11 @@ class Alpha_shapes { // Vector of points for alpha_shapes filtration value computation pointVector.push_back((*vit)->point()); #ifdef DEBUG_TRACES - std::cout << "Point "; + /*std::cout << "Point "; for (auto Coord = (*vit)->point().cartesian_begin(); Coord != (*vit)->point().cartesian_end(); ++Coord) { std::cout << *Coord << " | "; } - std::cout << std::endl; + std::cout << std::endl;*/ #endif // DEBUG_TRACES } } @@ -161,66 +161,71 @@ class Alpha_shapes { if (!triangulation.is_infinite(cit)) { alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); #ifdef DEBUG_TRACES - std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; + //std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; #endif // DEBUG_TRACES } else { Filtration_value tmp_filtration = 0.0; bool is_gab = true; - for (auto vit = triangulation.finite_vertices_begin(); vit != triangulation.finite_vertices_end(); ++vit) { + /*for (auto vit = triangulation.finite_vertices_begin(); vit != triangulation.finite_vertices_end(); ++vit) { if (CGAL::ON_UNBOUNDED_SIDE != is_gabriel(pointVector.begin(), pointVector.end(), vit->point())) { is_gab = false; // TODO(VR) : Compute minimum } - } + }*/ if (true == is_gab) { alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); #ifdef DEBUG_TRACES - std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; + //std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; #endif // DEBUG_TRACES } } // Insert each point in the simplex tree - _st.insert_simplex_and_subfaces(vertexVector, alpha_shapes_filtration); + st_.insert_simplex_and_subfaces(vertexVector, alpha_shapes_filtration); #ifdef DEBUG_TRACES std::cout << "C" << std::distance(triangulation.full_cells_begin(), cit) << ":"; for (auto value : vertexVector) { std::cout << value << ' '; } - std::cout << std::endl; + std::cout << " | alpha=" << alpha_shapes_filtration << std::endl; #endif // DEBUG_TRACES } - _st.set_filtration(filtration_max); + st_.set_filtration(filtration_max); + } + + template + void recursive_init(T& triangulation, typeVectorVertex vertexVector) { + } public: /** \brief Returns the number of vertices in the complex. */ size_t num_vertices() { - return _st.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(); + return st_.num_simplices(); } /** \brief Returns an upper bound on the dimension of the simplicial complex. */ int dimension() { - return _st.dimension(); + return st_.dimension(); } /** \brief Returns an upper bound of the filtration values of the simplices. */ Filtration_value filtration() { - return _st.filtration(); + return st_.filtration(); } friend std::ostream& operator<<(std::ostream& os, const Alpha_shapes& alpha_shape) { // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor - Gudhi::Simplex_tree<> st = alpha_shape._st; + Gudhi::Simplex_tree<> st = alpha_shape.st_; os << st << std::endl; return os; } diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h index 3215c8f6..1413ad89 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h @@ -25,6 +25,7 @@ #include #include #include +#include // std::distance #include "gudhi/Off_reader.h" @@ -47,7 +48,7 @@ class Delaunay_triangulation_off_visitor_reader { 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=" << + 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) { @@ -121,7 +122,7 @@ class Delaunay_triangulation_off_reader { bool is_valid() const { return valid_; } - + private: bool valid_; }; @@ -138,10 +139,19 @@ class Delaunay_triangulation_off_writer { Delaunay_triangulation_off_writer(const std::string & name_file, const Complex& save_complex) { std::ofstream stream(name_file); if (stream.is_open()) { - // OFF header - stream << "OFF" << std::endl; - // no endl on next line - don't know why... - stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; + if (save_complex.current_dimension() == 3) { + // OFF header + stream << "OFF" << std::endl; + // no endl on next line - don't know why... + stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; + } else { + // nOFF header + stream << "nOFF" << std::endl; + // no endl on next line - don't know why... + stream << save_complex.current_dimension() << " " << save_complex.number_of_vertices() << " " << + save_complex.number_of_finite_full_cells() << " 0"; + + } // Points list for (auto vit = save_complex.vertices_begin(); vit != save_complex.vertices_end(); ++vit) { @@ -151,16 +161,36 @@ class Delaunay_triangulation_off_writer { stream << std::endl; } - // Finite cells list - for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.finite_full_cells_end(); ++cit) { - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension + + for (auto cit = save_complex.full_cells_begin(); cit != save_complex.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) { - auto vertexHdl = *vit; - // auto vertexHdl = std::distance(save_complex.vertices_begin(), *vit) - 1; - // stream << std::distance(save_complex.vertices_begin(), *(vit)) - 1 << " "; + // Vector of vertex construction for simplex_tree structure + // Vertex handle is distance - 1 + //int vertexHdl = std::distance(save_complex.vertices_begin(), *vit); + // infinite cell is -1 for infinite + //vertexVector.push_back(vertexHdl); + // Vector of points for alpha_shapes filtration value computation } stream << std::endl; } + + + + + + /* + // Finite cells list + for (auto cit = save_complex.full_cells_begin(); cit != save_complex.full_cells_end(); ++cit) { + stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + //auto vertexHdl = *vit; + auto vertexHdl = std::distance(save_complex.vertices_begin(), vit) - 1; + // stream << std::distance(save_complex.vertices_begin(), *(vit)) - 1 << " "; + } + stream << std::endl; + }*/ stream.close(); } else { std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << -- cgit v1.2.3 From 844d6205eb6705935417b0ab45b0c71230bd9ed6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 10 Jun 2015 15:00:47 +0000 Subject: alpha shapes computation in progress but not finished git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@608 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d52ab152c6f765721657eaf5cbf07303a6c6c515 --- src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 69 +++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index 6de675f6..841c883a 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -42,6 +42,8 @@ #include #include #include +#include +#include namespace Gudhi { @@ -79,6 +81,8 @@ class Alpha_shapes { /** \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; + // From CGAL /** \brief Kernel for the Delaunay_triangulation. * Dimension can be set dynamically. @@ -126,13 +130,13 @@ class Alpha_shapes { private: template - void init(T& triangulation) { + void initial_init(T& triangulation) { st_.set_dimension(triangulation.maximal_dimension()); Filtration_value filtration_max = 0.0; Kernel k; Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); // triangulation full cells list for (auto cit = triangulation.full_cells_begin(); cit != triangulation.full_cells_end(); ++cit) { @@ -195,8 +199,67 @@ class Alpha_shapes { } template - void recursive_init(T& triangulation, typeVectorVertex vertexVector) { + void init(T& triangulation) { + st_.set_dimension(triangulation.maximal_dimension()); + Filtration_value filtration_max = 0.0; + Filtration_value filtration_unknown = std::numeric_limits::quiet_NaN(); + + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + + std::map points_to_vh; + // Start to insert at handle = 0 - default integer value + Vertex_handle vertex_handle = Vertex_handle(); + // Loop on triangulation vertices list + for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { + points_to_vh[vit->point()] = vertex_handle; + vertex_handle++; + } + + // Loop on triangulation finite full cells list + for (auto cit = triangulation.finite_full_cells_begin(); cit != triangulation.finite_full_cells_end(); ++cit) { + typeVectorVertex vertexVector; + typeVectorPoint pointVector; + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { +#ifdef DEBUG_TRACES + std::cout << "points_to_vh=" << points_to_vh[(*vit)->point()] << std::endl; +#endif // DEBUG_TRACES + // Vector of vertex construction for simplex_tree structure + vertexVector.push_back(points_to_vh[(*vit)->point()]); + // Vector of points for alpha_shapes filtration value computation + pointVector.push_back((*vit)->point()); + } + Filtration_value alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); + // Insert each simplex and its subfaces in the simplex tree - filtration is NaN + std::pair insert_result = st_.insert_simplex_and_subfaces(vertexVector, filtration_unknown); + + if (insert_result.second == true) { + // Only top-level cell must have the correct alpha value + st_.assign_filtration(insert_result.first, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << "alpha_shapes_filtration=" << st_.filtration(insert_result.first) << std::endl; +#endif // DEBUG_TRACES + + filtration_max = fmax(filtration_max, alpha_shapes_filtration); + } + } + // Loop on triangulation finite full cells list + for (auto f_simplex : st_.skeleton_simplex_range(st_.dimension() - 1)) { + std::cout << "vertex = [" << st_.filtration(f_simplex) << "] "; + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; + if (st_.filtration(f_simplex) == filtration_unknown) + st_.assign_filtration(f_simplex, filtration_max); // TODO(VR) Compute filtration value from simplex + } + +#ifdef DEBUG_TRACES + std::cout << "filtration_max=" << filtration_max << std::endl; +#endif // DEBUG_TRACES + st_.set_filtration(filtration_max); } public: -- cgit v1.2.3 From 24ed9e6896b0aafcaeaf19e5d2970915282fa7b7 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 12 Jun 2015 10:47:38 +0000 Subject: delaunay off reader/writer fix. alpha complex algo seems ok. tests are Nok. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@611 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 37cea3b33d783a77a23fa3a54a1bee106508d981 --- .../example/Delaunay_triangulation_off_rw.cpp | 38 +----- src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 109 +++++++++++++-- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 36 ++--- src/Simplex_tree/include/gudhi/Simplex_tree.h | 150 +++++++++++++++++---- src/common/include/gudhi/Off_reader.h | 4 +- 5 files changed, 242 insertions(+), 95 deletions(-) diff --git a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp index 6c9fcdab..fe889ec0 100644 --- a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp +++ b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp @@ -44,12 +44,12 @@ typedef CGAL::Delaunay_triangulation T; // TriangulationDataStructure template parameter void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off dimension" << std::endl; + std::cerr << "Usage: " << progName << " inputFile.off dimension outputFile.off" << std::endl; exit(-1); // ----- >> } int main(int argc, char **argv) { - if (argc != 3) { + if (argc != 4) { std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; usage(argv[0]); } @@ -68,37 +68,11 @@ int main(int argc, char **argv) { 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::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; - std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; - - // Points list - /*for (T::Vertex_iterator vit = dt.vertices_begin(); vit != dt.vertices_end(); ++vit) { - for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { - std::cout << *Coord << " "; - } - std::cout << std::endl; - } - std::cout << std::endl;*/ - - /*int i = 0, j = 0; - typedef T::Full_cell_iterator Full_cell_iterator; - typedef T::Facet Facet; - - for (Full_cell_iterator cit = dt.full_cells_begin(); cit != dt.full_cells_end(); ++cit) { - if (!dt.is_infinite(cit)) { - j++; - continue; - } - Facet fct(cit, cit->index(dt.infinite_vertex())); - i++; - } - std::cout << "There are " << i << " facets on the convex hull." << std::endl; - std::cout << "There are " << j << " facets not on the convex hull." << std::endl; -*/ - - std::string offOutputFile("out.off"); + std::string outFileName(argv[3]); + std::string offOutputFile(outFileName); Gudhi::alphashapes::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); return 0; diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index 841c883a..2bc8b221 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -32,6 +32,9 @@ #include #include +#include // isnan, fmax + +#include #include #include @@ -208,12 +211,14 @@ class Alpha_shapes { Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); - std::map points_to_vh; + // bimap to retrieve vertex handles from points and vice versa + typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; + bimap_points_vh points_to_vh; // Start to insert at handle = 0 - default integer value Vertex_handle vertex_handle = Vertex_handle(); // Loop on triangulation vertices list for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { - points_to_vh[vit->point()] = vertex_handle; + points_to_vh.insert(bimap_points_vh::value_type(vit->point(), vertex_handle)); vertex_handle++; } @@ -223,10 +228,10 @@ class Alpha_shapes { typeVectorPoint pointVector; for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { #ifdef DEBUG_TRACES - std::cout << "points_to_vh=" << points_to_vh[(*vit)->point()] << std::endl; + std::cout << "points_to_vh=" << points_to_vh.left.at((*vit)->point()) << std::endl; #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(points_to_vh[(*vit)->point()]); + vertexVector.push_back(points_to_vh.left.at((*vit)->point())); // Vector of points for alpha_shapes filtration value computation pointVector.push_back((*vit)->point()); } @@ -244,17 +249,99 @@ class Alpha_shapes { filtration_max = fmax(filtration_max, alpha_shapes_filtration); } } - - // Loop on triangulation finite full cells list - for (auto f_simplex : st_.skeleton_simplex_range(st_.dimension() - 1)) { - std::cout << "vertex = [" << st_.filtration(f_simplex) << "] "; + + // ### 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); +#ifdef DEBUG_TRACES + std::cout << "f_simplex_dim= " << f_simplex_dim << " - decr_dim= " << decr_dim << std::endl; +#endif // DEBUG_TRACES + if (decr_dim == f_simplex_dim) { + typeVectorPoint pointVector; +#ifdef DEBUG_TRACES + std::cout << "vertex "; +#endif // DEBUG_TRACES + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + pointVector.push_back(points_to_vh.right.at(vertex)); +#ifdef DEBUG_TRACES + std::cout << (int) 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_shapes_filtration = 0.0; + // No need to compute squared_radius on a single point - alpha is 0.0 + if (f_simplex_dim > 0) { + alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); + } + st_.assign_filtration(f_simplex, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << "From NaN to alpha_shapes_filtration=" << st_.filtration(f_simplex) << std::endl; +#endif // DEBUG_TRACES + } + + // ### Foreach Tau face of Sigma + for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { +#ifdef DEBUG_TRACES + std::cout << "Sigma "; + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << " - Tau "; + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + // insert the Tau points in a vector for is_gabriel function + typeVectorPoint pointVector; + Vertex_handle vertexForGabriel = Vertex_handle(); + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + pointVector.push_back(points_to_vh.right.at(vertex)); + } + // 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(), points_to_vh.right.at(vertex)) == pointVector.end()) { + // vertex is not found in Tau + vertexForGabriel = vertex; + // No need to continue loop + break; + } + } + // ### If filt(Tau) is not NaN + // ### or Tau is not Gabriel of Sigma + if (!isnan(st_.filtration(f_boundary)) || + !is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) + ) { + // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) + Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); + st_.assign_filtration(f_boundary, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << "From Boundary to alpha_shapes_filtration=" << st_.filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES + } + } + } + } + } + +#ifdef DEBUG_TRACES + 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; - if (st_.filtration(f_simplex) == filtration_unknown) - st_.assign_filtration(f_simplex, filtration_max); // TODO(VR) Compute filtration value from simplex } +#endif // DEBUG_TRACES #ifdef DEBUG_TRACES std::cout << "filtration_max=" << filtration_max << std::endl; @@ -286,7 +373,7 @@ class Alpha_shapes { return st_.filtration(); } - friend std::ostream& operator<<(std::ostream& os, const Alpha_shapes& alpha_shape) { + friend std::ostream& operator<<(std::ostream& os, const Alpha_shapes & alpha_shape) { // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor Gudhi::Simplex_tree<> st = alpha_shape.st_; os << st << std::endl; diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h index 1413ad89..a4e5e2fe 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h @@ -25,7 +25,7 @@ #include #include #include -#include // std::distance +#include #include "gudhi/Off_reader.h" @@ -130,6 +130,7 @@ class Delaunay_triangulation_off_reader { template class Delaunay_triangulation_off_writer { public: + typedef typename Complex::Point Point; /** * name_file : file where the off will be written @@ -153,44 +154,29 @@ class Delaunay_triangulation_off_writer { } + // 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 = save_complex.vertices_begin(); vit != save_complex.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 = save_complex.full_cells_begin(); cit != save_complex.full_cells_end(); ++cit) { + for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.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) { - // Vector of vertex construction for simplex_tree structure - // Vertex handle is distance - 1 - //int vertexHdl = std::distance(save_complex.vertices_begin(), *vit); - // infinite cell is -1 for infinite - //vertexVector.push_back(vertexHdl); - // Vector of points for alpha_shapes filtration value computation + stream << points_to_vh[(*vit)->point()] << " "; } stream << std::endl; } - - - - - - /* - // Finite cells list - for (auto cit = save_complex.full_cells_begin(); cit != save_complex.full_cells_end(); ++cit) { - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - //auto vertexHdl = *vit; - auto vertexHdl = std::distance(save_complex.vertices_begin(), vit) - 1; - // stream << std::distance(save_complex.vertices_begin(), *(vit)) - 1 << " "; - } - stream << std::endl; - }*/ stream.close(); } else { std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index b79e3c8f..32fb2f43 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -37,7 +37,6 @@ #include namespace Gudhi { - /** \defgroup simplex_tree Filtered Complexes * * A simplicial complex \f$\mathbf{K}\f$ @@ -84,8 +83,8 @@ namespace Gudhi { * */ template class Simplex_tree { @@ -245,6 +244,7 @@ class Simplex_tree { Filtration_simplex_range filtration_simplex_range() { return filtration_simplex_range(Indexing_tag()); } + /** \brief Returns a range over the vertices of a simplex. * * The order in which the vertices are visited is the decreasing order for < on Vertex_handles, @@ -316,12 +316,14 @@ class Simplex_tree { Simplex_key key(Simplex_handle sh) { return sh->second.key(); } + /** \brief Returns the simplex associated to a key. * * The filtration must be initialized. */ Simplex_handle simplex(Simplex_key key) { return filtration_vect_[key]; } + /** \brief Returns the filtration value of a simplex. * * Called on the null_simplex, returns INFINITY. */ @@ -330,12 +332,23 @@ class Simplex_tree { return sh->second.filtration(); } else { return INFINITY; - } // filtration(); } + } + } + + /** \brief Sets the filtration value of a simplex. + * + * No action if called on the null_simplex*/ + void assign_filtration(Simplex_handle sh, Filtration_value fv) { + if (sh != null_simplex()) { + sh->second.assign_filtration(fv); + } } + /** \brief Returns an upper bound of the filtration values of the simplices. */ Filtration_value filtration() { return threshold_; } + /** \brief Returns a Simplex_handle different from all Simplex_handles * associated to the simplices in the simplicial complex. * @@ -343,20 +356,24 @@ class Simplex_tree { Simplex_handle null_simplex() { return Dictionary_it(NULL); } + /** \brief Returns a key different for all keys associated to the * simplices of the simplicial complex. */ Simplex_key null_key() { return -1; } + /** \brief Returns a Vertex_handle different from all Vertex_handles associated * to the vertices of the simplicial complex. */ Vertex_handle null_vertex() { return null_vertex_; } + /** \brief Returns the number of vertices in the complex. */ size_t num_vertices() { return root_.members_.size(); } + /** \brief Returns the number of simplices in the complex. * * Does not count the empty simplex. */ @@ -376,6 +393,7 @@ class Simplex_tree { } return dim - 1; } + /** \brief Returns an upper bound on the dimension of the simplicial complex. */ int dimension() { return dimension_; @@ -423,7 +441,6 @@ class Simplex_tree { Simplex_handle find_vertex(Vertex_handle v) { return root_.members_.begin() + v; } -//{ return root_.members_.find(v); } /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. * @@ -479,7 +496,6 @@ class Simplex_tree { return res_insert; } - /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of * Vertex_handles, in the simplicial complex. * @@ -487,33 +503,35 @@ class Simplex_tree { * @param[in] filtration the filtration value assigned to the new N-simplex. */ template - void insert_simplex_and_subfaces(RandomAccessVertexRange& Nsimplex, - Filtration_value filtration = 0.0) { + std::pair insert_simplex_and_subfaces(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()]); + NsimplexMinusOne.push_back(Nsimplex[(NIndex + NListIter) % Nsimplex.size()]); } // (N-1)-Simplex recursive call - insert_simplex_and_subfaces(NsimplexMinusOne, filtration); + returned = insert_simplex_and_subfaces(NsimplexMinusOne, filtration); } // N-Simplex insert - std::pair returned = insert_simplex(Nsimplex, filtration); + returned = insert_simplex(Nsimplex, filtration); if (returned.second == true) { num_simplices_++; } } else if (Nsimplex.size() == 1) { // 1-Simplex insert - End of recursivity - std::pair returned = insert_simplex(Nsimplex, filtration); + returned = insert_simplex(Nsimplex, filtration); if (returned.second == true) { num_simplices_++; } } else { // Nothing to insert - empty vector } + return returned; } /** \brief Assign a value 'key' to the key of the simplex @@ -540,17 +558,6 @@ class Simplex_tree { return sh->second.children(); } -// void display_simplex(Simplex_handle sh) -// { -// std::cout << " " << "[" << filtration(sh) << "] "; -// for( auto vertex : simplex_vertex_range(sh) ) -// { std::cout << vertex << " "; } -// } - - // void print(Simplex_handle sh, std::ostream& os = std::cout) - // { for(auto v : simplex_vertex_range(sh)) {os << v << " ";} - // os << std::endl; } - public: /** Returns a pointer to the root nodes of the simplex tree. */ Siblings * root() { @@ -562,10 +569,12 @@ class Simplex_tree { void set_filtration(Filtration_value fil) { threshold_ = fil; } + /** Set a number of simplices for the simplicial complex. */ void set_num_simplices(const unsigned int& num_simplices) { num_simplices_ = num_simplices; } + /** Set a dimension for the simplicial complex. */ void set_dimension(int dimension) { dimension_ = dimension; @@ -623,6 +632,7 @@ class Simplex_tree { } return ((it1 == rg1.end()) && (it2 != rg2.end())); } + /** \brief StrictWeakOrdering, for the simplices, defined by the filtration. * * It corresponds to the partial order @@ -631,8 +641,7 @@ class Simplex_tree { * to be smaller. The filtration function must be monotonic. */ struct is_before_in_filtration { explicit is_before_in_filtration(Simplex_tree * st) - : st_(st) { - } + : st_(st) { } bool operator()(const Simplex_handle sh1, const Simplex_handle sh2) const { if (st_->filtration(sh1) != st_->filtration(sh2)) { @@ -708,6 +717,7 @@ class Simplex_tree { } } } + /** \brief Expands the Simplex_tree containing only its one skeleton * until dimension max_dim. * @@ -731,6 +741,7 @@ class Simplex_tree { } private: + /** \brief Recursive expansion of the simplex tree.*/ void siblings_expansion(Siblings * siblings, // must contain elements int k) { @@ -769,6 +780,7 @@ class Simplex_tree { } } } + /** \brief Intersects Dictionary 1 [begin1;end1) with Dictionary 2 [begin2,end2) * and assigns the maximal possible Filtration_value to the Nodes. */ void intersection(std::vector >& intersection, @@ -800,6 +812,7 @@ class Simplex_tree { } } } + /** Maximum over 3 values.*/ Filtration_value maximum(Filtration_value a, Filtration_value b, Filtration_value c) { @@ -824,6 +837,92 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } + //---------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------- + private: + + /** Recursive search of cofaces + */ + template + void rec_coface(RandomAccessVertexRange &vertices, Siblings *curr_sib, Dictionary *curr_res, std::vector& cofaces, unsigned int length, unsigned long codimension) { + for (auto sib = curr_sib->members().begin(); sib != curr_sib->members().end() && (vertices.empty() || sib->first <= vertices[vertices.size() - 1]); ++sib) { + bool continueRecursion = (codimension == length || curr_res->size() <= codimension); // dimension of actual simplex <= codimension + if (vertices.empty()) { + if (curr_res->size() >= length && continueRecursion) + // If we reached the end of the vertices, and the simplex has more vertices than the given simplex, we found a coface + { + curr_res->emplace(sib->first, sib->second); + bool egalDim = (codimension == length || curr_res->size() == codimension); // dimension of actual simplex == codimension + if (egalDim) + cofaces.push_back(*curr_res); + if (has_children(sib)) + rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); + curr_res->erase(curr_res->end() - 1); + } + } else if (continueRecursion) { + if (sib->first == vertices[vertices.size() - 1]) // If curr_sib matches with the top vertex + { + curr_res->emplace(sib->first, sib->second); + bool egalDim = (codimension == length || curr_res->size() == codimension); // dimension of actual simplex == codimension + if (vertices.size() == 1 && curr_res->size() > length && egalDim) + cofaces.push_back(*curr_res); + if (has_children(sib)) { // Rec call + Vertex_handle tmp = vertices[vertices.size() - 1]; + vertices.pop_back(); + rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); + vertices.push_back(tmp); + } + curr_res->erase(curr_res->end() - 1); + } else // (sib->first < vertices[vertices.size()-1]) + { + if (has_children(sib)) { + curr_res->emplace(sib->first, sib->second); + rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); + curr_res->erase(curr_res->end() - 1); + } + } + } + } + } + + public: + + /** \brief Compute the cofaces of a n simplex + * \param vertices List of vertices which represent the n simplex. + * \param codimension The function returns the n+codimension-simplices. If codimension = 0, return all cofaces + * \return Vector of Dictionary, empty vector if no cofaces found. + * \warning n+codimension must be lower than Simplex_tree dimension, otherwise an an empty vector is returned. + */ + + template + std::vector coface(const RandomAccessVertexRange &vertices, int codimension) { + RandomAccessVertexRange copy = vertices; + std::vector cofaces; + std::sort(copy.begin(), copy.end(), std::greater()); // must be sorted in decreasing order + if (root_.members().empty()) { + std::cerr << "Simplex_tree::coface - empty Simplex_tree" << std::endl; + return cofaces; // ----->> + } + if (vertices.empty()) { + std::cerr << "Simplex_tree::coface - empty vertices list" << std::endl; + return cofaces; // ----->> + } + if (codimension < 0) { + std::cerr << "Simplex_tree::coface - codimension is empty" << std::endl; + return cofaces; // ----->> + } + if (codimension + vertices.size() >= (unsigned long) dimension_) { + std::cerr << "Simplex_tree::coface - codimension + vertices list size cannot be greater than Simplex_tree dimension" << std::endl; + return cofaces; // ----->> + } + std::sort(copy.begin(), copy.end(), std::greater()); // must be sorted in decreasing order + Dictionary res; + rec_coface(copy, &root_, &res, cofaces, vertices.size(), codimension + vertices.size()); + return cofaces; + } + + //---------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------- private: Vertex_handle null_vertex_; @@ -851,6 +950,7 @@ std::ostream& operator<<(std::ostream & os, Simplex_tree & st) { } return os; } + template std::istream& operator>>(std::istream & is, Simplex_tree & st) { // assert(st.num_simplices() == 0); diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index e29218d8..618d1b4d 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -7,7 +7,7 @@ * * Author(s): David Salinas * - * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France) + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (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 @@ -121,7 +121,7 @@ private: if(!goto_next_uncomment_line(line)) return false; std::istringstream iss(line); - if(is_off_file){ + 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"; -- cgit v1.2.3 From 853eb92146a6d473337fed8ef57f77bee8efd356 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 15 Jun 2015 09:28:06 +0000 Subject: 1st version of alpha complex - compilation and tests are OK git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@613 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4bcf44466cce7d3dfd62e2e8a74b8c3e1f4808dd --- src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 159 +++++++------------------- 1 file changed, 41 insertions(+), 118 deletions(-) diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index 2bc8b221..f23df51a 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,7 @@ class Alpha_shapes { 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. @@ -132,85 +134,11 @@ class Alpha_shapes { private: - template - void initial_init(T& triangulation) { - st_.set_dimension(triangulation.maximal_dimension()); - Filtration_value filtration_max = 0.0; - - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); - - // triangulation full cells list - for (auto cit = triangulation.full_cells_begin(); cit != triangulation.full_cells_end(); ++cit) { - typeVectorVertex vertexVector; - typeVectorPoint pointVector; - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - if (!triangulation.is_infinite(*vit)) { - // Vector of vertex construction for simplex_tree structure - // Vertex handle is distance - 1 - Vertex_handle vertexHdl = std::distance(triangulation.vertices_begin(), *vit) - 1; - // infinite cell is -1 for infinite - vertexVector.push_back(vertexHdl); - // Vector of points for alpha_shapes filtration value computation - pointVector.push_back((*vit)->point()); -#ifdef DEBUG_TRACES - /*std::cout << "Point "; - for (auto Coord = (*vit)->point().cartesian_begin(); Coord != (*vit)->point().cartesian_end(); ++Coord) { - std::cout << *Coord << " | "; - } - std::cout << std::endl;*/ -#endif // DEBUG_TRACES - } - } - Filtration_value alpha_shapes_filtration = 0.0; - - if (!triangulation.is_infinite(cit)) { - alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); -#ifdef DEBUG_TRACES - //std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; -#endif // DEBUG_TRACES - } else { - Filtration_value tmp_filtration = 0.0; - bool is_gab = true; - /*for (auto vit = triangulation.finite_vertices_begin(); vit != triangulation.finite_vertices_end(); ++vit) { - if (CGAL::ON_UNBOUNDED_SIDE != is_gabriel(pointVector.begin(), pointVector.end(), vit->point())) { - is_gab = false; - // TODO(VR) : Compute minimum - - } - }*/ - if (true == is_gab) { - alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); -#ifdef DEBUG_TRACES - //std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; -#endif // DEBUG_TRACES - } - } - // Insert each point in the simplex tree - st_.insert_simplex_and_subfaces(vertexVector, alpha_shapes_filtration); - -#ifdef DEBUG_TRACES - std::cout << "C" << std::distance(triangulation.full_cells_begin(), cit) << ":"; - for (auto value : vertexVector) { - std::cout << value << ' '; - } - std::cout << " | alpha=" << alpha_shapes_filtration << std::endl; -#endif // DEBUG_TRACES - } - st_.set_filtration(filtration_max); - } - template void init(T& triangulation) { st_.set_dimension(triangulation.maximal_dimension()); - Filtration_value filtration_max = 0.0; - Filtration_value filtration_unknown = std::numeric_limits::quiet_NaN(); - - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + // -------------------------------------------------------------------------------------------- // bimap to retrieve vertex handles from points and vice versa typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; bimap_points_vh points_to_vh; @@ -221,52 +149,54 @@ class Alpha_shapes { points_to_vh.insert(bimap_points_vh::value_type(vit->point(), vertex_handle)); vertex_handle++; } + // -------------------------------------------------------------------------------------------- - // Loop on triangulation finite full cells list + // -------------------------------------------------------------------------------------------- + // 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; - typeVectorPoint pointVector; +#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 << "points_to_vh=" << points_to_vh.left.at((*vit)->point()) << std::endl; + std::cout << " " << points_to_vh.left.at((*vit)->point()); #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure vertexVector.push_back(points_to_vh.left.at((*vit)->point())); - // Vector of points for alpha_shapes filtration value computation - pointVector.push_back((*vit)->point()); } - Filtration_value alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); - // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - std::pair insert_result = st_.insert_simplex_and_subfaces(vertexVector, filtration_unknown); - - if (insert_result.second == true) { - // Only top-level cell must have the correct alpha value - st_.assign_filtration(insert_result.first, alpha_shapes_filtration); #ifdef DEBUG_TRACES - std::cout << "alpha_shapes_filtration=" << st_.filtration(insert_result.first) << std::endl; + std::cout << std::endl; #endif // DEBUG_TRACES - - filtration_max = fmax(filtration_max, alpha_shapes_filtration); + // 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_shapes::init insert_simplex_and_subfaces failed" << std::endl; } } + // -------------------------------------------------------------------------------------------- + + Filtration_value filtration_max = 0.0; + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + // -------------------------------------------------------------------------------------------- // ### 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); -#ifdef DEBUG_TRACES - std::cout << "f_simplex_dim= " << f_simplex_dim << " - decr_dim= " << decr_dim << std::endl; -#endif // DEBUG_TRACES if (decr_dim == f_simplex_dim) { typeVectorPoint pointVector; #ifdef DEBUG_TRACES - std::cout << "vertex "; + std::cout << "Sigma of dim " << decr_dim << " is"; #endif // DEBUG_TRACES for (auto vertex : st_.simplex_vertex_range(f_simplex)) { pointVector.push_back(points_to_vh.right.at(vertex)); #ifdef DEBUG_TRACES - std::cout << (int) vertex << " "; + std::cout << " " << vertex; #endif // DEBUG_TRACES } #ifdef DEBUG_TRACES @@ -280,23 +210,21 @@ class Alpha_shapes { alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); } st_.assign_filtration(f_simplex, alpha_shapes_filtration); + filtration_max = fmax(filtration_max, alpha_shapes_filtration); #ifdef DEBUG_TRACES - std::cout << "From NaN to alpha_shapes_filtration=" << st_.filtration(f_simplex) << std::endl; + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; #endif // DEBUG_TRACES } // ### Foreach Tau face of Sigma for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { #ifdef DEBUG_TRACES - std::cout << "Sigma "; - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { - std::cout << (int) vertex << " "; - } - std::cout << " - Tau "; + std::cout << " | --------------------------------------------------" << std::endl; + std::cout << " | Tau "; for (auto vertex : st_.simplex_vertex_range(f_boundary)) { - std::cout << (int) vertex << " "; + std::cout << vertex << " "; } - std::cout << std::endl; + std::cout << "is a face of Sigma" << std::endl; #endif // DEBUG_TRACES // insert the Tau points in a vector for is_gabriel function typeVectorPoint pointVector; @@ -313,35 +241,30 @@ class Alpha_shapes { break; } } +#ifdef DEBUG_TRACES + std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) + != CGAL::ON_BOUNDED_SIDE; + std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; +#endif // DEBUG_TRACES // ### If filt(Tau) is not NaN // ### or Tau is not Gabriel of Sigma if (!isnan(st_.filtration(f_boundary)) || - !is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) + (is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) == CGAL::ON_BOUNDED_SIDE) ) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); st_.assign_filtration(f_boundary, alpha_shapes_filtration); + filtration_max = fmax(filtration_max, alpha_shapes_filtration); #ifdef DEBUG_TRACES - std::cout << "From Boundary to alpha_shapes_filtration=" << st_.filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; #endif // DEBUG_TRACES } } } } } - -#ifdef DEBUG_TRACES - 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; - } -#endif // DEBUG_TRACES + // -------------------------------------------------------------------------------------------- #ifdef DEBUG_TRACES std::cout << "filtration_max=" << filtration_max << std::endl; -- cgit v1.2.3 From 17fd245908ba07d6bad974efa0be1ec6093262ec Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 15 Jun 2015 09:31:02 +0000 Subject: Alpha_shapes renamed Alpha_complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@614 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ede5d1c1175f9d314e23bc0b76f7376b3de90c93 --- src/Alpha_complex/example/CMakeLists.txt | 31 ++ .../example/Delaunay_triangulation_off_rw.cpp | 79 ++++++ .../Simplex_tree_from_delaunay_triangulation.cpp | 77 +++++ src/Alpha_complex/example/alphashapedoc.off | 10 + src/Alpha_complex/include/gudhi/Alpha_shapes.h | 311 +++++++++++++++++++++ .../Alpha_shapes/Delaunay_triangulation_off_io.h | 192 +++++++++++++ src/Alpha_complex/test/Alpha_shapes_unit_test.cpp | 126 +++++++++ src/Alpha_complex/test/CMakeLists.txt | 31 ++ src/Alpha_complex/test/README | 12 + src/Alpha_complex/test/S4_100.off | 102 +++++++ src/Alpha_complex/test/S8_10.off | 12 + src/Alpha_shapes/example/CMakeLists.txt | 31 -- .../example/Delaunay_triangulation_off_rw.cpp | 79 ------ .../Simplex_tree_from_delaunay_triangulation.cpp | 77 ----- src/Alpha_shapes/example/alphashapedoc.off | 10 - src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 311 --------------------- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 192 ------------- src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp | 126 --------- src/Alpha_shapes/test/CMakeLists.txt | 31 -- src/Alpha_shapes/test/README | 12 - src/Alpha_shapes/test/S4_100.off | 102 ------- src/Alpha_shapes/test/S8_10.off | 12 - 22 files changed, 983 insertions(+), 983 deletions(-) create mode 100644 src/Alpha_complex/example/CMakeLists.txt create mode 100644 src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp create mode 100644 src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp create mode 100755 src/Alpha_complex/example/alphashapedoc.off create mode 100644 src/Alpha_complex/include/gudhi/Alpha_shapes.h create mode 100644 src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h create mode 100644 src/Alpha_complex/test/Alpha_shapes_unit_test.cpp create mode 100644 src/Alpha_complex/test/CMakeLists.txt create mode 100644 src/Alpha_complex/test/README create mode 100644 src/Alpha_complex/test/S4_100.off create mode 100644 src/Alpha_complex/test/S8_10.off delete mode 100644 src/Alpha_shapes/example/CMakeLists.txt delete mode 100644 src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp delete mode 100644 src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp delete mode 100755 src/Alpha_shapes/example/alphashapedoc.off delete mode 100644 src/Alpha_shapes/include/gudhi/Alpha_shapes.h delete mode 100644 src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h delete mode 100644 src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp delete mode 100644 src/Alpha_shapes/test/CMakeLists.txt delete mode 100644 src/Alpha_shapes/test/README delete mode 100644 src/Alpha_shapes/test/S4_100.off delete mode 100644 src/Alpha_shapes/test/S8_10.off diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt new file mode 100644 index 00000000..582a9322 --- /dev/null +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIAlphaShapesExample) + +# need CGAL 4.7 +# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.7.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_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_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) + target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + 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/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp new file mode 100644 index 00000000..fe889ec0 --- /dev/null +++ b/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp @@ -0,0 +1,79 @@ +/* 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::alphashapes::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::alphashapes::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 new file mode 100644 index 00000000..0a24fb56 --- /dev/null +++ b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -0,0 +1,77 @@ +/* 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 "gudhi/Alpha_shapes.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 + +// 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); // ----- >> +} + +int main(int argc, char **argv) { + if (argc != 2) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + std::string off_file_name(argv[1]); + + // ---------------------------------------------------------------------------- + // + // Init of an alpha-shape from a OFF file + // + // ---------------------------------------------------------------------------- + Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); + + std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; + std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; + std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; + std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; + //std::cout << alpha_shapes_from_file << 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 new file mode 100755 index 00000000..bb790193 --- /dev/null +++ b/src/Alpha_complex/example/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/include/gudhi/Alpha_shapes.h b/src/Alpha_complex/include/gudhi/Alpha_shapes.h new file mode 100644 index 00000000..f23df51a --- /dev/null +++ b/src/Alpha_complex/include/gudhi/Alpha_shapes.h @@ -0,0 +1,311 @@ +/* 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 alphashapes { + +#define Kinit(f) =k.f() + +/** \defgroup alpha_shapes Alpha shapes in dimension N + * +
Implementations:
+ Alpha shapes 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 shapes 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. + * + * \implements FilteredComplex + * + */ +class Alpha_shapes { + 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-shape. + */ + 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 typeVectorPoint; + + private: + /** \brief Upper bound on the simplex tree of the simplicial complex.*/ + Gudhi::Simplex_tree<> st_; + + public: + + Alpha_shapes(std::string& off_file_name) { + // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function + Delaunay_triangulation dt(2); + Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << off_file_name << std::endl; + exit(-1); // ----- >> + } +#ifdef DEBUG_TRACES + std::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; + std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; + std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; +#endif // DEBUG_TRACES + init(dt); + } + + template + Alpha_shapes(T& triangulation) { + init(triangulation); + } + + ~Alpha_shapes() { } + + private: + + template + void init(T& triangulation) { + st_.set_dimension(triangulation.maximal_dimension()); + + // -------------------------------------------------------------------------------------------- + // bimap to retrieve vertex handles from points and vice versa + typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; + bimap_points_vh points_to_vh; + // Start to insert at handle = 0 - default integer value + Vertex_handle vertex_handle = Vertex_handle(); + // Loop on triangulation vertices list + for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { + points_to_vh.insert(bimap_points_vh::value_type(vit->point(), 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 << " " << points_to_vh.left.at((*vit)->point()); +#endif // DEBUG_TRACES + // Vector of vertex construction for simplex_tree structure + vertexVector.push_back(points_to_vh.left.at((*vit)->point())); + } +#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_shapes::init insert_simplex_and_subfaces failed" << std::endl; + } + } + // -------------------------------------------------------------------------------------------- + + Filtration_value filtration_max = 0.0; + + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + // -------------------------------------------------------------------------------------------- + // ### 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) { + typeVectorPoint 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(points_to_vh.right.at(vertex)); +#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_shapes_filtration = 0.0; + // No need to compute squared_radius on a single point - alpha is 0.0 + if (f_simplex_dim > 0) { + alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); + } + st_.assign_filtration(f_simplex, alpha_shapes_filtration); + filtration_max = fmax(filtration_max, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; +#endif // DEBUG_TRACES + } + + // ### 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; +#endif // DEBUG_TRACES + // insert the Tau points in a vector for is_gabriel function + typeVectorPoint pointVector; + Vertex_handle vertexForGabriel = Vertex_handle(); + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + pointVector.push_back(points_to_vh.right.at(vertex)); + } + // 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(), points_to_vh.right.at(vertex)) == pointVector.end()) { + // vertex is not found in Tau + vertexForGabriel = vertex; + // No need to continue loop + break; + } + } +#ifdef DEBUG_TRACES + std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) + != CGAL::ON_BOUNDED_SIDE; + std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; +#endif // DEBUG_TRACES + // ### If filt(Tau) is not NaN + // ### or Tau is not Gabriel of Sigma + if (!isnan(st_.filtration(f_boundary)) || + (is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) == CGAL::ON_BOUNDED_SIDE) + ) { + // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) + Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); + st_.assign_filtration(f_boundary, alpha_shapes_filtration); + filtration_max = fmax(filtration_max, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES + } + } + } + } + } + // -------------------------------------------------------------------------------------------- + +#ifdef DEBUG_TRACES + std::cout << "filtration_max=" << filtration_max << std::endl; +#endif // DEBUG_TRACES + st_.set_filtration(filtration_max); + } + + 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_shapes & alpha_shape) { + // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor + Gudhi::Simplex_tree<> st = alpha_shape.st_; + os << st << std::endl; + return os; + } +}; + +} // namespace alphashapes + +} // namespace Gudhi + +#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ 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 new file mode 100644 index 00000000..a4e5e2fe --- /dev/null +++ b/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h @@ -0,0 +1,192 @@ +/* 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 alphashapes { + +/** + *@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 { + Complex& complex_; + typedef typename Complex::Point Point; + + public: + + explicit Delaunay_triangulation_off_visitor_reader(Complex& complex) : + complex_(complex) { } + + 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_.set_current_dimension(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 + } +}; + +/** + *@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, Complex& read_complex) : valid_(false) { + std::ifstream stream(name_file); + if (stream.is_open()) { + Delaunay_triangulation_off_visitor_reader off_visitor(read_complex); + Off_reader off_reader(stream); + valid_ = off_reader.read(off_visitor); + } 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_; + } + + private: + bool valid_; +}; + +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, const Complex& save_complex) { + std::ofstream stream(name_file); + if (stream.is_open()) { + if (save_complex.current_dimension() == 3) { + // OFF header + stream << "OFF" << std::endl; + // no endl on next line - don't know why... + stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; + } else { + // nOFF header + stream << "nOFF" << std::endl; + // no endl on next line - don't know why... + stream << save_complex.current_dimension() << " " << save_complex.number_of_vertices() << " " << + save_complex.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 = save_complex.vertices_begin(); vit != save_complex.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 = save_complex.finite_full_cells_begin(); cit != save_complex.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 alphashapes + +} // namespace Gudhi + +#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp b/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp new file mode 100644 index 00000000..d5db3bfa --- /dev/null +++ b/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp @@ -0,0 +1,126 @@ +/* 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 alpha_shapes +#include +#include +#include +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_shapes.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 + +// 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 + +BOOST_AUTO_TEST_CASE( OFF_file ) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-shape from a OFF file + // + // ---------------------------------------------------------------------------- + std::string off_file_name("S4_100.off"); + std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + + Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name, 4); + + const int DIMENSION = 4; + std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; + BOOST_CHECK(alpha_shapes_from_file.dimension() == DIMENSION); + + const double FILTRATION = 0.0; + std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; + BOOST_CHECK(alpha_shapes_from_file.filtration() == FILTRATION); + + const int NUMBER_OF_VERTICES = 100; + std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_shapes_from_file.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 6779; + std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; + BOOST_CHECK(alpha_shapes_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + +} + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-shape from a Delauny triangulation + // + // ---------------------------------------------------------------------------- + T dt(8); + std::string off_file_name("S8_10.off"); + std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + + Gudhi::alphashapes::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::alphashapes::Alpha_shapes alpha_shapes_from_dt(dt); + + const int DIMENSION = 8; + std::cout << "alpha_shapes_from_dt.dimension()=" << alpha_shapes_from_dt.dimension() << std::endl; + BOOST_CHECK(alpha_shapes_from_dt.dimension() == DIMENSION); + + const double FILTRATION = 0.0; + std::cout << "alpha_shapes_from_dt.filtration()=" << alpha_shapes_from_dt.filtration() << std::endl; + BOOST_CHECK(alpha_shapes_from_dt.filtration() == FILTRATION); + + std::cout << "alpha_shapes_from_dt.num_vertices()=" << alpha_shapes_from_dt.num_vertices() << std::endl; + BOOST_CHECK(alpha_shapes_from_dt.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 997; + std::cout << "alpha_shapes_from_dt.num_simplices()=" << alpha_shapes_from_dt.num_simplices() << std::endl; + BOOST_CHECK(alpha_shapes_from_dt.num_simplices() == NUMBER_OF_SIMPLICES); +} + diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt new file mode 100644 index 00000000..3cf97b71 --- /dev/null +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIAlphaShapesTest) + +# need CGAL 4.7 +# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.7.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} ) + include_directories (BEFORE "../../include") + + add_definitions(-DDEBUG_TRACES) + add_executable ( AlphaShapesUnitTest Alpha_shapes_unit_test.cpp ) + target_link_libraries(AlphaShapesUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_test(AlphaShapesUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaShapesUnitTest) + + 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/Alpha_shapes/include/gudhi") diff --git a/src/Alpha_complex/test/README b/src/Alpha_complex/test/README new file mode 100644 index 00000000..244a2b84 --- /dev/null +++ b/src/Alpha_complex/test/README @@ -0,0 +1,12 @@ +To compile: +*********** + +cmake . +make + +To launch with details: +*********************** + +./AlphaShapesUnitTest --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 new file mode 100644 index 00000000..0a5dc58c --- /dev/null +++ b/src/Alpha_complex/test/S4_100.off @@ -0,0 +1,102 @@ +OFF +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 +0.916381 -0.0512295 0.371049 0.141223 +0.182222 0.940836 -0.171362 -0.228599 +-0.787145 -0.129213 0.568102 -0.202402 +0.0187866 -0.22093 -0.832882 -0.507095 +-0.4702 -0.533814 0.353776 0.607286 +-0.159798 -0.504771 0.263586 0.806346 +0.295546 0.162541 0.452931 0.825279 +0.242043 -0.107437 -0.913612 -0.308521 +0.875759 -0.113035 -0.469189 -0.0114505 +0.547877 -0.762247 -0.256972 -0.229729 +-0.172302 0.521057 0.412013 -0.727363 +-0.724729 -0.0574074 -0.0290602 0.686023 +0.700434 -0.102636 0.687285 0.162779 +-0.681386 0.0946893 0.610047 0.393178 +-0.847553 -0.357132 0.383743 0.0827718 +0.72297 -0.161631 -0.608517 0.284424 +0.757394 0.141549 0.196065 -0.606528 +0.78094 0.00901997 0.434536 0.448586 +0.14166 -0.619339 0.614589 -0.467582 +0.473105 -0.537832 -0.0103746 0.697711 +-0.208004 0.536218 0.818027 0.00605288 +0.743694 -0.628926 0.188072 0.126488 +-0.462228 -0.278147 0.35514 -0.76345 +-0.17361 0.249211 0.758567 -0.57648 +0.416958 -0.254924 -0.576373 -0.654946 +-0.590751 -0.286089 -0.424896 0.623402 +-0.639538 -0.739693 -0.203745 0.0482932 +0.0731787 0.132121 0.864022 0.480266 +-0.149644 -0.164724 -0.249746 -0.94239 +-0.348592 0.0120379 -0.928656 -0.126239 +0.395328 -0.54513 0.149976 -0.723917 +-0.974164 0.14707 0.157191 0.068302 +-0.166425 0.119943 -0.627304 -0.751269 +0.031947 -0.358518 -0.708301 -0.607251 +0.93781 -0.155368 -0.30951 0.0240237 +0.276094 -0.753155 -0.597088 -0.00387459 +-0.642876 -0.200551 -0.263517 -0.690687 +0.178711 0.604987 -0.262989 0.729993 +-0.520347 0.497922 -0.676144 0.155374 +-0.703999 0.500219 -0.484381 0.139789 +-0.131013 0.835735 0.506779 0.166004 +-0.536116 -0.566557 0.229226 0.582279 +-0.334105 0.158252 0.926091 0.0754059 +-0.0362677 0.296076 0.897108 0.325915 +-0.57486 0.798575 0.15324 -0.0912754 +0.498602 0.0186805 0.72824 0.469801 +-0.960329 0.0473356 0.261005 -0.0860505 +0.899134 -0.381392 -0.214508 0.00921711 +0.570576 0.567224 0.393019 -0.445237 +-0.761763 -0.614589 -0.0546476 -0.197513 +0.188584 0.289531 0.174031 0.922129 +-0.458506 -0.583876 0.639297 -0.2004 +0.785343 -0.21571 0.0794082 -0.574804 +0.0819036 0.65961 -0.247426 0.704973 +0.573125 0.49706 0.373026 0.534145 +-0.513286 -0.626226 0.208535 -0.548536 +0.460558 0.468686 0.507832 -0.55707 +0.716158 -0.488201 0.388209 -0.313164 +0.881074 0.152441 0.380128 -0.236589 +0.885793 0.0386389 0.161009 -0.433537 +-0.365162 0.298384 0.292846 0.831784 +0.364934 0.632269 -0.197205 -0.654346 +-0.31469 -0.429991 0.665304 -0.522923 +-0.734198 0.462914 -0.135691 -0.477756 +-0.422885 0.674444 -0.364143 -0.483419 +0.829218 -0.154622 -0.381147 0.378439 +0.887881 0.310479 -0.109528 0.321363 +-0.354398 -0.693974 0.456019 -0.429941 +-0.492045 -0.160008 0.044387 0.854587 +0.0595532 0.158421 0.412577 -0.895062 +-0.211441 0.491794 -0.153521 0.83058 +-0.33558 -0.504711 0.353831 -0.71236 +-0.735211 -0.197714 0.525626 0.379593 +0.465818 -0.424245 0.769469 -0.104627 +-0.641071 -0.286339 -0.704442 -0.103923 +-0.00446569 0.0249849 -0.194417 -0.980591 +-0.610081 -0.252448 0.176698 -0.729966 +-0.0859217 -0.154471 0.715027 0.676382 +0.091315 0.0723382 -0.855023 -0.505337 +0.165362 0.200983 -0.428242 -0.865373 +-0.587465 0.303019 -0.152442 0.734729 +0.454946 -0.319828 0.437063 -0.706902 +-0.384368 0.277509 0.879225 -0.0470385 +0.523335 -0.330233 -0.208592 0.757335 +0.895086 0.0448492 0.268089 -0.353466 +-0.0272491 -0.567336 -0.72254 -0.39411 +-0.0745014 -0.121818 -0.882466 0.448179 +0.382304 -0.240135 0.851109 -0.267941 +-0.418057 -0.852847 -0.3128 0.00606452 +-0.554046 0.304237 0.272381 -0.725453 +0.155115 -0.0894732 -0.245017 -0.952838 +0.114459 -0.130722 0.953669 0.245614 +0.0913002 -0.462466 0.244433 0.847374 +-0.198849 0.0785111 0.131441 -0.967997 +-0.303154 -0.686484 0.639333 0.167604 +0.521455 0.256835 -0.0584503 -0.811606 +-0.109787 0.870544 0.161523 0.451676 diff --git a/src/Alpha_complex/test/S8_10.off b/src/Alpha_complex/test/S8_10.off new file mode 100644 index 00000000..1d67e10f --- /dev/null +++ b/src/Alpha_complex/test/S8_10.off @@ -0,0 +1,12 @@ +OFF +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 +0.0137399 -0.161581 -0.609142 -0.370872 -0.320669 -0.364053 0.24127 0.41416 +-0.115313 -0.36425 0.190208 0.581871 0.204605 0.112527 0.313562 0.571337 +0.168272 -0.0746917 -0.635156 -0.214488 0.629498 -0.0812499 -0.337255 -0.00823068 +0.369896 -0.514626 -0.173493 -0.1551 -0.127105 0.384377 0.303936 -0.536566 +-0.49013 -0.0388242 -0.0196532 0.463953 0.515962 -0.0756047 0.506276 0.119908 +-0.434258 0.060347 0.388793 0.250579 -0.653127 -0.275207 0.295714 0.0637842 +0.596172 -0.133284 -0.501793 0.234541 0.428452 0.0800735 0.110912 -0.343109 diff --git a/src/Alpha_shapes/example/CMakeLists.txt b/src/Alpha_shapes/example/CMakeLists.txt deleted file mode 100644 index 582a9322..00000000 --- a/src/Alpha_shapes/example/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -cmake_minimum_required(VERSION 2.6) -project(GUDHIAlphaShapesExample) - -# need CGAL 4.7 -# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. -if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.7.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_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_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) - target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - 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/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp deleted file mode 100644 index fe889ec0..00000000 --- a/src/Alpha_shapes/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::alphashapes::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::alphashapes::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); - - return 0; -} \ No newline at end of file diff --git a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp deleted file mode 100644 index 0a24fb56..00000000 --- a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp +++ /dev/null @@ -1,77 +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 "gudhi/Alpha_shapes.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 - -// 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); // ----- >> -} - -int main(int argc, char **argv) { - if (argc != 2) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - std::string off_file_name(argv[1]); - - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a OFF file - // - // ---------------------------------------------------------------------------- - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); - - std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; - std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; - std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; - std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; - //std::cout << alpha_shapes_from_file << std::endl; - - return 0; -} \ No newline at end of file diff --git a/src/Alpha_shapes/example/alphashapedoc.off b/src/Alpha_shapes/example/alphashapedoc.off deleted file mode 100755 index bb790193..00000000 --- a/src/Alpha_shapes/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_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h deleted file mode 100644 index f23df51a..00000000 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ /dev/null @@ -1,311 +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_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 alphashapes { - -#define Kinit(f) =k.f() - -/** \defgroup alpha_shapes Alpha shapes in dimension N - * -
Implementations:
- Alpha shapes 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 shapes 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. - * - * \implements FilteredComplex - * - */ -class Alpha_shapes { - 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-shape. - */ - 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 typeVectorPoint; - - private: - /** \brief Upper bound on the simplex tree of the simplicial complex.*/ - Gudhi::Simplex_tree<> st_; - - public: - - Alpha_shapes(std::string& off_file_name) { - // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function - Delaunay_triangulation dt(2); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << off_file_name << std::endl; - exit(-1); // ----- >> - } -#ifdef DEBUG_TRACES - std::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; - std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; -#endif // DEBUG_TRACES - init(dt); - } - - template - Alpha_shapes(T& triangulation) { - init(triangulation); - } - - ~Alpha_shapes() { } - - private: - - template - void init(T& triangulation) { - st_.set_dimension(triangulation.maximal_dimension()); - - // -------------------------------------------------------------------------------------------- - // bimap to retrieve vertex handles from points and vice versa - typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; - bimap_points_vh points_to_vh; - // Start to insert at handle = 0 - default integer value - Vertex_handle vertex_handle = Vertex_handle(); - // Loop on triangulation vertices list - for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { - points_to_vh.insert(bimap_points_vh::value_type(vit->point(), 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 << " " << points_to_vh.left.at((*vit)->point()); -#endif // DEBUG_TRACES - // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(points_to_vh.left.at((*vit)->point())); - } -#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_shapes::init insert_simplex_and_subfaces failed" << std::endl; - } - } - // -------------------------------------------------------------------------------------------- - - Filtration_value filtration_max = 0.0; - - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); - // -------------------------------------------------------------------------------------------- - // ### 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) { - typeVectorPoint 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(points_to_vh.right.at(vertex)); -#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_shapes_filtration = 0.0; - // No need to compute squared_radius on a single point - alpha is 0.0 - if (f_simplex_dim > 0) { - alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); - } - st_.assign_filtration(f_simplex, alpha_shapes_filtration); - filtration_max = fmax(filtration_max, alpha_shapes_filtration); -#ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; -#endif // DEBUG_TRACES - } - - // ### 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; -#endif // DEBUG_TRACES - // insert the Tau points in a vector for is_gabriel function - typeVectorPoint pointVector; - Vertex_handle vertexForGabriel = Vertex_handle(); - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { - pointVector.push_back(points_to_vh.right.at(vertex)); - } - // 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(), points_to_vh.right.at(vertex)) == pointVector.end()) { - // vertex is not found in Tau - vertexForGabriel = vertex; - // No need to continue loop - break; - } - } -#ifdef DEBUG_TRACES - std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; - bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) - != CGAL::ON_BOUNDED_SIDE; - std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; -#endif // DEBUG_TRACES - // ### If filt(Tau) is not NaN - // ### or Tau is not Gabriel of Sigma - if (!isnan(st_.filtration(f_boundary)) || - (is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) == CGAL::ON_BOUNDED_SIDE) - ) { - // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) - Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); - st_.assign_filtration(f_boundary, alpha_shapes_filtration); - filtration_max = fmax(filtration_max, alpha_shapes_filtration); -#ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; -#endif // DEBUG_TRACES - } - } - } - } - } - // -------------------------------------------------------------------------------------------- - -#ifdef DEBUG_TRACES - std::cout << "filtration_max=" << filtration_max << std::endl; -#endif // DEBUG_TRACES - st_.set_filtration(filtration_max); - } - - 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_shapes & alpha_shape) { - // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor - Gudhi::Simplex_tree<> st = alpha_shape.st_; - os << st << std::endl; - return os; - } -}; - -} // namespace alphashapes - -} // namespace Gudhi - -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h deleted file mode 100644 index a4e5e2fe..00000000 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ /dev/null @@ -1,192 +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 alphashapes { - -/** - *@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 { - Complex& complex_; - typedef typename Complex::Point Point; - - public: - - explicit Delaunay_triangulation_off_visitor_reader(Complex& complex) : - complex_(complex) { } - - 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_.set_current_dimension(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 - } -}; - -/** - *@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, Complex& read_complex) : valid_(false) { - std::ifstream stream(name_file); - if (stream.is_open()) { - Delaunay_triangulation_off_visitor_reader off_visitor(read_complex); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - } 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_; - } - - private: - bool valid_; -}; - -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, const Complex& save_complex) { - std::ofstream stream(name_file); - if (stream.is_open()) { - if (save_complex.current_dimension() == 3) { - // OFF header - stream << "OFF" << std::endl; - // no endl on next line - don't know why... - stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; - } else { - // nOFF header - stream << "nOFF" << std::endl; - // no endl on next line - don't know why... - stream << save_complex.current_dimension() << " " << save_complex.number_of_vertices() << " " << - save_complex.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 = save_complex.vertices_begin(); vit != save_complex.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 = save_complex.finite_full_cells_begin(); cit != save_complex.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 alphashapes - -} // namespace Gudhi - -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp b/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp deleted file mode 100644 index d5db3bfa..00000000 --- a/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp +++ /dev/null @@ -1,126 +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 . - */ - -#define BOOST_TEST_MODULE alpha_shapes -#include -#include -#include -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_shapes.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 - -// 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 - -BOOST_AUTO_TEST_CASE( OFF_file ) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a OFF file - // - // ---------------------------------------------------------------------------- - std::string off_file_name("S4_100.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name, 4); - - const int DIMENSION = 4; - std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.filtration() == FILTRATION); - - const int NUMBER_OF_VERTICES = 100; - std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.num_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_SIMPLICES = 6779; - std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.num_simplices() == NUMBER_OF_SIMPLICES); - -} - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a Delauny triangulation - // - // ---------------------------------------------------------------------------- - T dt(8); - std::string off_file_name("S8_10.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - - Gudhi::alphashapes::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::alphashapes::Alpha_shapes alpha_shapes_from_dt(dt); - - const int DIMENSION = 8; - std::cout << "alpha_shapes_from_dt.dimension()=" << alpha_shapes_from_dt.dimension() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_shapes_from_dt.filtration()=" << alpha_shapes_from_dt.filtration() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.filtration() == FILTRATION); - - std::cout << "alpha_shapes_from_dt.num_vertices()=" << alpha_shapes_from_dt.num_vertices() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.num_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_SIMPLICES = 997; - std::cout << "alpha_shapes_from_dt.num_simplices()=" << alpha_shapes_from_dt.num_simplices() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.num_simplices() == NUMBER_OF_SIMPLICES); -} - diff --git a/src/Alpha_shapes/test/CMakeLists.txt b/src/Alpha_shapes/test/CMakeLists.txt deleted file mode 100644 index 3cf97b71..00000000 --- a/src/Alpha_shapes/test/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -cmake_minimum_required(VERSION 2.6) -project(GUDHIAlphaShapesTest) - -# need CGAL 4.7 -# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. -if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.7.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} ) - include_directories (BEFORE "../../include") - - add_definitions(-DDEBUG_TRACES) - add_executable ( AlphaShapesUnitTest Alpha_shapes_unit_test.cpp ) - target_link_libraries(AlphaShapesUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - add_test(AlphaShapesUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaShapesUnitTest) - - 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/Alpha_shapes/include/gudhi") diff --git a/src/Alpha_shapes/test/README b/src/Alpha_shapes/test/README deleted file mode 100644 index 244a2b84..00000000 --- a/src/Alpha_shapes/test/README +++ /dev/null @@ -1,12 +0,0 @@ -To compile: -*********** - -cmake . -make - -To launch with details: -*********************** - -./AlphaShapesUnitTest --report_level=detailed --log_level=all - - ==> echo $? returns 0 in case of success (non-zero otherwise) diff --git a/src/Alpha_shapes/test/S4_100.off b/src/Alpha_shapes/test/S4_100.off deleted file mode 100644 index 0a5dc58c..00000000 --- a/src/Alpha_shapes/test/S4_100.off +++ /dev/null @@ -1,102 +0,0 @@ -OFF -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 -0.916381 -0.0512295 0.371049 0.141223 -0.182222 0.940836 -0.171362 -0.228599 --0.787145 -0.129213 0.568102 -0.202402 -0.0187866 -0.22093 -0.832882 -0.507095 --0.4702 -0.533814 0.353776 0.607286 --0.159798 -0.504771 0.263586 0.806346 -0.295546 0.162541 0.452931 0.825279 -0.242043 -0.107437 -0.913612 -0.308521 -0.875759 -0.113035 -0.469189 -0.0114505 -0.547877 -0.762247 -0.256972 -0.229729 --0.172302 0.521057 0.412013 -0.727363 --0.724729 -0.0574074 -0.0290602 0.686023 -0.700434 -0.102636 0.687285 0.162779 --0.681386 0.0946893 0.610047 0.393178 --0.847553 -0.357132 0.383743 0.0827718 -0.72297 -0.161631 -0.608517 0.284424 -0.757394 0.141549 0.196065 -0.606528 -0.78094 0.00901997 0.434536 0.448586 -0.14166 -0.619339 0.614589 -0.467582 -0.473105 -0.537832 -0.0103746 0.697711 --0.208004 0.536218 0.818027 0.00605288 -0.743694 -0.628926 0.188072 0.126488 --0.462228 -0.278147 0.35514 -0.76345 --0.17361 0.249211 0.758567 -0.57648 -0.416958 -0.254924 -0.576373 -0.654946 --0.590751 -0.286089 -0.424896 0.623402 --0.639538 -0.739693 -0.203745 0.0482932 -0.0731787 0.132121 0.864022 0.480266 --0.149644 -0.164724 -0.249746 -0.94239 --0.348592 0.0120379 -0.928656 -0.126239 -0.395328 -0.54513 0.149976 -0.723917 --0.974164 0.14707 0.157191 0.068302 --0.166425 0.119943 -0.627304 -0.751269 -0.031947 -0.358518 -0.708301 -0.607251 -0.93781 -0.155368 -0.30951 0.0240237 -0.276094 -0.753155 -0.597088 -0.00387459 --0.642876 -0.200551 -0.263517 -0.690687 -0.178711 0.604987 -0.262989 0.729993 --0.520347 0.497922 -0.676144 0.155374 --0.703999 0.500219 -0.484381 0.139789 --0.131013 0.835735 0.506779 0.166004 --0.536116 -0.566557 0.229226 0.582279 --0.334105 0.158252 0.926091 0.0754059 --0.0362677 0.296076 0.897108 0.325915 --0.57486 0.798575 0.15324 -0.0912754 -0.498602 0.0186805 0.72824 0.469801 --0.960329 0.0473356 0.261005 -0.0860505 -0.899134 -0.381392 -0.214508 0.00921711 -0.570576 0.567224 0.393019 -0.445237 --0.761763 -0.614589 -0.0546476 -0.197513 -0.188584 0.289531 0.174031 0.922129 --0.458506 -0.583876 0.639297 -0.2004 -0.785343 -0.21571 0.0794082 -0.574804 -0.0819036 0.65961 -0.247426 0.704973 -0.573125 0.49706 0.373026 0.534145 --0.513286 -0.626226 0.208535 -0.548536 -0.460558 0.468686 0.507832 -0.55707 -0.716158 -0.488201 0.388209 -0.313164 -0.881074 0.152441 0.380128 -0.236589 -0.885793 0.0386389 0.161009 -0.433537 --0.365162 0.298384 0.292846 0.831784 -0.364934 0.632269 -0.197205 -0.654346 --0.31469 -0.429991 0.665304 -0.522923 --0.734198 0.462914 -0.135691 -0.477756 --0.422885 0.674444 -0.364143 -0.483419 -0.829218 -0.154622 -0.381147 0.378439 -0.887881 0.310479 -0.109528 0.321363 --0.354398 -0.693974 0.456019 -0.429941 --0.492045 -0.160008 0.044387 0.854587 -0.0595532 0.158421 0.412577 -0.895062 --0.211441 0.491794 -0.153521 0.83058 --0.33558 -0.504711 0.353831 -0.71236 --0.735211 -0.197714 0.525626 0.379593 -0.465818 -0.424245 0.769469 -0.104627 --0.641071 -0.286339 -0.704442 -0.103923 --0.00446569 0.0249849 -0.194417 -0.980591 --0.610081 -0.252448 0.176698 -0.729966 --0.0859217 -0.154471 0.715027 0.676382 -0.091315 0.0723382 -0.855023 -0.505337 -0.165362 0.200983 -0.428242 -0.865373 --0.587465 0.303019 -0.152442 0.734729 -0.454946 -0.319828 0.437063 -0.706902 --0.384368 0.277509 0.879225 -0.0470385 -0.523335 -0.330233 -0.208592 0.757335 -0.895086 0.0448492 0.268089 -0.353466 --0.0272491 -0.567336 -0.72254 -0.39411 --0.0745014 -0.121818 -0.882466 0.448179 -0.382304 -0.240135 0.851109 -0.267941 --0.418057 -0.852847 -0.3128 0.00606452 --0.554046 0.304237 0.272381 -0.725453 -0.155115 -0.0894732 -0.245017 -0.952838 -0.114459 -0.130722 0.953669 0.245614 -0.0913002 -0.462466 0.244433 0.847374 --0.198849 0.0785111 0.131441 -0.967997 --0.303154 -0.686484 0.639333 0.167604 -0.521455 0.256835 -0.0584503 -0.811606 --0.109787 0.870544 0.161523 0.451676 diff --git a/src/Alpha_shapes/test/S8_10.off b/src/Alpha_shapes/test/S8_10.off deleted file mode 100644 index 1d67e10f..00000000 --- a/src/Alpha_shapes/test/S8_10.off +++ /dev/null @@ -1,12 +0,0 @@ -OFF -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 -0.0137399 -0.161581 -0.609142 -0.370872 -0.320669 -0.364053 0.24127 0.41416 --0.115313 -0.36425 0.190208 0.581871 0.204605 0.112527 0.313562 0.571337 -0.168272 -0.0746917 -0.635156 -0.214488 0.629498 -0.0812499 -0.337255 -0.00823068 -0.369896 -0.514626 -0.173493 -0.1551 -0.127105 0.384377 0.303936 -0.536566 --0.49013 -0.0388242 -0.0196532 0.463953 0.515962 -0.0756047 0.506276 0.119908 --0.434258 0.060347 0.388793 0.250579 -0.653127 -0.275207 0.295714 0.0637842 -0.596172 -0.133284 -0.501793 0.234541 0.428452 0.0800735 0.110912 -0.343109 -- cgit v1.2.3 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 --- CMakeLists.txt | 6 +- data/points/generator/hypergenerator.cpp | 9 +- src/Alpha_complex/example/CMakeLists.txt | 3 + .../example/Delaunay_triangulation_off_rw.cpp | 4 +- .../Simplex_tree_from_delaunay_triangulation.cpp | 16 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 339 +++++++++++++++++++++ src/Alpha_complex/include/gudhi/Alpha_shapes.h | 311 ------------------- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 50 ++- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 126 ++++++++ src/Alpha_complex/test/Alpha_shapes_unit_test.cpp | 126 -------- src/Alpha_complex/test/CMakeLists.txt | 14 +- src/CMakeLists.txt | 2 +- 12 files changed, 530 insertions(+), 476 deletions(-) create mode 100644 src/Alpha_complex/include/gudhi/Alpha_complex.h delete mode 100644 src/Alpha_complex/include/gudhi/Alpha_shapes.h create mode 100644 src/Alpha_complex/test/Alpha_complex_unit_test.cpp delete mode 100644 src/Alpha_complex/test/Alpha_shapes_unit_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 89440490..01108db9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,7 @@ else() message(STATUS "boost include dirs:" ${Boost_INCLUDE_DIRS}) include_directories(src/common/include/) - include_directories(src/Alpha_shapes/include/) + include_directories(src/Alpha_complex/include/) include_directories(src/Bottleneck/include/) include_directories(src/Contraction/include/) include_directories(src/Hasse_complex/include/) @@ -85,8 +85,8 @@ else() add_subdirectory(src/Skeleton_blocker/example) add_subdirectory(src/Contraction/example) add_subdirectory(src/Hasse_complex/example) - add_subdirectory(src/Alpha_shapes/example) - add_subdirectory(src/Alpha_shapes/test) + add_subdirectory(src/Alpha_complex/example) + add_subdirectory(src/Alpha_complex/test) add_subdirectory(src/Bottleneck/example) add_subdirectory(src/Bottleneck/test) diff --git a/data/points/generator/hypergenerator.cpp b/data/points/generator/hypergenerator.cpp index f4ea6b07..32ef450d 100644 --- a/data/points/generator/hypergenerator.cpp +++ b/data/points/generator/hypergenerator.cpp @@ -86,8 +86,13 @@ int main(int argc, char **argv) { } std::ofstream diagram_out(argv[3]); - diagram_out << "OFF" << std::endl; - diagram_out << points_number << " 0 0" << std::endl; + if (dimension == 3) { + diagram_out << "OFF" << std::endl; + diagram_out << points_number << " 0 0" << std::endl; + } else { + diagram_out << "nOFF" << std::endl; + diagram_out << dimension << " " << points_number << " 0 0" << std::endl; + } if (diagram_out.is_open()) { // Instanciate a random point generator diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 582a9322..258def49 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -22,6 +22,9 @@ if(CGAL_FOUND) 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 index fe889ec0..405b3cb9 100644 --- a/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp +++ b/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp @@ -63,7 +63,7 @@ int main(int argc, char **argv) { T dt(dimension); std::string offFileName(argv[1]); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(offFileName, dt); + 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); // ----- >> @@ -73,7 +73,7 @@ int main(int argc, char **argv) { std::string outFileName(argv[3]); std::string offOutputFile(outFileName); - Gudhi::alphashapes::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); + 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 0a24fb56..f09e6121 100644 --- a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -22,7 +22,7 @@ // to construct a Delaunay_triangulation from a OFF file #include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_shapes.h" +#include "gudhi/Alpha_complex.h" // to construct a simplex_tree from Delaunay_triangulation #include "gudhi/graph_simplicial_complex.h" @@ -62,16 +62,16 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // - // Init of an alpha-shape from a OFF file + // Init of an alpha-complex from a OFF file // // ---------------------------------------------------------------------------- - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); - std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; - std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; - std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; - std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; - //std::cout << alpha_shapes_from_file << std::endl; + std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; + 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; 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 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_ diff --git a/src/Alpha_complex/include/gudhi/Alpha_shapes.h b/src/Alpha_complex/include/gudhi/Alpha_shapes.h deleted file mode 100644 index f23df51a..00000000 --- a/src/Alpha_complex/include/gudhi/Alpha_shapes.h +++ /dev/null @@ -1,311 +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_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 alphashapes { - -#define Kinit(f) =k.f() - -/** \defgroup alpha_shapes Alpha shapes in dimension N - * -
Implementations:
- Alpha shapes 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 shapes 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. - * - * \implements FilteredComplex - * - */ -class Alpha_shapes { - 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-shape. - */ - 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 typeVectorPoint; - - private: - /** \brief Upper bound on the simplex tree of the simplicial complex.*/ - Gudhi::Simplex_tree<> st_; - - public: - - Alpha_shapes(std::string& off_file_name) { - // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function - Delaunay_triangulation dt(2); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << off_file_name << std::endl; - exit(-1); // ----- >> - } -#ifdef DEBUG_TRACES - std::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; - std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; -#endif // DEBUG_TRACES - init(dt); - } - - template - Alpha_shapes(T& triangulation) { - init(triangulation); - } - - ~Alpha_shapes() { } - - private: - - template - void init(T& triangulation) { - st_.set_dimension(triangulation.maximal_dimension()); - - // -------------------------------------------------------------------------------------------- - // bimap to retrieve vertex handles from points and vice versa - typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; - bimap_points_vh points_to_vh; - // Start to insert at handle = 0 - default integer value - Vertex_handle vertex_handle = Vertex_handle(); - // Loop on triangulation vertices list - for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { - points_to_vh.insert(bimap_points_vh::value_type(vit->point(), 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 << " " << points_to_vh.left.at((*vit)->point()); -#endif // DEBUG_TRACES - // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(points_to_vh.left.at((*vit)->point())); - } -#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_shapes::init insert_simplex_and_subfaces failed" << std::endl; - } - } - // -------------------------------------------------------------------------------------------- - - Filtration_value filtration_max = 0.0; - - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); - // -------------------------------------------------------------------------------------------- - // ### 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) { - typeVectorPoint 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(points_to_vh.right.at(vertex)); -#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_shapes_filtration = 0.0; - // No need to compute squared_radius on a single point - alpha is 0.0 - if (f_simplex_dim > 0) { - alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); - } - st_.assign_filtration(f_simplex, alpha_shapes_filtration); - filtration_max = fmax(filtration_max, alpha_shapes_filtration); -#ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; -#endif // DEBUG_TRACES - } - - // ### 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; -#endif // DEBUG_TRACES - // insert the Tau points in a vector for is_gabriel function - typeVectorPoint pointVector; - Vertex_handle vertexForGabriel = Vertex_handle(); - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { - pointVector.push_back(points_to_vh.right.at(vertex)); - } - // 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(), points_to_vh.right.at(vertex)) == pointVector.end()) { - // vertex is not found in Tau - vertexForGabriel = vertex; - // No need to continue loop - break; - } - } -#ifdef DEBUG_TRACES - std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; - bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) - != CGAL::ON_BOUNDED_SIDE; - std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; -#endif // DEBUG_TRACES - // ### If filt(Tau) is not NaN - // ### or Tau is not Gabriel of Sigma - if (!isnan(st_.filtration(f_boundary)) || - (is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) == CGAL::ON_BOUNDED_SIDE) - ) { - // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) - Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); - st_.assign_filtration(f_boundary, alpha_shapes_filtration); - filtration_max = fmax(filtration_max, alpha_shapes_filtration); -#ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; -#endif // DEBUG_TRACES - } - } - } - } - } - // -------------------------------------------------------------------------------------------- - -#ifdef DEBUG_TRACES - std::cout << "filtration_max=" << filtration_max << std::endl; -#endif // DEBUG_TRACES - st_.set_filtration(filtration_max); - } - - 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_shapes & alpha_shape) { - // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor - Gudhi::Simplex_tree<> st = alpha_shape.st_; - os << st << std::endl; - return os; - } -}; - -} // namespace alphashapes - -} // namespace Gudhi - -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ 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 index a4e5e2fe..8bda23b7 100644 --- 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 @@ -31,20 +31,22 @@ namespace Gudhi { -namespace alphashapes { +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 { - Complex& complex_; + private: + Complex* _complex; typedef typename Complex::Point Point; public: - explicit Delaunay_triangulation_off_visitor_reader(Complex& complex) : - complex_(complex) { } + // 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 @@ -59,7 +61,8 @@ class Delaunay_triangulation_off_visitor_reader { 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_.set_current_dimension(dim); + // Complex construction with dimension from file + _complex = new Complex(dim); } void point(const std::vector& point) { @@ -70,7 +73,7 @@ class Delaunay_triangulation_off_visitor_reader { } std::cout << std::endl; #endif // DEBUG_TRACES - complex_.insert(Point(point.size(), point.begin(), point.end())); + _complex->insert(Point(point.size(), point.begin(), point.end())); } void maximal_face(const std::vector& face) { @@ -89,6 +92,10 @@ class Delaunay_triangulation_off_visitor_reader { std::cout << "Delaunay_triangulation_off_visitor_reader::done" << std::endl; #endif // DEBUG_TRACES } + + Complex* get_complex() { + return _complex; + } }; /** @@ -103,12 +110,15 @@ class Delaunay_triangulation_off_reader { * 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, Complex& read_complex) : valid_(false) { + 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(read_complex); + 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; @@ -123,8 +133,16 @@ class Delaunay_triangulation_off_reader { return valid_; } + Complex* get_complex() { + if (valid_) + return _complex; + return nullptr; + + } + private: bool valid_; + Complex* _complex; }; template @@ -137,20 +155,20 @@ class Delaunay_triangulation_off_writer { * save_complex : complex that be outputted in the file * for now only save triangles. */ - Delaunay_triangulation_off_writer(const std::string & name_file, const Complex& save_complex) { + Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) { std::ofstream stream(name_file); if (stream.is_open()) { - if (save_complex.current_dimension() == 3) { + if (complex_ptr->current_dimension() == 3) { // OFF header stream << "OFF" << std::endl; // no endl on next line - don't know why... - stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; + 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 << save_complex.current_dimension() << " " << save_complex.number_of_vertices() << " " << - save_complex.number_of_finite_full_cells() << " 0"; + stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << + complex_ptr->number_of_finite_full_cells() << " 0"; } @@ -160,7 +178,7 @@ class Delaunay_triangulation_off_writer { int vertex_handle = int(); // Points list - for (auto vit = save_complex.vertices_begin(); vit != save_complex.vertices_end(); ++vit) { + 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 << " "; } @@ -169,7 +187,7 @@ class Delaunay_triangulation_off_writer { vertex_handle++; } - for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.finite_full_cells_end(); ++cit) { + 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) { @@ -185,7 +203,7 @@ class Delaunay_triangulation_off_writer { } }; -} // namespace alphashapes +} // namespace alphacomplex } // namespace Gudhi diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp new file mode 100644 index 00000000..38168f10 --- /dev/null +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -0,0 +1,126 @@ +/* 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 alpha_complex +#include +#include +#include +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Alpha_shapes/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 + +// 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 + +BOOST_AUTO_TEST_CASE( OFF_file ) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-complex from a 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 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; + 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 ) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-complex from a Delaunay triangulation + // + // ---------------------------------------------------------------------------- + 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); + + 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_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_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); +} + diff --git a/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp b/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp deleted file mode 100644 index d5db3bfa..00000000 --- a/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp +++ /dev/null @@ -1,126 +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 . - */ - -#define BOOST_TEST_MODULE alpha_shapes -#include -#include -#include -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_shapes.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 - -// 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 - -BOOST_AUTO_TEST_CASE( OFF_file ) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a OFF file - // - // ---------------------------------------------------------------------------- - std::string off_file_name("S4_100.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name, 4); - - const int DIMENSION = 4; - std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.filtration() == FILTRATION); - - const int NUMBER_OF_VERTICES = 100; - std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.num_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_SIMPLICES = 6779; - std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.num_simplices() == NUMBER_OF_SIMPLICES); - -} - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a Delauny triangulation - // - // ---------------------------------------------------------------------------- - T dt(8); - std::string off_file_name("S8_10.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - - Gudhi::alphashapes::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::alphashapes::Alpha_shapes alpha_shapes_from_dt(dt); - - const int DIMENSION = 8; - std::cout << "alpha_shapes_from_dt.dimension()=" << alpha_shapes_from_dt.dimension() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_shapes_from_dt.filtration()=" << alpha_shapes_from_dt.filtration() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.filtration() == FILTRATION); - - std::cout << "alpha_shapes_from_dt.num_vertices()=" << alpha_shapes_from_dt.num_vertices() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.num_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_SIMPLICES = 997; - std::cout << "alpha_shapes_from_dt.num_simplices()=" << alpha_shapes_from_dt.num_simplices() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.num_simplices() == NUMBER_OF_SIMPLICES); -} - diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 3cf97b71..72e8390a 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.6) -project(GUDHIAlphaShapesTest) +project(GUDHIAlphaComplexTest) # need CGAL 4.7 # cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. @@ -16,16 +16,16 @@ if(CGAL_FOUND) include_directories (BEFORE "../../include") add_definitions(-DDEBUG_TRACES) - add_executable ( AlphaShapesUnitTest Alpha_shapes_unit_test.cpp ) - target_link_libraries(AlphaShapesUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - add_test(AlphaShapesUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaShapesUnitTest) + 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) else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha complex feature.") endif() else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha complex feature. Version 4.6.0 is required.") endif () endif() -cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/Alpha_shapes/include/gudhi") +cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/Alpha_complex/include/gudhi") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ceb993fa..e0d5ff28 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,7 +37,7 @@ else() add_subdirectory(example/Skeleton_blocker) add_subdirectory(example/Contraction) add_subdirectory(example/Hasse_complex) - add_subdirectory(example/Alpha_shapes) + add_subdirectory(example/Alpha_complex) add_subdirectory(example/Bottleneck) endif() -- 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 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 4f18bf5115955c764f4eb15cd600a776f1a4d9ce Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 Jun 2015 14:35:35 +0000 Subject: Ignore this commented line git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@624 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0c8ce17217e7b110df0276f51295fd02af4b54e3 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 86b4e2b6..4596f3da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,7 +86,7 @@ else() 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) -- cgit v1.2.3 From 9e7a221884346501d5bcb06ad184e08f96938315 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 Jun 2015 14:58:02 +0000 Subject: From trunk, cpplint was removed git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@626 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 404ea81f038969fb4d96945cfb9856b8ee4ac12a --- src/Alpha_complex/test/CMakeLists.txt | 1 - src/common/test/CMakeLists.txt | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 4fe69ce5..0bd55433 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -28,4 +28,3 @@ if(CGAL_FOUND) endif () endif() -cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/Alpha_complex/include/gudhi") diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 22783caf..e4ac6c7b 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -37,8 +37,3 @@ if(CGAL_FOUND) endif () endif() - - - - -cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/common/include/gudhi") -- cgit v1.2.3 From 2a3afe37fa9423890f4747373c955d7195ce8f72 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 19 Jun 2015 10:57:11 +0000 Subject: Commit before changing example file name git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@628 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3e03055a89514f6308e6aed58a9bcb1d64c95a83 --- src/Alpha_complex/example/CMakeLists.txt | 5 ++-- .../Simplex_tree_from_delaunay_triangulation.cpp | 28 +++++++++------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 9129fdcf..04c0ba58 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -15,9 +15,8 @@ if(CGAL_FOUND) include( ${EIGEN3_USE_FILE} ) #add_definitions(-DDEBUG_TRACES) - add_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) - target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - + add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) + target_link_libraries(alphaoffreader ${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/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp index 1523372a..d129ebf7 100644 --- a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -24,13 +24,6 @@ #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 @@ -49,23 +42,24 @@ int main(int argc, char **argv) { std::string off_file_name(argv[1]); // ---------------------------------------------------------------------------- - // - // Init of an alpha-complex from an OFF file - // + // 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); - std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; - 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; + // ---------------------------------------------------------------------------- + // 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 Simplices in the filtration order, with [filtration value]:" << 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 << " " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; + 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; -- cgit v1.2.3 From 5ade372f809008bf41410455836d07c5efb6bdb9 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 19 Jun 2015 10:57:51 +0000 Subject: File name changed git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@629 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 25f954a52cd71e769a3820751080761eb350891d --- .../example/Alpha_complex_from_off.cpp | 66 ++++++++++++++++++++++ .../Simplex_tree_from_delaunay_triangulation.cpp | 66 ---------------------- 2 files changed, 66 insertions(+), 66 deletions(-) create mode 100644 src/Alpha_complex/example/Alpha_complex_from_off.cpp delete mode 100644 src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp new file mode 100644 index 00000000..d129ebf7 --- /dev/null +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -0,0 +1,66 @@ +/* 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" + +#include +#include +#include + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " filename.off" << 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]); + } + + std::string off_file_name(argv[1]); + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from an OFF file + // ---------------------------------------------------------------------------- + Gudhi::alphacomplex::Alpha_complex<> alpha_complex_from_file(off_file_name); + + // ---------------------------------------------------------------------------- + // 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 << " ( "; + 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; +} \ 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 deleted file mode 100644 index d129ebf7..00000000 --- a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp +++ /dev/null @@ -1,66 +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/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" - -#include -#include -#include - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off" << 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]); - } - - std::string off_file_name(argv[1]); - - // ---------------------------------------------------------------------------- - // Init of an alpha complex from an OFF file - // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex<> alpha_complex_from_file(off_file_name); - - // ---------------------------------------------------------------------------- - // 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 << " ( "; - 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; -} \ No newline at end of file -- 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 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 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 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 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 fc092e56fd3148c40b054d9cd05b05ed3c171295 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 25 Jun 2015 07:39:26 +0000 Subject: Modification for doxygen to be generated from user version (to fix bad path in doc) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@642 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 68362c2ab9d83a8daa31bcb9d7799216c8ccf94c --- scripts/generate_version.sh | 20 ++++++++-------- .../example/alphaoffreader_for_doc.txt | 27 ++++++++++++++++++++++ src/Alpha_complex/test/alphaoffreader_for_doc.txt | 27 ---------------------- src/Doxyfile | 17 +++++++------- .../example/dtoffrw_alphashapedoc_result.txt | 3 +++ src/common/test/dtoffrw_alphashapedoc_result.txt | 3 --- 6 files changed, 48 insertions(+), 49 deletions(-) create mode 100644 src/Alpha_complex/example/alphaoffreader_for_doc.txt delete mode 100644 src/Alpha_complex/test/alphaoffreader_for_doc.txt create mode 100644 src/common/example/dtoffrw_alphashapedoc_result.txt delete mode 100644 src/common/test/dtoffrw_alphashapedoc_result.txt diff --git a/scripts/generate_version.sh b/scripts/generate_version.sh index 4d28cf53..e7575282 100755 --- a/scripts/generate_version.sh +++ b/scripts/generate_version.sh @@ -2,6 +2,8 @@ #usage bash generate_version.sh : dont generate if svn st non empty #usage bash generate_version.sh -f : generate even if svn is empty #usage bash generate_version.sh -f DIR : generate even if svn is empty and save library in dir +# +# 23/06/2015 - Remove source, add biblio, and doc # VERSION CHECK ROOT_DIR=.. VERSION_FILE="$ROOT_DIR/Version.txt" @@ -48,11 +50,13 @@ cp $ROOT_DIR/COPYING $VERSION_DIR cp -R $ROOT_DIR/data $VERSION_DIR cp $ROOT_DIR/src/CMakeLists.txt $VERSION_DIR cp $ROOT_DIR/src/Doxyfile $VERSION_DIR +cp -R $ROOT_DIR/biblio $VERSION_DIR # PACKAGE LEVEL COPY PACKAGE_INC_DIR="/include" -PACKAGE_SRC_DIR="/source" +#PACKAGE_SRC_DIR="/source" PACKAGE_EX_DIR="/example" +PACKAGE_DOC_DIR="/doc" for package in `ls $ROOT_DIR/src/` do echo $package @@ -77,20 +81,16 @@ do fi cp -R $ROOT_DIR/src/$package$PACKAGE_INC_DIR/* $VERSION_DIR$PACKAGE_INC_DIR/ fi - if [ -d "$ROOT_DIR/src/$package$PACKAGE_SRC_DIR" ] - then - if [ ! -d "$VERSION_DIR$PACKAGE_SRC_DIR" ] - then - # MUST CREATE DIRECTORY ON FIRST LOOP - mkdir $VERSION_DIR$PACKAGE_INC_DIR - fi - cp -R $ROOT_DIR/src/$package$PACKAGE_SRC_DIR/* $VERSION_DIR$PACKAGE_SRC_DIR/ - fi if [ -d "$ROOT_DIR/src/$package$PACKAGE_EX_DIR" ] then mkdir -p $VERSION_DIR$PACKAGE_EX_DIR/$package cp -R $ROOT_DIR/src/$package$PACKAGE_EX_DIR/* $VERSION_DIR$PACKAGE_EX_DIR/$package fi + if [ -d "$ROOT_DIR/src/$package$PACKAGE_DOC_DIR" ] + then + mkdir -p $VERSION_DIR$PACKAGE_DOC_DIR/$package + cp -R $ROOT_DIR/src/$package$PACKAGE_DOC_DIR/* $VERSION_DIR$PACKAGE_DOC_DIR/$package + fi fi fi done diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc.txt b/src/Alpha_complex/example/alphaoffreader_for_doc.txt new file mode 100644 index 00000000..1153f097 --- /dev/null +++ b/src/Alpha_complex/example/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/Alpha_complex/test/alphaoffreader_for_doc.txt b/src/Alpha_complex/test/alphaoffreader_for_doc.txt deleted file mode 100644 index 1153f097..00000000 --- a/src/Alpha_complex/test/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]: - ( 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 a84c4897..0724de1c 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -672,7 +672,7 @@ LAYOUT_FILE = # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. -CITE_BIB_FILES = ../biblio/bibliography.bib +CITE_BIB_FILES = biblio/bibliography.bib #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages @@ -811,10 +811,9 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = common/example \ - common/test \ - Alpha_complex/example \ - Alpha_complex/test \ +EXAMPLE_PATH = example/common/ \ + example/Alpha_complex/ + # 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 @@ -833,10 +832,10 @@ EXAMPLE_RECURSIVE = NO # that contain images that are to be included in the documentation (see the # \image command). -IMAGE_PATH = Skeleton_blocker/doc/ \ - Alpha_complex/doc/ \ - common/doc/ \ - Contraction/doc/ +IMAGE_PATH = doc/Skeleton_blocker/ \ + doc/Alpha_complex/ \ + doc/common/ \ + doc/Contraction/ # The INPUT_FILTER tag can be used to specify a program that doxygen should diff --git a/src/common/example/dtoffrw_alphashapedoc_result.txt b/src/common/example/dtoffrw_alphashapedoc_result.txt new file mode 100644 index 00000000..57761d14 --- /dev/null +++ b/src/common/example/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_alphashapedoc_result.txt b/src/common/test/dtoffrw_alphashapedoc_result.txt deleted file mode 100644 index 57761d14..00000000 --- a/src/common/test/dtoffrw_alphashapedoc_result.txt +++ /dev/null @@ -1,3 +0,0 @@ -Number of vertices= 7 -Number of finite full cells= 6 - -- cgit v1.2.3 From e1b8ee37a896ddb8d733ecd8752eb70307521f7a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 25 Jun 2015 08:25:54 +0000 Subject: File was not renamed here git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@643 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ea5a10408d8f44eb508ae68cb3ed0699dc4eba93 --- src/common/example/CMakeLists.txt | 2 +- src/common/test/dtoffrw_unit_test.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index ae30da54..4cb03dbe 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -15,7 +15,7 @@ if(CGAL_FOUND) 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) + add_test(dtoffrw ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp index 4905d845..d2705955 100644 --- a/src/common/test/dtoffrw_unit_test.cpp +++ b/src/common/test/dtoffrw_unit_test.cpp @@ -43,7 +43,7 @@ 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"); + Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphacomplexdoc.off"); // Check the read operation was correct BOOST_CHECK(off_reader.is_valid()); @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) 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"); + Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphacomplexdoc.off"); // Retrieve the triangulation T* triangulation = off_reader.get_complex(); -- cgit v1.2.3 From ed8ae292df7b486b71f573431e17e3466a0a2ace Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 25 Jun 2015 09:01:59 +0000 Subject: coface removal - added but not needed git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@644 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3598444f908fd791b111c8ab8eb18a3c0a15fc16 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 87 --------------------------- 1 file changed, 87 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 32fb2f43..9a06b262 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -837,92 +837,6 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } - //---------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------- - private: - - /** Recursive search of cofaces - */ - template - void rec_coface(RandomAccessVertexRange &vertices, Siblings *curr_sib, Dictionary *curr_res, std::vector& cofaces, unsigned int length, unsigned long codimension) { - for (auto sib = curr_sib->members().begin(); sib != curr_sib->members().end() && (vertices.empty() || sib->first <= vertices[vertices.size() - 1]); ++sib) { - bool continueRecursion = (codimension == length || curr_res->size() <= codimension); // dimension of actual simplex <= codimension - if (vertices.empty()) { - if (curr_res->size() >= length && continueRecursion) - // If we reached the end of the vertices, and the simplex has more vertices than the given simplex, we found a coface - { - curr_res->emplace(sib->first, sib->second); - bool egalDim = (codimension == length || curr_res->size() == codimension); // dimension of actual simplex == codimension - if (egalDim) - cofaces.push_back(*curr_res); - if (has_children(sib)) - rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); - curr_res->erase(curr_res->end() - 1); - } - } else if (continueRecursion) { - if (sib->first == vertices[vertices.size() - 1]) // If curr_sib matches with the top vertex - { - curr_res->emplace(sib->first, sib->second); - bool egalDim = (codimension == length || curr_res->size() == codimension); // dimension of actual simplex == codimension - if (vertices.size() == 1 && curr_res->size() > length && egalDim) - cofaces.push_back(*curr_res); - if (has_children(sib)) { // Rec call - Vertex_handle tmp = vertices[vertices.size() - 1]; - vertices.pop_back(); - rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); - vertices.push_back(tmp); - } - curr_res->erase(curr_res->end() - 1); - } else // (sib->first < vertices[vertices.size()-1]) - { - if (has_children(sib)) { - curr_res->emplace(sib->first, sib->second); - rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); - curr_res->erase(curr_res->end() - 1); - } - } - } - } - } - - public: - - /** \brief Compute the cofaces of a n simplex - * \param vertices List of vertices which represent the n simplex. - * \param codimension The function returns the n+codimension-simplices. If codimension = 0, return all cofaces - * \return Vector of Dictionary, empty vector if no cofaces found. - * \warning n+codimension must be lower than Simplex_tree dimension, otherwise an an empty vector is returned. - */ - - template - std::vector coface(const RandomAccessVertexRange &vertices, int codimension) { - RandomAccessVertexRange copy = vertices; - std::vector cofaces; - std::sort(copy.begin(), copy.end(), std::greater()); // must be sorted in decreasing order - if (root_.members().empty()) { - std::cerr << "Simplex_tree::coface - empty Simplex_tree" << std::endl; - return cofaces; // ----->> - } - if (vertices.empty()) { - std::cerr << "Simplex_tree::coface - empty vertices list" << std::endl; - return cofaces; // ----->> - } - if (codimension < 0) { - std::cerr << "Simplex_tree::coface - codimension is empty" << std::endl; - return cofaces; // ----->> - } - if (codimension + vertices.size() >= (unsigned long) dimension_) { - std::cerr << "Simplex_tree::coface - codimension + vertices list size cannot be greater than Simplex_tree dimension" << std::endl; - return cofaces; // ----->> - } - std::sort(copy.begin(), copy.end(), std::greater()); // must be sorted in decreasing order - Dictionary res; - rec_coface(copy, &root_, &res, cofaces, vertices.size(), codimension + vertices.size()); - return cofaces; - } - - //---------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------- private: Vertex_handle null_vertex_; @@ -950,7 +864,6 @@ std::ostream& operator<<(std::ostream & os, Simplex_tree & st) { } return os; } - template std::istream& operator>>(std::istream & is, Simplex_tree & st) { // assert(st.num_simplices() == 0); -- 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(-) 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(-) 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 f572657e071e25e6fddea4950096e7eefc72072e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 10 Aug 2015 09:26:11 +0000 Subject: fix bad merge in src/CMakeLists.txt Remove commented lines from UT git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@726 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c0d0c1412205aacbedaa0a562ba5e1e12513020b --- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 4 ++-- src/CMakeLists.txt | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 4202c9e9..b7aceb5e 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -37,7 +37,7 @@ // Use dynamic_dimension_tag for the user to be able to set dimension 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) { // ---------------------------------------------------------------------------- // @@ -86,7 +86,7 @@ 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(); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0af1a6d..7b30f77a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -47,7 +47,6 @@ else() add_subdirectory(example/Hasse_complex) add_subdirectory(example/Alpha_complex) add_subdirectory(example/Bottleneck) - add_subdirectory(example/Bottleneck) # GudhUI add_subdirectory(GudhUI) -- 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(-) 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(-) 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(-) 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(-) 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(-) 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 4b44247f14ddd84bf3e58ba53fe93a3e793f0ce4 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 1 Sep 2015 07:50:33 +0000 Subject: Documentation fix (starts at 0 and not 1 + alpha shape was not correct) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@765 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 99f8d4cd274778f5d7aac04afa84b780dc3678ec --- src/Alpha_complex/doc/Intro_alpha_complex.h | 10 +-- src/Alpha_complex/doc/alpha_complex_doc.ipe | 64 ++++++++--------- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 46226 -> 64997 bytes src/Alpha_complex/doc/alpha_complex_doc_135.ipe | 78 ++++++++++----------- src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 94098 -> 120335 bytes .../doc/alpha_complex_doc_alpha_shape.ipe | 75 +++++++++----------- .../doc/alpha_complex_doc_alpha_shape.png | Bin 70425 -> 136492 bytes 7 files changed, 108 insertions(+), 119 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 34af2b98..d266219b 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -35,7 +35,7 @@ namespace alphacomplex { * * 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 + * 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. @@ -54,7 +54,7 @@ namespace alphacomplex { * * When launching: * - * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off + * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off 60.0 * \endcode * * the program output is: @@ -77,7 +77,7 @@ namespace alphacomplex { * \For{i : dimension $\rightarrow$ 1} * \ForAll{$\sigma$ of dimension i} * \If {filtration($\sigma$) is NaN} - * \State filtration($\sigma$) = $\alpha(\sigma)$ + * \State filtration($\sigma$) = $\alpha^2(\sigma)$ * \EndIf * \ForAll{$\tau$ face of $\sigma$} \Comment{propagate alpha filtration value} * \If {filtration($\tau$) is not NaN} @@ -105,8 +105,8 @@ namespace alphacomplex { * * \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 + * In the example above, the alpha shape of \f$\alpha^2_{74} < \alpha^2 < \alpha^2_{73}\f$ is the alpha complex where the + * \f$\alpha^2_{74} <\f$ filtration value \f$< \alpha^2_{73}\f$ as described in \cite AlphaShapesIntroduction * * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" * \copyright GNU General Public License v3. diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe index 6257b2f4..b5601143 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -1,7 +1,7 @@ - + @@ -260,13 +260,13 @@ h 320 580 l Delaunay triangulation -1 -2 -3 -4 -5 -6 -7 +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -285,30 +285,30 @@ h 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 +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 diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index ff51ea9a..297c39ae 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 df55639a..28b893b8 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 @@ - + @@ -259,14 +259,14 @@ h 350 520 l 320 580 l -Cell [5,3,1] -1 -2 -3 -4 -5 -6 -7 +Cell [4,2,0] +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -293,7 +293,7 @@ h 243.428 591.569 m 186.061 643.28 l -$\alpha_{531}$ +$\alpha_{420}$ @@ -321,16 +321,16 @@ h 350 520 l 320 580 l -[3,1] is Gabriel $\rightarrow$ $\alpha_{31}$ is not$\\$ +[2,0] is Gabriel $\rightarrow$ $\alpha_{20}$ is not$\\$ modified (NaN) -1 -2 -3 -4 -5 -6 -7 +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -349,7 +349,7 @@ modified (NaN) 320 580 l 280 660 l -$\alpha_{31}$ +$\alpha_{20}$ 290 530 m 320 580 l @@ -389,14 +389,14 @@ modified (NaN) 350 520 l 320 580 l -[1,5] is not Gabriel $\rightarrow$ $\alpha_{15} = \alpha_{135}$ -1 -2 -3 -4 -5 -6 -7 +[0,4] is not Gabriel $\rightarrow$ $\alpha_{40} = \alpha_{420}$ +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -415,7 +415,7 @@ modified (NaN) 320 580 l 280 660 l -$\alpha_{15}$ +$\alpha_{40}$ 290 530 m 280 660 l @@ -450,12 +450,12 @@ modified (NaN) 350 520 l 320 580 l -1 -2 -3 -4 -6 -7 +0 +1 +2 +3 +5 +6 280 660 m 300 710 l @@ -474,8 +474,8 @@ modified (NaN) 320 580 l 280 660 l -$\alpha_{35}$ -5 +$\alpha_{42}$ +4 406.093 497.775 m 446.094 418.092 l @@ -488,7 +488,7 @@ modified (NaN) 425.854 457.774 m 470.795 457.774 l -[3,5] is Gabriel $\rightarrow$ $\alpha_{35}$ is not modified (NaN) +[2,4] is Gabriel $\rightarrow$ $\alpha_{42}$ is not modified (NaN) 205.028 596.091 m @@ -502,9 +502,9 @@ modified (NaN) 341.123 594.316 m 413.904 554.079 l -For all faces of [5,3,1] +For all faces of [4,2,0] N.B. : is Gabriel on a single point has no sense. -Dimension =2 - $\sigma$ = [5,3,1] +Dimension =2 - $\sigma$ = [4,2,0] 247.333 430.892 m diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png index edf61368..8ce6a426 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_doc_alpha_shape.ipe b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe index 192ea772..7563cf3d 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe @@ -1,7 +1,7 @@ - + @@ -240,37 +240,37 @@ 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 +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 @@ -398,15 +398,9 @@ h 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 @@ -449,11 +443,6 @@ h 80 580 l -80 580 m -110 520 l -110 520 l - - 130 580 m 130 690 l diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png index 516de126..87da0884 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png and b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png differ -- cgit v1.2.3 From cdd296b1c849cde74835d4043b9c4ecfe0ab16c2 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 1 Sep 2015 08:04:55 +0000 Subject: doc images size was not correct. bad cut in simplex_tree.h (assign_key was badly removed). git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@766 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 05761f615e4518d7816c08121402980625409014 --- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 64997 -> 46746 bytes src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 120335 -> 127130 bytes .../doc/alpha_complex_doc_alpha_shape.png | Bin 136492 -> 62759 bytes src/Simplex_tree/include/gudhi/Simplex_tree.h | 6 ++++++ 4 files changed, 6 insertions(+) diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index 297c39ae..601ac051 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.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png index 8ce6a426..5dce5edd 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_doc_alpha_shape.png b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png index 87da0884..2d5f59a3 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png and b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png differ diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index bda7e72a..4a75852e 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -574,6 +574,12 @@ class Simplex_tree { } public: + /** \brief Assign a value 'key' to the key of the simplex + * represented by the Simplex_handle 'sh'. */ + void assign_key(Simplex_handle sh, Simplex_key key) { + sh->second.assign_key(key); + } + /** Returns the two Simplex_handle corresponding to the endpoints of * and edge. sh must point to a 1-dimensional simplex. This is an * optimized version of the boundary computation. */ -- cgit v1.2.3 From 0d55fc06c82882327a8af82b20fc001b7cd71a66 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 1 Sep 2015 13:55:49 +0000 Subject: order was not correct in rec_insert_simplex_and_subfaces. + UT fix according to this fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@767 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a6c7bcc3776e01c2247fbd862b4a3842b76aefe0 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 13 ++- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 139 +++++++++++++++-------- 2 files changed, 104 insertions(+), 48 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 4a75852e..279327f7 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -540,7 +540,7 @@ class Simplex_tree { 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_inserted.insert(to_be_inserted.begin(), to_be_propagated.begin(), to_be_propagated.end()); to_be_propagated = to_be_inserted; // to_be_inserted treatment @@ -548,8 +548,14 @@ class Simplex_tree { simplex_tbi.push_back(last_vertex); } std::vector last_simplex(1, last_vertex); - to_be_inserted.push_back(last_simplex); - + to_be_inserted.insert(to_be_inserted.begin(), last_simplex); + // i.e. (0,1,2) => + // [to_be_inserted | to_be_propagated] = [(1) (0,1) | (0)] + // [to_be_inserted | to_be_propagated] = [(2) (0,2) (1,2) (0,1,2) | (0) (1) (0,1)] + // N.B. : it is important the last inserted to be the highest in dimension + // in order to return the "last" insert_simplex result + + // insert all to_be_inserted for (auto& simplex_tbi : to_be_inserted) { insert_result = insert_simplex(simplex_tbi, filtration); } @@ -562,6 +568,7 @@ class Simplex_tree { exit(-1); } std::vector first_simplex(1, the_simplex.back()); + // i.e. (0,1,2) => [to_be_inserted | to_be_propagated] = [(0) | ] to_be_inserted.push_back(first_simplex); insert_result = insert_simplex(first_simplex, filtration); diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 20403e2a..9340aaa3 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -157,16 +157,16 @@ void set_and_test_simplex_tree_dim_fil(typeST& simplexTree, int vectorSize, cons std::cout << " set_and_test_simplex_tree_dim_fil - max_fil=" << max_fil << std::endl; } - + BOOST_CHECK(simplexTree.dimension() == dim_max); BOOST_CHECK(AreAlmostTheSame(simplexTree.filtration(), max_fil)); // Another way to count simplices: - long long int num_simp = 0; + size_t num_simp = 0; for (auto f_simplex : simplexTree.complex_simplex_range()) { num_simp++; } - + BOOST_CHECK(simplexTree.num_simplices() == num_simp); } @@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ FIRST std::cout << " - INSERT 0" << std::endl; - typeVectorVertex firstSimplexVector { 0 }; + typeVectorVertex firstSimplexVector{0}; BOOST_CHECK(firstSimplexVector.size() == 1); typeSimplex firstSimplex = std::make_pair(firstSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); typePairSimplexBool returnValue = st.insert_simplex(firstSimplex.first, firstSimplex.second); @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ SECOND std::cout << " - INSERT 1" << std::endl; - typeVectorVertex secondSimplexVector { 1 }; + typeVectorVertex secondSimplexVector{1}; BOOST_CHECK(secondSimplexVector.size() == 1); typeSimplex secondSimplex = std::make_pair(secondSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); returnValue = st.insert_simplex(secondSimplex.first, secondSimplex.second); @@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ THIRD std::cout << " - INSERT (0,1)" << std::endl; - typeVectorVertex thirdSimplexVector { 0, 1 }; + typeVectorVertex thirdSimplexVector{0, 1}; BOOST_CHECK(thirdSimplexVector.size() == 2); typeSimplex thirdSimplex = std::make_pair(thirdSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); returnValue = st.insert_simplex(thirdSimplex.first, thirdSimplex.second); @@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ FOURTH std::cout << " - INSERT 2" << std::endl; - typeVectorVertex fourthSimplexVector { 2 }; + typeVectorVertex fourthSimplexVector{2}; BOOST_CHECK(fourthSimplexVector.size() == 1); typeSimplex fourthSimplex = std::make_pair(fourthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); returnValue = st.insert_simplex(fourthSimplex.first, fourthSimplex.second); @@ -243,7 +243,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ FIFTH std::cout << " - INSERT (2,0)" << std::endl; - typeVectorVertex fifthSimplexVector { 2, 0 }; + typeVectorVertex fifthSimplexVector{2, 0}; BOOST_CHECK(fifthSimplexVector.size() == 2); typeSimplex fifthSimplex = std::make_pair(fifthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); returnValue = st.insert_simplex(fifthSimplex.first, fifthSimplex.second); @@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ SIXTH std::cout << " - INSERT (2,1)" << std::endl; - typeVectorVertex sixthSimplexVector { 2, 1 }; + typeVectorVertex sixthSimplexVector{2, 1}; BOOST_CHECK(sixthSimplexVector.size() == 2); typeSimplex sixthSimplex = std::make_pair(sixthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); returnValue = st.insert_simplex(sixthSimplex.first, sixthSimplex.second); @@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ SEVENTH std::cout << " - INSERT (2,1,0)" << std::endl; - typeVectorVertex seventhSimplexVector { 2, 1, 0 }; + typeVectorVertex seventhSimplexVector{2, 1, 0}; BOOST_CHECK(seventhSimplexVector.size() == 3); typeSimplex seventhSimplex = std::make_pair(seventhSimplexVector, Filtration_value(THIRD_FILTRATION_VALUE)); returnValue = st.insert_simplex(seventhSimplex.first, seventhSimplex.second); @@ -276,7 +276,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ EIGHTH std::cout << " - INSERT 3" << std::endl; - typeVectorVertex eighthSimplexVector { 3 }; + typeVectorVertex eighthSimplexVector{3}; BOOST_CHECK(eighthSimplexVector.size() == 1); typeSimplex eighthSimplex = std::make_pair(eighthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); returnValue = st.insert_simplex(eighthSimplex.first, eighthSimplex.second); @@ -287,7 +287,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ NINETH std::cout << " - INSERT (3,0)" << std::endl; - typeVectorVertex ninethSimplexVector { 3, 0 }; + typeVectorVertex ninethSimplexVector{3, 0}; BOOST_CHECK(ninethSimplexVector.size() == 2); typeSimplex ninethSimplex = std::make_pair(ninethSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); returnValue = st.insert_simplex(ninethSimplex.first, ninethSimplex.second); @@ -298,7 +298,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ TENTH std::cout << " - INSERT 0 (already inserted)" << std::endl; - typeVectorVertex tenthSimplexVector { 0 }; + typeVectorVertex tenthSimplexVector{0}; BOOST_CHECK(tenthSimplexVector.size() == 1); // With a different filtration value typeSimplex tenthSimplex = std::make_pair(tenthSimplexVector, Filtration_value(FOURTH_FILTRATION_VALUE)); @@ -313,7 +313,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ ELEVENTH std::cout << " - INSERT (2,1,0) (already inserted)" << std::endl; - typeVectorVertex eleventhSimplexVector { 2, 1, 0 }; + typeVectorVertex eleventhSimplexVector{2, 1, 0}; BOOST_CHECK(eleventhSimplexVector.size() == 3); typeSimplex eleventhSimplex = std::make_pair(eleventhSimplexVector, Filtration_value(FOURTH_FILTRATION_VALUE)); returnValue = st.insert_simplex(eleventhSimplex.first, eleventhSimplex.second); @@ -375,60 +375,122 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { } +bool sort_in_decr_order (Vertex_handle i,Vertex_handle j) { return (i>j); } + BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { - // TEST OF INSERTION + // TEST OF INSERTION WITH SUBFACES std::cout << "********************************************************************" << std::endl; - std::cout << "TEST OF INSERTION" << std::endl; + std::cout << "TEST OF INSERTION WITH SUBFACES" << std::endl; typeST st; + typePairSimplexBool returnValue; + int position = 0; // ++ FIRST std::cout << " - INSERT (2,1,0)" << std::endl; - typeVectorVertex SimplexVector1 { 2, 1, 0 }; + typeVectorVertex SimplexVector1{2, 1, 0}; BOOST_CHECK(SimplexVector1.size() == 3); - st.insert_simplex_and_subfaces(SimplexVector1); + returnValue = st.insert_simplex_and_subfaces(SimplexVector1); BOOST_CHECK(st.num_vertices() == (size_t) 3); // +3 (2, 1 and 0 are not existing) + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector1.begin(), SimplexVector1.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector1[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector1[position]); + position++; + } + // ++ SECOND std::cout << " - INSERT 3" << std::endl; - typeVectorVertex SimplexVector2 { 3 }; + typeVectorVertex SimplexVector2{3}; BOOST_CHECK(SimplexVector2.size() == 1); - st.insert_simplex_and_subfaces(SimplexVector2); + returnValue = st.insert_simplex_and_subfaces(SimplexVector2); BOOST_CHECK(st.num_vertices() == (size_t) 4); // +1 (3 is not existing) + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector2.begin(), SimplexVector2.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector2[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector2[position]); + position++; + } + // ++ THIRD std::cout << " - INSERT (0,3)" << std::endl; - typeVectorVertex SimplexVector3 { 3, 0 }; + typeVectorVertex SimplexVector3{3, 0}; BOOST_CHECK(SimplexVector3.size() == 2); - st.insert_simplex_and_subfaces(SimplexVector3); + returnValue = st.insert_simplex_and_subfaces(SimplexVector3); BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented (all are existing) + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector3.begin(), SimplexVector3.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector3[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector3[position]); + position++; + } + // ++ FOURTH std::cout << " - INSERT (1,0) (already inserted)" << std::endl; - typeVectorVertex SimplexVector4 { 1, 0 }; + typeVectorVertex SimplexVector4{1, 0}; BOOST_CHECK(SimplexVector4.size() == 2); - st.insert_simplex_and_subfaces(SimplexVector4); + returnValue = st.insert_simplex_and_subfaces(SimplexVector4); BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented (all are existing) + // Check it was not inserted (already there from {2,1,0} insertion) + BOOST_CHECK(false == returnValue.second); + // ++ FIFTH std::cout << " - INSERT (3,4,5)" << std::endl; - typeVectorVertex SimplexVector5 { 3, 4, 5 }; + typeVectorVertex SimplexVector5{3, 4, 5}; BOOST_CHECK(SimplexVector5.size() == 3); - st.insert_simplex_and_subfaces(SimplexVector5); + returnValue = st.insert_simplex_and_subfaces(SimplexVector5); BOOST_CHECK(st.num_vertices() == (size_t) 6); + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector5.begin(), SimplexVector5.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector5[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector5[position]); + position++; + } + // ++ SIXTH std::cout << " - INSERT (0,1,6,7)" << std::endl; - typeVectorVertex SimplexVector6 { 0, 1, 6, 7 }; + typeVectorVertex SimplexVector6{0, 1, 6, 7}; BOOST_CHECK(SimplexVector6.size() == 4); - st.insert_simplex_and_subfaces(SimplexVector6); + returnValue = st.insert_simplex_and_subfaces(SimplexVector6); BOOST_CHECK(st.num_vertices() == (size_t) 8); // +2 (6 and 7 are not existing - 0 and 1 are already existing) + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector6.begin(), SimplexVector6.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector6[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector6[position]); + position++; + } + /* Inserted simplex: */ /* 1 6 */ /* o---o */ @@ -444,23 +506,10 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { /* A facet [3,4,5] */ /* A cell [0,1,6,7] */ - typeSimplex simplexPair1 = std::make_pair(SimplexVector1, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair2 = std::make_pair(SimplexVector2, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair3 = std::make_pair(SimplexVector3, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair4 = std::make_pair(SimplexVector4, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair5 = std::make_pair(SimplexVector5, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair6 = std::make_pair(SimplexVector6, DEFAULT_FILTRATION_VALUE); - test_simplex_tree_contains(st, simplexPair1, 6); // (2,1,0) is in position 6 - test_simplex_tree_contains(st, simplexPair2, 7); // (3) is in position 7 - test_simplex_tree_contains(st, simplexPair3, 8); // (3,0) is in position 8 - test_simplex_tree_contains(st, simplexPair4, 2); // (1,0) is in position 2 - test_simplex_tree_contains(st, simplexPair5, 14); // (3,4,5) is in position 14 - test_simplex_tree_contains(st, simplexPair6, 26); // (7,6,1,0) is in position 26 - // ------------------------------------------------------------------------------------------------------------------ // Find in the simplex_tree // ------------------------------------------------------------------------------------------------------------------ - typeVectorVertex simpleSimplexVector { 1 }; + typeVectorVertex simpleSimplexVector{1}; Simplex_tree<>::Simplex_handle simplexFound = st.find(simpleSimplexVector); std::cout << "**************IS THE SIMPLEX {1} IN THE SIMPLEX TREE ?\n"; if (simplexFound != st.null_simplex()) @@ -470,7 +519,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { // Check it is found BOOST_CHECK(simplexFound != st.null_simplex()); - typeVectorVertex unknownSimplexVector { 15 }; + typeVectorVertex unknownSimplexVector{15}; simplexFound = st.find(unknownSimplexVector); std::cout << "**************IS THE SIMPLEX {15} IN THE SIMPLEX TREE ?\n"; if (simplexFound != st.null_simplex()) @@ -489,7 +538,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { // Check it is found BOOST_CHECK(simplexFound != st.null_simplex()); - typeVectorVertex otherSimplexVector { 1, 15 }; + typeVectorVertex otherSimplexVector{1, 15}; simplexFound = st.find(otherSimplexVector); std::cout << "**************IS THE SIMPLEX {15,1} IN THE SIMPLEX TREE ?\n"; if (simplexFound != st.null_simplex()) @@ -499,7 +548,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { // Check it is NOT found BOOST_CHECK(simplexFound == st.null_simplex()); - typeVectorVertex invSimplexVector { 1, 2, 0 }; + typeVectorVertex invSimplexVector{1, 2, 0}; simplexFound = st.find(invSimplexVector); std::cout << "**************IS THE SIMPLEX {1,2,0} IN THE SIMPLEX TREE ?\n"; if (simplexFound != st.null_simplex()) -- cgit v1.2.3 From 89d8caff43f3c38ee3ce3fd96000eaa549ba0481 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 1 Sep 2015 15:04:46 +0000 Subject: UT fix to compile and run under osX git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@768 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a8351f5bd12a2d5e4869a61c298ddf76ad04f91d --- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 8 ++++---- src/common/test/dtoffrw_unit_test.cpp | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index b2597eff..7a0800e4 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -20,10 +20,10 @@ * along with this program. If not, see . */ -#define BOOST_TEST_MODULE alpha_complex -#include -#include -#include +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "alpha_complex" +#include + #include #include diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp index d2705955..ada218ac 100644 --- a/src/common/test/dtoffrw_unit_test.cpp +++ b/src/common/test/dtoffrw_unit_test.cpp @@ -20,8 +20,6 @@ * 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" @@ -32,9 +30,9 @@ #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; -- cgit v1.2.3 -- cgit v1.2.3 From 62937147e40a7d2da7aa7a7a604808feeccaa75e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 25 Sep 2015 14:57:29 +0000 Subject: Add bitmap cubical complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@794 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 50d9b8eb80e0fe99f871afa5bdbb853add97e25e --- CMakeLists.txt | 3 + data/bitmap/CubicalOneSphere.txt | 12 + data/bitmap/CubicalTwoSphere.txt | 31 + .../example/Bitmap_cubical_complex.cpp | 69 ++ src/Bitmap_cubical_complex/example/CMakeLists.txt | 12 + .../example/Random_bitmap_cubical_complex.cpp | 85 +++ .../include/gudhi/Bitmap_cubical_complex.h | 706 +++++++++++++++++++++ .../include/gudhi/Bitmap_cubical_complex_base.h | 577 +++++++++++++++++ src/Bitmap_cubical_complex/include/gudhi/counter.h | 136 ++++ src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 623 ++++++++++++++++++ src/Bitmap_cubical_complex/test/CMakeLists.txt | 25 + src/CMakeLists.txt | 1 + 12 files changed, 2280 insertions(+) create mode 100644 data/bitmap/CubicalOneSphere.txt create mode 100644 data/bitmap/CubicalTwoSphere.txt create mode 100644 src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp create mode 100644 src/Bitmap_cubical_complex/example/CMakeLists.txt create mode 100644 src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/counter.h create mode 100644 src/Bitmap_cubical_complex/test/Bitmap_test.cpp create mode 100644 src/Bitmap_cubical_complex/test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bea06e2..43e0558c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ else() message(STATUS "boost library dirs:" ${Boost_LIBRARY_DIRS}) include_directories(src/common/include/) + include_directories(src/Bitmap_cubical_complex/include/) include_directories(src/Bottleneck/include/) include_directories(src/Contraction/include/) include_directories(src/Hasse_complex/include/) @@ -74,6 +75,8 @@ else() add_subdirectory(src/Hasse_complex/example) add_subdirectory(src/Bottleneck/example) add_subdirectory(src/Bottleneck/test) + add_subdirectory(src/Bitmap_cubical_complex/example) + add_subdirectory(src/Bitmap_cubical_complex/test) # GudhUI add_subdirectory(src/GudhUI) diff --git a/data/bitmap/CubicalOneSphere.txt b/data/bitmap/CubicalOneSphere.txt new file mode 100644 index 00000000..4dec3fc6 --- /dev/null +++ b/data/bitmap/CubicalOneSphere.txt @@ -0,0 +1,12 @@ +2 +3 +3 +0 +0 +0 +0 +100 +0 +0 +0 +0 diff --git a/data/bitmap/CubicalTwoSphere.txt b/data/bitmap/CubicalTwoSphere.txt new file mode 100644 index 00000000..32f5d933 --- /dev/null +++ b/data/bitmap/CubicalTwoSphere.txt @@ -0,0 +1,31 @@ +3 +3 +3 +3 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +100 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp new file mode 100644 index 00000000..c0dbaf36 --- /dev/null +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -0,0 +1,69 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 . + */ + +//for persistence algorithm +#include "gudhi/reader_utils.h" +#include "gudhi/Bitmap_cubical_complex.h" +#include "gudhi/Persistent_cohomology.h" + +#include + +using namespace Gudhi; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include + +using namespace std; + +int main(int argc, char** argv) { + cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbed in \ +the first line is a dimension D of a cubical complex. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if (argc != 2) { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style cubical complex at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex b(argv[1]); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients(p); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*) ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt new file mode 100644 index 00000000..05ef1319 --- /dev/null +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHISimplexTreeFromFile) + +add_executable ( Bitmap_cubical_complex Bitmap_cubical_complex.cpp ) +target_link_libraries(Bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) +add_test(Bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalOneSphere.txt) +add_test(Bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) + +add_executable ( Random_bitmap_cubical_complex Random_bitmap_cubical_complex.cpp ) +target_link_libraries(Random_bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) +add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap_cubical_complex 2 100 100) + diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp new file mode 100644 index 00000000..de9d96e0 --- /dev/null +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -0,0 +1,85 @@ +/* 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): Pawel Dlotko + * + * 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 . + */ + + +//for persistence algorithm +#include "gudhi/reader_utils.h" +#include "gudhi/Bitmap_cubical_complex.h" +#include "gudhi/Persistent_cohomology.h" + +#include + +using namespace Gudhi; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include +#include +#include + +using namespace std; + +int main(int argc, char** argv) { + srand(time(0)); + + cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes. \ +The first parameter of the program is the dimension D of the cubical complex. The next D parameters are number of top dimensional cubes in each dimension of the cubical complex.\ +The program will create random cubical complex of that sizes and compute persistent homology of it." << endl; + + int p = 2; + double min_persistence = 0; + + size_t dimensionOfBitmap = (size_t) atoi(argv[1]); + std::vector< unsigned > sizes; + size_t multipliers = 1; + for (size_t dim = 0; dim != dimensionOfBitmap; ++dim) { + unsigned sizeInThisDimension = (unsigned) atoi(argv[2 + dim]); + sizes.push_back(sizeInThisDimension); + multipliers *= sizeInThisDimension; + } + + std::vector< double > data; + for (size_t i = 0; i != multipliers; ++i) { + data.push_back(rand() / (double) RAND_MAX); + } + + + + Bitmap_cubical_complex b(sizes, data); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients(p); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); + + + stringstream ss; + ss << "randomComplex_persistence"; + std::ofstream out((char*) ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h new file mode 100644 index 00000000..61ae8105 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -0,0 +1,706 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 BITMAP_CUBICAL_COMPLEX_H_ +#define BITMAP_CUBICAL_COMPLEX_H_ + +#include + +#include + +//global variable, was used just for debugging. +bool globalDbg = false; + +template +class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { + public: + //*********************************************************************************************************************************// + //Typedefs and typenames + //*********************************************************************************************************************************// + friend class Simplex_handle; + typedef size_t Simplex_key; + typedef T Filtration_value; + + + //*********************************************************************************************************************************// + //Simplex handle class + //*********************************************************************************************************************************// + + /** + * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. Elements of this class are: the pointer to the bitmap B in which the considered cell is + * together with a position of this cell in B. Given this data, one can get all the information about the considered cell. + **/ + class Simplex_handle { + public: + + Simplex_handle() { + if (globalDbg) { + cerr << "Simplex_handle()\n"; + } + this->b = 0; + this->position = 0; + } + + Simplex_handle(Bitmap_cubical_complex* b) { + if (globalDbg) { + cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; + } + this->b = b; + this->position = 0; + } + + Simplex_handle(const Simplex_handle& org) : b(org.b) { + if (globalDbg) { + cerr << "Simplex_handle( const Simplex_handle& org )\n"; + } + this->position = org.position; + } + + Simplex_handle& operator=(const Simplex_handle& rhs) { + if (globalDbg) { + cerr << "Simplex_handle operator = \n"; + } + this->position = rhs.position; + this->b = rhs.b; + return *this; + } + + Simplex_handle(Bitmap_cubical_complex* b, Simplex_key position) { + if (globalDbg) { + cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; + cerr << "Position : " << position << endl; + } + this->b = b; + this->position = position; + } + friend class Bitmap_cubical_complex; + private: + Bitmap_cubical_complex* b; + Simplex_key position; //Assumption -- this field always keep the REAL position of simplex in the bitmap, no matter what keys have been. + //to deal with the keys, the class Bitmap_cubical_complex have extra vectors: keyAssociatedToSimplex and simplexAssociatedToKey + //that allow to move between actual cell and the key assigned to it. + }; + + + //*********************************************************************************************************************************// + //Constructors + //*********************************************************************************************************************************// + //Over here we need to definie various input types. I am proposing the following ones: + //Perseus style + //H5 files? TODO + //binary files with little endiangs / big endians? TODO + //constructor from a vector of elements of a type T. TODO + + /** + * Constructor form a Perseus-style file. + **/ + Bitmap_cubical_complex(char* perseusStyleFile) : Bitmap_cubical_complex_base(perseusStyleFile) { + if (globalDbg) { + cerr << "Bitmap_cubical_complex( char* perseusStyleFile )\n"; + } + std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); + std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); + + for (size_t i = 0; i != this->totalNumberOfCells; ++i) { + keyAssociatedToSimplex[i] = simplexAssociatedToKey[i] = i; + } + this->keyAssociatedToSimplex = keyAssociatedToSimplex; + this->simplexAssociatedToKey = simplexAssociatedToKey; + //we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initializeElementsOrderedAccordingToFiltration(); + } + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells in the following directions and vector of element of a type T + * with filtration on top dimensional cells. + **/ + Bitmap_cubical_complex(std::vector dimensions, std::vector topDimensionalCells) : Bitmap_cubical_complex_base(dimensions, topDimensionalCells) { + std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); + std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); + + for (size_t i = 0; i != this->totalNumberOfCells; ++i) { + keyAssociatedToSimplex[i] = simplexAssociatedToKey[i] = i; + } + this->keyAssociatedToSimplex = keyAssociatedToSimplex; + this->simplexAssociatedToKey = simplexAssociatedToKey; + //we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initializeElementsOrderedAccordingToFiltration(); + } + + //*********************************************************************************************************************************// + //Other 'easy' functions + //*********************************************************************************************************************************// + + /** + * Returns number of all cubes in the complex. + **/ + size_t num_simplices()const { + return this->totalNumberOfCells; + } + + /** + * Returns a Simplex_handle to a cube that do not exist in this complex. + **/ + Simplex_handle null_simplex() { + return Simplex_handle(this, this->data.size()); + } + + /** + * Returns dimension of the complex. + **/ + size_t dimension() { + return this->sizes.size(); + } + + /** + * Return dimension of a cell pointed by the Simplex_handle. + **/ + size_t dimension(const Simplex_handle& sh) { + if (globalDbg) { + cerr << "int dimension(const Simplex_handle& sh)\n"; + } + if (sh.position != this->data.size()) return sh.b->get_dimension_of_a_cell(sh.position); + return std::numeric_limits::max(); + } + + /** + * Return the filtration of a cell pointed by the Simplex_handle. + **/ + T filtration(const Simplex_handle& sh) { + if (globalDbg) { + cerr << "T filtration(const Simplex_handle& sh)\n"; + } + //Returns the filtration value of a simplex. + if (sh.position != this->data.size()) return sh.b->data[ sh.position ]; + return INT_MAX; + } + + /** + * Return a key which is not a key of any cube in the considered data structure. + **/ + Simplex_key null_key() { + if (globalDbg) { + cerr << "Simplex_key null_key()\n"; + } + return this->data.size(); + } + + /** + * Return the key of a cube pointed by the Simplex_handle. + **/ + Simplex_key key(const Simplex_handle& sh) { + if (globalDbg) { + cerr << "Simplex_key key(const Simplex_handle& sh)\n"; + } + return sh.b->keyAssociatedToSimplex[ sh.position ]; + } + + /** + * Return the Simplex_handle given the key of the cube. + **/ + Simplex_handle simplex(Simplex_key key) { + if (globalDbg) { + cerr << "Simplex_handle simplex(Simplex_key key)\n"; + } + return Simplex_handle(this, this->simplexAssociatedToKey[ key ]); + } + + /** + * Assign key to a cube pointed by the Simplex_handle + **/ + void assign_key(Simplex_handle& sh, Simplex_key key) { + if (globalDbg) { + cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; + } + this->keyAssociatedToSimplex[sh.position] = key; + this->simplexAssociatedToKey[key] = sh.position; + } + + /** + * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. + **/ + void initializeElementsOrderedAccordingToFiltration(); + + + + //*********************************************************************************************************************************// + //Iterators + //*********************************************************************************************************************************// + + /** + * Boundary_simplex_iterator class allows iteration on boundary of each cube. + **/ + class Boundary_simplex_range; + + class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + //Iterator on the simplices belonging to the boundary of a simplex. + //value_type must be 'Simplex_handle'. + public: + + Boundary_simplex_iterator(Simplex_handle& sh) : sh(sh) { + if (globalDbg) { + cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n"; + } + this->position = 0; + this->boundaryElements = this->sh.b->get_boundary_of_a_cell(this->sh.position); + } + + Boundary_simplex_iterator operator++() { + if (globalDbg) { + cerr << "Boundary_simplex_iterator operator++()\n"; + } + ++this->position; + return *this; + } + + Boundary_simplex_iterator operator++(int) { + Boundary_simplex_iterator result = *this; + ++(*this); + return result; + } + + Boundary_simplex_iterator operator=(const Boundary_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "Boundary_simplex_iterator operator =\n"; + } + this->sh = rhs.sh; + this->boundaryElements.clear(); + this->boundaryElementsinsert(this->boundaryElements.end(), rhs.boundaryElements.begin(), rhs.boundaryElements.end()); + } + + bool operator==(const Boundary_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator ==\n"; + } + if (this->position == rhs.position) { + if (this->boundaryElements.size() != rhs.boundaryElements.size())return false; + for (size_t i = 0; i != this->boundaryElements.size(); ++i) { + if (this->boundaryElements[i] != rhs.boundaryElements[i])return false; + } + return true; + } + return false; + } + + bool operator!=(const Boundary_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator != \n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + cerr << "Simplex_handle operator*\n"; + } + return Simplex_handle(this->sh.b, this->boundaryElements[this->position]); + } + + friend class Boundary_simplex_range; + private: + Simplex_handle sh; + std::vector< size_t > boundaryElements; + size_t position; + }; + + /** + * Boundary_simplex_range class provides ranges for boundary iterators. + **/ + class Boundary_simplex_range { + //Range giving access to the simplices in the boundary of a simplex. + //.begin() and .end() return type Boundary_simplex_iterator. + public: + + Boundary_simplex_range(const Simplex_handle& sh) : sh(sh) { }; + + Boundary_simplex_iterator begin() { + if (globalDbg) { + cerr << "Boundary_simplex_iterator begin\n"; + } + Boundary_simplex_iterator it(this->sh); + return it; + } + + Boundary_simplex_iterator end() { + if (globalDbg) { + cerr << "Boundary_simplex_iterator end()\n"; + } + Boundary_simplex_iterator it(this->sh); + it.position = it.boundaryElements.size(); + return it; + } + private: + Simplex_handle sh; + }; + + + /** + * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. Secondary criteria for filtration are: + * (1) Dimension of a cube (lower dimensional comes first). + * (2) Position in the data structure (the ones that are earlies in the data structure comes first). + **/ + class Filtration_simplex_range; + + class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + //Iterator over all simplices of the complex in the order of the indexing scheme. + //'value_type' must be 'Simplex_handle'. + public: + + Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { }; + + Filtration_simplex_iterator() : b(NULL) { }; + + Filtration_simplex_iterator operator++() { + if (globalDbg) { + cerr << "Filtration_simplex_iterator operator++\n"; + } + ++this->position; + return (*this); + } + + Filtration_simplex_iterator operator++(int) { + Filtration_simplex_iterator result = *this; + ++(*this); + return result; + } + + Filtration_simplex_iterator operator=(const Filtration_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "Filtration_simplex_iterator operator =\n"; + } + this->b = rhs.b; + this->position = rhs.position; + } + + bool operator==(const Filtration_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; + } + if (this->position == rhs.position) { + return true; + } + return false; + } + + bool operator!=(const Filtration_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + cerr << "Simplex_handle operator*()\n"; + } + return Simplex_handle(this->b, this->b->elementsOrderedAccordingToFiltration[ this->position ]); + } + + friend class Filtration_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + }; + + /** + * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. + **/ + class Filtration_simplex_range { + //Range over the simplices of the complex in the order of the filtration. + //.begin() and .end() return type Filtration_simplex_iterator. + public: + + Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { }; + + Filtration_simplex_iterator begin() { + if (globalDbg) { + cerr << "Filtration_simplex_iterator begin() \n"; + } + return Filtration_simplex_iterator(this->b); + } + + Filtration_simplex_iterator end() { + if (globalDbg) { + cerr << "Filtration_simplex_iterator end()\n"; + } + Filtration_simplex_iterator it(this->b); + it.position = this->b->elementsOrderedAccordingToFiltration.size(); + return it; + } + private: + Bitmap_cubical_complex* b; + }; + + + + //*********************************************************************************************************************************// + //Methods to access iterators from the container: + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class that provides ranges for the Boundary_simplex_iterator. + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) { + if (globalDbg) { + cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n"; + } + //Returns a range giving access to all simplices of the boundary of a simplex, i.e. the set of codimension 1 subsimplices of the Simplex. + return Boundary_simplex_range(sh); + } + + /** + * filtration_simplex_range creates an object of a Filtration_simplex_range class that provides ranges for the Filtration_simplex_iterator. + **/ + Filtration_simplex_range filtration_simplex_range() { + if (globalDbg) { + cerr << "Filtration_simplex_range filtration_simplex_range()\n"; + } + //Returns a range over the simplices of the complex in the order of the filtration + return Filtration_simplex_range(this); + } + //*********************************************************************************************************************************// + + + + //*********************************************************************************************************************************// + //Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. + //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so I understand that this is something that was planned (for simplicial maps?) + //but was never finished. The only idea I have here is to use the same empty structure from IndexingTag.h file, but only if the compiler needs it. If the compiler + //do not need it, then I would rather not add here elements which I do not understand. + //typedef Indexing_tag + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + std::pair endpoints(Simplex_handle sh) { + std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh.position); + if (globalDbg) { + cerr << "std::pair endpoints( Simplex_handle sh )\n"; + cerr << "bdry.size() : " << bdry.size() << endl; + } + //this method returns two first elements from the boundary of sh. + if (bdry.size() < 2)throw ("Error in endpoints in Bitmap_cubical_complex class. The cell for which this method was called have less than two elements in the boundary."); + return std::make_pair(Simplex_handle(this, bdry[0]), Simplex_handle(this, bdry[1])); + } + + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range; + + class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + //Iterator over all simplices of the complex in the order of the indexing scheme. + //'value_type' must be 'Simplex_handle'. + public: + + Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; + } + //find the position of the first simplex of a dimension d + this->position = 0; + while ((this->position != b->data.size()) && (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { + ++this->position; + } + }; + + Skeleton_simplex_iterator() : b(NULL), dimension(0) { }; + + Skeleton_simplex_iterator operator++() { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator operator++()\n"; + } + //increment the position as long as you did not get to the next element of the dimension dimension. + ++this->position; + while ((this->position != this->b->data.size()) && (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { + ++this->position; + } + return (*this); + } + + Skeleton_simplex_iterator operator++(int) { + Skeleton_simplex_iterator result = *this; + ++(*this); + return result; + } + + Skeleton_simplex_iterator operator=(const Skeleton_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator operator =\n"; + } + this->b = rhs.b; + this->position = rhs.position; + } + + bool operator==(const Skeleton_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator ==\n"; + } + if (this->position == rhs.position) { + return true; + } + return false; + } + + bool operator!=(const Skeleton_simplex_iterator& rhs) { + if (globalDbg) { + cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + cerr << "Simplex_handle operator*() \n"; + } + return Simplex_handle(this->b, this->position); + } + + friend class Skeleton_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + int dimension; + }; + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range { + //Range over the simplices of the complex in the order of the filtration. + //.begin() and .end() return type Filtration_simplex_iterator. + public: + + Skeleton_simplex_range(Bitmap_cubical_complex* b, int dimension) : b(b), dimension(dimension) { }; + + Skeleton_simplex_iterator begin() { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator begin()\n"; + } + return Skeleton_simplex_iterator(this->b, this->dimension); + } + + Skeleton_simplex_iterator end() { + if (globalDbg) { + cerr << "Skeleton_simplex_iterator end()\n"; + } + Skeleton_simplex_iterator it(this->b, this->dimension); + it.position = this->b->data.size(); + return it; + } + private: + Bitmap_cubical_complex* b; + int dimension; + }; + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + Skeleton_simplex_range skeleton_simplex_range(int dimension) { + if (globalDbg) { + cerr << "Skeleton_simplex_range skeleton_simplex_range( int dimension )\n"; + } + return Skeleton_simplex_range(this, dimension); + } + + + + //*********************************************************************************************************************************// + //functions used for debugging: + + /** + * Function used for debugging purposes. + **/ + void printKeyAssociatedToSimplex() { + for (size_t i = 0; i != this->data.size(); ++i) { + cerr << i << " -> " << this->simplexAssociatedToKey[i] << endl; + } + } + + /** + * Function used for debugging purposes. + **/ + size_t printRealPosition(const Simplex_handle& sh) { + return sh.position; + } + + private: + std::vector< size_t > keyAssociatedToSimplex; + std::vector< size_t > simplexAssociatedToKey; + std::vector< size_t > elementsOrderedAccordingToFiltration; //needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. +}; //Bitmap_cubical_complex + +template +bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< size_t, std::pair< T, char > >& f, const std::pair< size_t, std::pair< T, char > >& s) { + if (globalDbg) { + cerr << "ompareElementsForElementsOrderedAccordingToFiltration\n"; + } + if (f.second.first < s.second.first) { + return true; + } else { + if (f.second.first > s.second.first) { + return false; + } else { + //in this case f.second.first == s.second.first, and we use dimension to compare: + if (f.second.second < s.second.second) { + return true; + } else { + if (f.second.second > s.second.second) { + return false; + } else { + //in this case, both the filtration value and the dimensions for those cells are the same. Since it may be nice to have a stable sorting procedure, in this case, we compare positions in the bitmap: + return ( f.first < s.first); + } + } + } + } +} + +template +void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() { + if (globalDbg) { + cerr << "void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() \n"; + } + //( position , (filtration , dimension) ) + std::vector< std::pair< size_t, std::pair< T, char > > > dataOfElementsFromBitmap(this->data.size()); + for (size_t i = 0; i != this->data.size(); ++i) { + //TODO -- this can be optimized by having a counter here. We do not need to re-compute the dimension for every cell from scratch + dataOfElementsFromBitmap[i] = std::make_pair(i, std::make_pair(this->data[i], this->get_dimension_of_a_cell(i))); + } + std::sort(dataOfElementsFromBitmap.begin(), dataOfElementsFromBitmap.end(), compareElementsForElementsOrderedAccordingToFiltration); + + std::vector< size_t > elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap(this->data.size()); + for (size_t i = 0; i != dataOfElementsFromBitmap.size(); ++i) { + elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap[i] = dataOfElementsFromBitmap[i].first; + } + this->elementsOrderedAccordingToFiltration = elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap; +} + + +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// + +#endif // BITMAP_CUBICAL_COMPLEX_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h new file mode 100644 index 00000000..26c97872 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -0,0 +1,577 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 BITMAP_CUBICAL_COMPLEX_BASE_H_ +#define BITMAP_CUBICAL_COMPLEX_BASE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +/** + * This is a class implementing a basic bitmap data structure to store cubical complexes. It implements only the most basic subroutines. + * The idea of the bitmap is the following. Our aim is to have a memory efficient data structure to store d-dimensional cubical complex C being a cubical decomposition + * of a rectangular region of a space. This is achieved by storing C as a vector of bits (this is where the name 'bitmap' came from). Each cell is represented by a single + * bit (in case of black and white bitmaps, or by a single element of a type T (here T is a filtration type of a bitmap, typically a double). All the informations needed for homology and + * persistent homology computations (like dimension of a cell, boundary and coboundary elements of a cell, are then obtained from the position of the element in C. + */ +template +class Bitmap_cubical_complex_base { + public: + /** + * There are a few constructors of a Bitmap_cubical_complex_base class. First one, that takes vector, creates an empty bitmap of a dimension equal to the number of elements in the + * input vector and size in the i-th dimension equal the number in the position i-of the input vector. + */ + Bitmap_cubical_complex_base(std::vector sizes_); + /** + * The second constructor takes as a input a Perseus style file. For more details, please consult the documentations of Perseus software as well as examples attached to this + * implementation. + **/ + Bitmap_cubical_complex_base(char* perseusStyleFile_); + /** + * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) together with vector of filtration values of top dimensional cells. + **/ + Bitmap_cubical_complex_base(std::vector dimensions_, std::vector topDimensionalCells_); + + /** + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell and get_cell_data are the basic functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a non-negative integer, indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to the positions of (co)boundary element of the input cell. + */ + inline std::vector< size_t > get_boundary_of_a_cell(size_t cell_); + /** + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell and get_cell_data are the basic functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a non-negative integer, indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to the positions of (co)boundary element of the input cell. + **/ + inline std::vector< size_t > get_coboundary_of_a_cell(size_t cell_); + /** + * In the case of get_dimension_of_a_cell function, the output is a non-negative integer indicating the dimension of a cell. + **/ + inline unsigned get_dimension_of_a_cell(size_t cell_); + /** + * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. + **/ + inline T& get_cell_data(size_t cell_); + + + /** + * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. Then, there are a few ways one can pick the filtration of lower dimensional + * cells. The most typical one is by so called lower star filtration. This function is always called by any constructor which takes the top dimensional cells. If you use such a constructor, + * then there is no need to call this function. Call it only if you are putting the filtration of the cells by your own (for instance by using topDimensionalCellsIterator). + **/ + void impose_lower_star_filtration(); //assume that top dimensional cells are already set. + + /** + * Returns dimension of a complex. + **/ + inline unsigned dimension() { + return sizes.size(); + } + + /** + * Returns number of all cubes in the data structure. + **/ + inline unsigned size_of_bitmap() { + return this->data.size(); + } + + /** + * Writing to stream operator. + **/ + template + friend ostream& operator<<(ostream & os_, const Bitmap_cubical_complex_base& b_); + + //ITERATORS + + /** + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. in lexicographical order). + **/ + typedef typename std::vector< T >::iterator all_cells_iterator; + + all_cells_iterator all_cells_begin()const { + return this->data.begin(); + } + + all_cells_iterator all_cells_end()const { + return this->data.end(); + } + + + typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + + all_cells_const_iterator all_cells_const_begin()const { + return this->data.begin(); + } + + all_cells_const_iterator all_cells_const_end()const { + return this->data.end(); + } + + /** + * Iterator through top dimensional cells of the complex. The cells appear in order they are stored in the structure (i.e. in lexicographical order) + **/ + class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > { + public: + + Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b_) : b(b_) { + for (size_t i = 0; i != b_.dimension(); ++i) { + this->counter.push_back(0); + } + } + + Top_dimensional_cells_iterator operator++() { + //first find first element of the counter that can be increased: + size_t dim = 0; + while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; + + if (dim != this->b.dimension()) { + ++this->counter[dim]; + for (size_t i = 0; i != dim; ++i) { + this->counter[i] = 0; + } + } else { + ++this->counter[0]; + } + return *this; + } + + Top_dimensional_cells_iterator operator++(int) { + Top_dimensional_cells_iterator result = *this; + ++(*this); + return result; + } + + Top_dimensional_cells_iterator operator=(const Top_dimensional_cells_iterator& rhs_) { + this->counter = rhs_.counter; + this->b = rhs_.b; + return *this; + } + + bool operator==(const Top_dimensional_cells_iterator& rhs_) { + if (&this->b != &rhs_.b)return false; + if (this->counter.size() != rhs_.counter.size())return false; + for (size_t i = 0; i != this->counter.size(); ++i) { + if (this->counter[i] != rhs_.counter[i])return false; + } + return true; + } + + bool operator!=(const Top_dimensional_cells_iterator& rhs_) { + return !(*this == rhs_); + } + + T& operator*() { + //given the counter, compute the index in the array and return this element. + unsigned index = 0; + for (size_t i = 0; i != this->counter.size(); ++i) { + index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; + } + return this->b.data[index]; + } + + size_t computeIndexInBitmap() { + size_t index = 0; + for (size_t i = 0; i != this->counter.size(); ++i) { + index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; + } + return index; + } + + void printCounter() { + for (size_t i = 0; i != this->counter.size(); ++i) { + cout << this->counter[i] << " "; + } + } + friend class Bitmap_cubical_complex_base; + protected: + std::vector< unsigned > counter; + Bitmap_cubical_complex_base& b; + }; + + Top_dimensional_cells_iterator top_dimensional_cells_begin() { + Top_dimensional_cells_iterator a(*this); + return a; + } + + Top_dimensional_cells_iterator top_dimensional_cells_end() { + Top_dimensional_cells_iterator a(*this); + for (size_t i = 0; i != this->dimension(); ++i) { + a.counter[i] = this->sizes[i] - 1; + } + a.counter[0]++; + return a; + } + + + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + + + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + + protected: + std::vector sizes; + std::vector multipliers; + std::vector data; + size_t totalNumberOfCells; + + void set_up_containers(std::vector sizes_) { + unsigned multiplier = 1; + for (size_t i = 0; i != sizes_.size(); ++i) { + this->sizes.push_back(sizes_[i]); + this->multipliers.push_back(multiplier); + //multiplier *= 2*(sizes[i]+1)+1; + multiplier *= 2 * sizes_[i] + 1; + } + //std::reverse( this->sizes.begin() , this->sizes.end() ); + std::vector data(multiplier); + std::fill(data.begin(), data.end(), INT_MAX); + this->totalNumberOfCells = multiplier; + this->data = data; + } + + size_t compute_position_in_bitmap(std::vector< int > counter_) { + size_t position = 0; + for (size_t i = 0; i != this->multipliers.size(); ++i) { + position += this->multipliers[i] * counter_[i]; + } + return position; + } + + std::vector compute_counter_for_given_cell(size_t cell_) { + std::vector counter; + for (size_t dim = this->sizes.size(); dim != 0; --dim) { + counter.push_back(cell_ / this->multipliers[dim - 1]); + cell_ = cell_ % this->multipliers[dim - 1]; + } + std::reverse(counter.begin(), counter.end()); + return counter; + } + + std::vector< size_t > generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_); +}; + +template +ostream& operator<<(ostream & out_, const Bitmap_cubical_complex_base& b_) { + //for ( typename bitmap::all_cells_const_iterator it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) + for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b_.all_cells_const_begin(); it != b_.all_cells_const_end(); ++it) { + out_ << *it << " "; + } + return out_; +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizes_) { + this->set_up_containers(sizes_); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_, std::vector topDimensionalCells_) { + this->set_up_containers(sizesInFollowingDirections_); + + size_t numberOfTopDimensionalElements = 1; + for (size_t i = 0; i != sizesInFollowingDirections_.size(); ++i) { + numberOfTopDimensionalElements *= sizesInFollowingDirections_[i]; + } + if (numberOfTopDimensionalElements != topDimensionalCells_.size()) { + cerr << "Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from sizesInFollowingDirections vector is different than the size of topDimensionalCells vector." << endl; + throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from sizesInFollowingDirections vector is different than the size of topDimensionalCells vector."); + } + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + size_t index = 0; + for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { + (*it) = topDimensionalCells_[index]; + ++index; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFile_) { + bool dbg = false; + ifstream inFiltration, inIds; + inFiltration.open(perseusStyleFile_); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + if (dbg) { + cerr << "dimensionOfData : " << dimensionOfData << endl; + } + + std::vector sizes; + for (size_t i = 0; i != dimensionOfData; ++i) { + int sizeInThisDimension; + inFiltration >> sizeInThisDimension; + sizeInThisDimension = abs(sizeInThisDimension); + sizes.push_back(sizeInThisDimension); + if (dbg) { + cerr << "sizeInThisDimension : " << sizeInThisDimension << endl; + } + } + this->set_up_containers(sizes); + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_begin(); + + //TODO -- over here we also need to read id's of cell and put them to bitmapElement structure! + while (!inFiltration.eof()) { + double filtrationLevel; + inFiltration >> filtrationLevel; + if (dbg) { + cerr << "Cell of an index : " << it.computeIndexInBitmap() << " and dimension: " << this->get_dimension_of_a_cell(it.computeIndexInBitmap()) << " get the value : " << filtrationLevel << endl; + } + *it = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); +} + +template +std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell_) { + bool bdg = false; + //first of all, we need to take the list of coordinates in which the cell has nonzero length. We do it by using modified version to compute dimension of a cell: + std::vector< unsigned > dimensionsInWhichCellHasNonzeroLength; + unsigned dimension = 0; + size_t cell1 = cell_; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / multipliers[i - 1]; + if (position % 2 == 1) { + dimensionsInWhichCellHasNonzeroLength.push_back(i - 1); + dimension++; + } + cell1 = cell1 % multipliers[i - 1]; + } + + if (bdg) { + cerr << "dimensionsInWhichCellHasNonzeroLength : \n"; + for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { + cerr << dimensionsInWhichCellHasNonzeroLength[i] << endl; + } + getchar(); + } + + std::vector< size_t > boundaryElements; + if (dimensionsInWhichCellHasNonzeroLength.size() == 0)return boundaryElements; + for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { + boundaryElements.push_back(cell_ - multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); + boundaryElements.push_back(cell_ + multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); + + if (bdg) cerr << "multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; + if (bdg) cerr << "cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; + if (bdg) cerr << "cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; + } + return boundaryElements; +} + +template +std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(size_t cell_) { + bool bdg = false; + //first of all, we need to take the list of coordinates in which the cell has nonzero length. We do it by using modified version to compute dimension of a cell: + std::vector< unsigned > dimensionsInWhichCellHasZeroLength; + unsigned dimension = 0; + size_t cell1 = cell_; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / multipliers[i - 1]; + if (position % 2 == 0) { + dimensionsInWhichCellHasZeroLength.push_back(i - 1); + dimension++; + } + cell1 = cell1 % multipliers[i - 1]; + } + + std::vector counter = this->compute_counter_for_given_cell(cell_); + //reverse(counter.begin() , counter.end()); + + if (bdg) { + cerr << "dimensionsInWhichCellHasZeroLength : \n"; + for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { + cerr << dimensionsInWhichCellHasZeroLength[i] << endl; + } + cerr << "\n counter : " << endl; + for (size_t i = 0; i != counter.size(); ++i) { + cerr << counter[i] << endl; + } + getchar(); + } + + std::vector< size_t > coboundaryElements; + if (dimensionsInWhichCellHasZeroLength.size() == 0)return coboundaryElements; + for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { + if (bdg) { + cerr << "Dimension : " << i << endl; + if (counter[dimensionsInWhichCellHasZeroLength[i]] == 0) { + cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + } + if (counter[dimensionsInWhichCellHasZeroLength[i]] == 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]]) { + cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + } + } + + + if ((cell_ > multipliers[dimensionsInWhichCellHasZeroLength[i]]) && (counter[dimensionsInWhichCellHasZeroLength[i]] != 0)) + //if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 0 ) + { + if (bdg)cerr << "Subtracting : " << cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]] << endl; + coboundaryElements.push_back(cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]]); + } + if ((cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] < this->data.size()) && (counter[dimensionsInWhichCellHasZeroLength[i]] != 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]])) + //if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 2*this->sizes[dimensionsInWhichCellHasZeroLength[i]] ) + { + coboundaryElements.push_back(cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]]); + if (bdg)cerr << "Adding : " << cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] << endl; + } + } + return coboundaryElements; +} + +template +unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell(size_t cell_) { + bool dbg = false; + if (dbg)cerr << "\n\n\n Computing position o a cell of an index : " << cell_ << endl; + unsigned dimension = 0; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell_ / multipliers[i - 1]; + + if (dbg)cerr << "i-1 :" << i - 1 << endl; + if (dbg)cerr << "cell_ : " << cell_ << endl; + if (dbg)cerr << "position : " << position << endl; + if (dbg)cerr << "multipliers[" << i - 1 << "] = " << multipliers[i - 1] << endl; + if (dbg)getchar(); + + if (position % 2 == 1) { + if (dbg)cerr << "Nonzero length in this direction \n"; + dimension++; + } + cell_ = cell_ % multipliers[i - 1]; + } + return dimension; +} + +template +T& Bitmap_cubical_complex_base::get_cell_data(size_t cell_) { + return this->data[cell_]; +} + +template +void Bitmap_cubical_complex_base::impose_lower_star_filtration() { + bool dbg = false; + + //this vector will be used to check which elements have already been taken care of in imposing lower star filtration: + std::vector isThisCellConsidered(this->data.size(), false); + + std::vector indicesToConsider; + //we assume here that we already have a filtration on the top dimensional cells and we have to extend it to lower ones. + typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { + indicesToConsider.push_back(it.computeIndexInBitmap()); + } + + while (indicesToConsider.size()) { + if (dbg) { + cerr << "indicesToConsider in this iteration \n"; + for (size_t i = 0; i != indicesToConsider.size(); ++i) { + cout << indicesToConsider[i] << " "; + } + getchar(); + } + std::vector newIndicesToConsider; + for (size_t i = 0; i != indicesToConsider.size(); ++i) { + std::vector bd = this->get_boundary_of_a_cell(indicesToConsider[i]); + for (size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) { + if (this->data[ bd[boundaryIt] ] > this->data[ indicesToConsider[i] ]) { + this->data[ bd[boundaryIt] ] = this->data[ indicesToConsider[i] ]; + } + if (isThisCellConsidered[ bd[boundaryIt] ] == false) { + newIndicesToConsider.push_back(bd[boundaryIt]); + isThisCellConsidered[ bd[boundaryIt] ] = true; + } + } + } + indicesToConsider.swap(newIndicesToConsider); + } +} + +template +std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_) { + bool dbg = false; + if (this->sizes.size() != directionsForPeriodicBCond_.size())throw "directionsForPeriodicBCond_ vector size is different from the size of the bitmap. The program will now terminate \n"; + + std::vector sizes(this->sizes.size()); + for (size_t i = 0; i != this->sizes.size(); ++i)sizes[i] = 2 * this->sizes[i]; + + counter c(sizes); + + std::vector< size_t > result; + + for (size_t i = 0; i != this->data.size(); ++i) { + size_t position; + if (!c.isFinal()) { + position = i; + //result.push_back( i ); + } else { + std::vector< bool > finals = c.directionsOfFinals(); + bool jumpInPosition = false; + for (size_t dir = 0; dir != finals.size(); ++dir) { + if (finals[dir] == false)continue; + if (directionsForPeriodicBCond_[dir]) { + jumpInPosition = true; + } + } + if (jumpInPosition == true) { + //in this case this guy is final, so we need to find 'the opposite one' + position = compute_position_in_bitmap(c.findOpposite(directionsForPeriodicBCond_)); + } else { + position = i; + } + } + result.push_back(position); + if (dbg) { + cerr << " position : " << position << endl; + cerr << c << endl; + getchar(); + } + + c.increment(); + } + + return result; +} + +#endif // BITMAP_CUBICAL_COMPLEX_BASE_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/counter.h b/src/Bitmap_cubical_complex/include/gudhi/counter.h new file mode 100644 index 00000000..9df819b2 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/counter.h @@ -0,0 +1,136 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 COUNTER_H_ +#define COUNTER_H_ + +#include +#include + +using namespace std; + +/** + * This is an implementation of a simple counter. It is needed for the implementation of a bitmapCubicalComplex. + **/ + +class counter { + public: + + /** + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. The default beginning value is a vector of the same length as the endd, filled-in with zeros. + **/ + counter(std::vector< int > endd) { + for (size_t i = 0; i != endd.size(); ++i) { + this->current.push_back(0); + this->begin.push_back(0); + this->end.push_back(endd[i]); + } + } + + /** + * Constructor of a counter class. It takes as the input beginn and end vector. It assumes that begin vector is lexicographically below the end vector. + **/ + counter(std::vector< int > beginn, std::vector< int > endd) { + if (beginn.size() != endd.size())throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + for (size_t i = 0; i != endd.size(); ++i) { + this->current.push_back(0); + this->begin.push_back(0); + this->end.push_back(endd[i]); + } + } + + /** + * Function to increment the counter. If the value returned by the function is true, then the incrementation process was successful. + * If the value of the function is false, that means, that the counter have reached its end-value. + **/ + bool increment() { + size_t i = 0; + while ((i != this->end.size()) && (this->current[i] == this->end[i])) { + ++i; + } + + if (i == this->end.size())return false; + ++this->current[i]; + for (size_t j = 0; j != i; ++j) { + this->current[j] = this->begin[j]; + } + return true; + } + + /** + * Function to check if we are at the end of counter. + **/ + bool isFinal() { + for (size_t i = 0; i != this->current.size(); ++i) { + if (this->current[i] == this->end[i])return true; + } + return false; + } + + /** + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. Its aim is to find an counter corresponding to the element the following + * boundary element is identified with when periodic boundary conditions are imposed. + **/ + std::vector< int > findOpposite(std::vector< bool > directionsForPeriodicBCond) { + std::vector< int > result; + for (size_t i = 0; i != this->current.size(); ++i) { + if ((this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true)) { + result.push_back(this->begin[i]); + } else { + result.push_back(this->current[i]); + } + } + return result; + } + + /** + * Function checking at which positions the current value of a counter is the final value of the counter. + **/ + std::vector< bool > directionsOfFinals() { + std::vector< bool > result; + for (size_t i = 0; i != this->current.size(); ++i) { + if (this->current[i] == this->end[i]) { + result.push_back(true); + } else { + result.push_back(false); + } + } + return result; + } + + /** + * Function to write counter to the stream. + **/ + friend std::ostream& operator<<(std::ostream& out, const counter& c) { + //cerr << "c.current.size() : " << c.current.size() << endl; + for (size_t i = 0; i != c.current.size(); ++i) { + out << c.current[i] << " "; + } + return out; + } + private: + std::vector< int > begin; + std::vector< int > end; + std::vector< int > current; +}; + +#endif // COUNTER_H_ diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp new file mode 100644 index 00000000..1c204bae --- /dev/null +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -0,0 +1,623 @@ +#include "gudhi/Bitmap_cubical_complex.h" + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "cubical_complex" +#include + +using namespace std; + +BOOST_AUTO_TEST_CASE(check_dimension) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + BOOST_CHECK(increasing.dimension() == 2); +} + +BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { + std::vector< double > expectedFiltrationValues1; + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(100); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + + std::vector< double > expectedFiltrationValues2; + expectedFiltrationValues2.push_back(1); + expectedFiltrationValues2.push_back(2); + expectedFiltrationValues2.push_back(3); + expectedFiltrationValues2.push_back(4); + expectedFiltrationValues2.push_back(5); + expectedFiltrationValues2.push_back(6); + expectedFiltrationValues2.push_back(7); + expectedFiltrationValues2.push_back(8); + expectedFiltrationValues2.push_back(9); + + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector< double > oneDimensionalCycle; + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(100); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); + + + int i = 0; + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { + BOOST_CHECK(*it == expectedFiltrationValues2[i]); + ++i; + } + i = 0; + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { + BOOST_CHECK(*it == expectedFiltrationValues1[i]); + ++i; + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { + + std::vector boundary0; + std::vector boundary1; + boundary1.push_back(0); + boundary1.push_back(2); + std::vector boundary2; + std::vector boundary3; + boundary3.push_back(2); + boundary3.push_back(4); + std::vector boundary4; + std::vector boundary5; + boundary5.push_back(4); + boundary5.push_back(6); + std::vector boundary6; + std::vector boundary7; + boundary7.push_back(0); + boundary7.push_back(14); + std::vector boundary8; + boundary8.push_back(1); + boundary8.push_back(15); + boundary8.push_back(7); + boundary8.push_back(9); + std::vector boundary9; + boundary9.push_back(2); + boundary9.push_back(16); + std::vector boundary10; + boundary10.push_back(3); + boundary10.push_back(17); + boundary10.push_back(9); + boundary10.push_back(11); + std::vector boundary11; + boundary11.push_back(4); + boundary11.push_back(18); + std::vector boundary12; + boundary12.push_back(5); + boundary12.push_back(19); + boundary12.push_back(11); + boundary12.push_back(13); + std::vector boundary13; + boundary13.push_back(6); + boundary13.push_back(20); + std::vector boundary14; + std::vector boundary15; + boundary15.push_back(14); + boundary15.push_back(16); + std::vector boundary16; + std::vector boundary17; + boundary17.push_back(16); + boundary17.push_back(18); + std::vector boundary18; + std::vector boundary19; + boundary19.push_back(18); + boundary19.push_back(20); + std::vector boundary20; + std::vector boundary21; + boundary21.push_back(14); + boundary21.push_back(28); + std::vector boundary22; + boundary22.push_back(15); + boundary22.push_back(29); + boundary22.push_back(21); + boundary22.push_back(23); + std::vector boundary23; + boundary23.push_back(16); + boundary23.push_back(30); + std::vector boundary24; + boundary24.push_back(17); + boundary24.push_back(31); + boundary24.push_back(23); + boundary24.push_back(25); + std::vector boundary25; + boundary25.push_back(18); + boundary25.push_back(32); + std::vector boundary26; + boundary26.push_back(19); + boundary26.push_back(33); + boundary26.push_back(25); + boundary26.push_back(27); + std::vector boundary27; + boundary27.push_back(20); + boundary27.push_back(34); + std::vector boundary28; + std::vector boundary29; + boundary29.push_back(28); + boundary29.push_back(30); + std::vector boundary30; + std::vector boundary31; + boundary31.push_back(30); + boundary31.push_back(32); + std::vector boundary32; + std::vector boundary33; + boundary33.push_back(32); + boundary33.push_back(34); + std::vector boundary34; + std::vector boundary35; + boundary35.push_back(28); + boundary35.push_back(42); + std::vector boundary36; + boundary36.push_back(29); + boundary36.push_back(43); + boundary36.push_back(35); + boundary36.push_back(37); + std::vector boundary37; + boundary37.push_back(30); + boundary37.push_back(44); + std::vector boundary38; + boundary38.push_back(31); + boundary38.push_back(45); + boundary38.push_back(37); + boundary38.push_back(39); + std::vector boundary39; + boundary39.push_back(32); + boundary39.push_back(46); + std::vector boundary40; + boundary40.push_back(33); + boundary40.push_back(47); + boundary40.push_back(39); + boundary40.push_back(41); + std::vector boundary41; + boundary41.push_back(34); + boundary41.push_back(48); + std::vector boundary42; + std::vector boundary43; + boundary43.push_back(42); + boundary43.push_back(44); + std::vector boundary44; + std::vector boundary45; + boundary45.push_back(44); + boundary45.push_back(46); + std::vector boundary46; + std::vector boundary47; + boundary47.push_back(46); + boundary47.push_back(48); + std::vector boundary48; + std::vector< std::vector > boundaries; + boundaries.push_back(boundary0); + boundaries.push_back(boundary1); + boundaries.push_back(boundary2); + boundaries.push_back(boundary3); + boundaries.push_back(boundary4); + boundaries.push_back(boundary5); + boundaries.push_back(boundary6); + boundaries.push_back(boundary7); + boundaries.push_back(boundary8); + boundaries.push_back(boundary9); + boundaries.push_back(boundary10); + boundaries.push_back(boundary11); + boundaries.push_back(boundary12); + boundaries.push_back(boundary13); + boundaries.push_back(boundary14); + boundaries.push_back(boundary15); + boundaries.push_back(boundary16); + boundaries.push_back(boundary17); + boundaries.push_back(boundary18); + boundaries.push_back(boundary19); + boundaries.push_back(boundary20); + boundaries.push_back(boundary21); + boundaries.push_back(boundary22); + boundaries.push_back(boundary23); + boundaries.push_back(boundary24); + boundaries.push_back(boundary25); + boundaries.push_back(boundary26); + boundaries.push_back(boundary27); + boundaries.push_back(boundary28); + boundaries.push_back(boundary29); + boundaries.push_back(boundary30); + boundaries.push_back(boundary31); + boundaries.push_back(boundary32); + boundaries.push_back(boundary33); + boundaries.push_back(boundary34); + boundaries.push_back(boundary35); + boundaries.push_back(boundary36); + boundaries.push_back(boundary37); + boundaries.push_back(boundary38); + boundaries.push_back(boundary39); + boundaries.push_back(boundary40); + boundaries.push_back(boundary41); + boundaries.push_back(boundary42); + boundaries.push_back(boundary43); + boundaries.push_back(boundary44); + boundaries.push_back(boundary45); + boundaries.push_back(boundary46); + boundaries.push_back(boundary47); + boundaries.push_back(boundary48); + + + + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(boundaries[i][j] == bd[j]); + } + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + + std::vector coboundaryElements; + coboundaryElements.push_back(7); + coboundaryElements.push_back(1); + coboundaryElements.push_back(8); + coboundaryElements.push_back(9); + coboundaryElements.push_back(1); + coboundaryElements.push_back(3); + coboundaryElements.push_back(10); + coboundaryElements.push_back(11); + coboundaryElements.push_back(3); + coboundaryElements.push_back(5); + coboundaryElements.push_back(12); + coboundaryElements.push_back(13); + coboundaryElements.push_back(5); + coboundaryElements.push_back(8); + coboundaryElements.push_back(8); + coboundaryElements.push_back(10); + coboundaryElements.push_back(10); + coboundaryElements.push_back(12); + coboundaryElements.push_back(12); + coboundaryElements.push_back(7); + coboundaryElements.push_back(21); + coboundaryElements.push_back(15); + coboundaryElements.push_back(8); + coboundaryElements.push_back(22); + coboundaryElements.push_back(9); + coboundaryElements.push_back(23); + coboundaryElements.push_back(15); + coboundaryElements.push_back(17); + coboundaryElements.push_back(10); + coboundaryElements.push_back(24); + coboundaryElements.push_back(11); + coboundaryElements.push_back(25); + coboundaryElements.push_back(17); + coboundaryElements.push_back(19); + coboundaryElements.push_back(12); + coboundaryElements.push_back(26); + coboundaryElements.push_back(13); + coboundaryElements.push_back(27); + coboundaryElements.push_back(19); + coboundaryElements.push_back(22); + coboundaryElements.push_back(22); + coboundaryElements.push_back(24); + coboundaryElements.push_back(24); + coboundaryElements.push_back(26); + coboundaryElements.push_back(26); + coboundaryElements.push_back(21); + coboundaryElements.push_back(35); + coboundaryElements.push_back(29); + coboundaryElements.push_back(22); + coboundaryElements.push_back(36); + coboundaryElements.push_back(23); + coboundaryElements.push_back(37); + coboundaryElements.push_back(29); + coboundaryElements.push_back(31); + coboundaryElements.push_back(24); + coboundaryElements.push_back(38); + coboundaryElements.push_back(25); + coboundaryElements.push_back(39); + coboundaryElements.push_back(31); + coboundaryElements.push_back(33); + coboundaryElements.push_back(26); + coboundaryElements.push_back(40); + coboundaryElements.push_back(27); + coboundaryElements.push_back(41); + coboundaryElements.push_back(33); + coboundaryElements.push_back(36); + coboundaryElements.push_back(36); + coboundaryElements.push_back(38); + coboundaryElements.push_back(38); + coboundaryElements.push_back(40); + coboundaryElements.push_back(40); + coboundaryElements.push_back(35); + coboundaryElements.push_back(43); + coboundaryElements.push_back(36); + coboundaryElements.push_back(37); + coboundaryElements.push_back(43); + coboundaryElements.push_back(45); + coboundaryElements.push_back(38); + coboundaryElements.push_back(39); + coboundaryElements.push_back(45); + coboundaryElements.push_back(47); + coboundaryElements.push_back(40); + coboundaryElements.push_back(41); + coboundaryElements.push_back(47); + size_t number = 0; + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + std::vector< size_t > bd = increasing.get_coboundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(coboundaryElements[number] == bd[j]); + ++number; + } + + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + std::vector dim; + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]); + } +} + +BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + std::vector< unsigned > dim; + dim.push_back(0); + dim.push_back(0); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + + std::vector fil; + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(5); + fil.push_back(5); + fil.push_back(5); + fil.push_back(5); + fil.push_back(6); + fil.push_back(6); + fil.push_back(6); + fil.push_back(6); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(8); + fil.push_back(8); + fil.push_back(8); + fil.push_back(8); + fil.push_back(9); + fil.push_back(9); + fil.push_back(9); + fil.push_back(9); + + + Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); + size_t position = 0; + for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { + BOOST_CHECK(increasing.dimension(*it) == dim[position]); + BOOST_CHECK(increasing.filtration(*it) == fil[position]); + ++position; + } +} diff --git a/src/Bitmap_cubical_complex/test/CMakeLists.txt b/src/Bitmap_cubical_complex/test/CMakeLists.txt new file mode 100644 index 00000000..97c374e6 --- /dev/null +++ b/src/Bitmap_cubical_complex/test/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIBitmapCCUT) + +if (GCOVR_PATH) + # for gcovr to make coverage reports - Corbera Jenkins plugin + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage") +endif() +if (GPROF_PATH) + # for gprof to make coverage reports - Jenkins + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pg") +endif() + +add_executable ( BitmapCCUT Bitmap_test.cpp ) +target_link_libraries(BitmapCCUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + +# Unitary tests +add_test(NAME BitmapCCUT + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/BitmapCCUT + # XML format for Jenkins xUnit plugin + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/BitmapCCUT.xml --log_level=test_suite --report_level=no) + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 545b0b58..576ba353 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,7 @@ else() add_subdirectory(example/Contraction) add_subdirectory(example/Hasse_complex) add_subdirectory(example/Bottleneck) + add_subdirectory(example/Bitmap_cubical_complex) # GudhUI add_subdirectory(GudhUI) -- cgit v1.2.3 From dd2a15d1a8d2607848527513210330baebce9e8e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 25 Sep 2015 16:07:20 +0000 Subject: cpplint fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@795 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 94efebf169656da3179640ce9c02e8416cc75a18 --- .../example/Bitmap_cubical_complex.cpp | 30 ++- .../example/Random_bitmap_cubical_complex.cpp | 28 +- .../include/gudhi/Bitmap_cubical_complex.h | 294 +++++++++++---------- .../include/gudhi/Bitmap_cubical_complex_base.h | 144 +++++----- src/Bitmap_cubical_complex/include/gudhi/counter.h | 23 +- 5 files changed, 277 insertions(+), 242 deletions(-) diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index c0dbaf36..37c16618 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -20,33 +20,35 @@ * along with this program. If not, see . */ -//for persistence algorithm -#include "gudhi/reader_utils.h" -#include "gudhi/Bitmap_cubical_complex.h" -#include "gudhi/Persistent_cohomology.h" +// for persistence algorithm +#include +#include +#include #include -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include +using namespace Gudhi; +using namespace Gudhi::persistent_cohomology; using namespace std; int main(int argc, char** argv) { - cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbed in \ -the first line is a dimension D of a cubical complex. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes " + "provided in text files in Perseus style (the only numbed in the first line is a dimension D of a cubical " + "complex. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N " + "denote product of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of " + "top dimensional cells. We assume that the cells are in the lexicographical order. See CubicalOneSphere.txt or " + "CubicalTwoSphere.txt for example." << endl; int p = 2; double min_persistence = 0; if (argc != 2) { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style cubical complex at the input. The program will now terminate.\n"; + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style cubical complex at the " + "input. The program will now terminate.\n"; return 1; } @@ -55,7 +57,7 @@ lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for exam // Compute the persistence diagram of the complex persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients(p); //initilizes the coefficient field for homology + pcoh.init_coefficients(p); // initializes the coefficient field for homology pcoh.compute_persistent_cohomology(min_persistence); diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index de9d96e0..ac7557ce 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -21,31 +21,31 @@ */ -//for persistence algorithm -#include "gudhi/reader_utils.h" -#include "gudhi/Bitmap_cubical_complex.h" -#include "gudhi/Persistent_cohomology.h" +// for persistence algorithm +#include +#include +#include #include -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include #include #include #include +using namespace Gudhi; +using namespace Gudhi::persistent_cohomology; using namespace std; int main(int argc, char** argv) { srand(time(0)); - cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes. \ -The first parameter of the program is the dimension D of the cubical complex. The next D parameters are number of top dimensional cubes in each dimension of the cubical complex.\ -The program will create random cubical complex of that sizes and compute persistent homology of it." << endl; + cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes. " + "The first parameter of the program is the dimension D of the cubical complex. The next D parameters are number " + "of top dimensional cubes in each dimension of the cubical complex. The program will create random cubical " + "complex of that sizes and compute persistent homology of it." << endl; int p = 2; double min_persistence = 0; @@ -64,17 +64,13 @@ The program will create random cubical complex of that sizes and compute persist data.push_back(rand() / (double) RAND_MAX); } - - Bitmap_cubical_complex b(sizes, data); - // Compute the persistence diagram of the complex persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients(p); //initilizes the coefficient field for homology + pcoh.init_coefficients(p); // initializes the coefficient field for homology pcoh.compute_persistent_cohomology(min_persistence); - stringstream ss; ss << "randomComplex_persistence"; std::ofstream out((char*) ss.str().c_str()); diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 61ae8105..2f8cb0a3 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -23,38 +23,41 @@ #ifndef BITMAP_CUBICAL_COMPLEX_H_ #define BITMAP_CUBICAL_COMPLEX_H_ -#include - #include -//global variable, was used just for debugging. +#include +#include // for pair +#include // for sort +#include // for vector + +// global variable, was used just for debugging. bool globalDbg = false; template class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { public: - //*********************************************************************************************************************************// - //Typedefs and typenames - //*********************************************************************************************************************************// + //******************************************************************************************************************// + // Typedefs and typenames + //******************************************************************************************************************// friend class Simplex_handle; typedef size_t Simplex_key; typedef T Filtration_value; - //*********************************************************************************************************************************// - //Simplex handle class - //*********************************************************************************************************************************// + //******************************************************************************************************************// + // Simplex handle class + //******************************************************************************************************************// /** - * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. Elements of this class are: the pointer to the bitmap B in which the considered cell is - * together with a position of this cell in B. Given this data, one can get all the information about the considered cell. + * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. Elements of this + * class are: the pointer to the bitmap B in which the considered cell is together with a position of this cell in B. + * Given this data, one can get all the information about the considered cell. **/ class Simplex_handle { public: - Simplex_handle() { if (globalDbg) { - cerr << "Simplex_handle()\n"; + std::cerr << "Simplex_handle()\n"; } this->b = 0; this->position = 0; @@ -62,7 +65,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Simplex_handle(Bitmap_cubical_complex* b) { if (globalDbg) { - cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; + std::cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; } this->b = b; this->position = 0; @@ -70,14 +73,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Simplex_handle(const Simplex_handle& org) : b(org.b) { if (globalDbg) { - cerr << "Simplex_handle( const Simplex_handle& org )\n"; + std::cerr << "Simplex_handle( const Simplex_handle& org )\n"; } this->position = org.position; } Simplex_handle& operator=(const Simplex_handle& rhs) { if (globalDbg) { - cerr << "Simplex_handle operator = \n"; + std::cerr << "Simplex_handle operator = \n"; } this->position = rhs.position; this->b = rhs.b; @@ -86,8 +89,8 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Simplex_handle(Bitmap_cubical_complex* b, Simplex_key position) { if (globalDbg) { - cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; - cerr << "Position : " << position << endl; + std::cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; + std::cerr << "Position : " << position << std::endl; } this->b = b; this->position = position; @@ -95,27 +98,28 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { friend class Bitmap_cubical_complex; private: Bitmap_cubical_complex* b; - Simplex_key position; //Assumption -- this field always keep the REAL position of simplex in the bitmap, no matter what keys have been. - //to deal with the keys, the class Bitmap_cubical_complex have extra vectors: keyAssociatedToSimplex and simplexAssociatedToKey - //that allow to move between actual cell and the key assigned to it. + Simplex_key position; + // Assumption -- this field always keep the REAL position of simplex in the bitmap, no matter what keys have been. + // to deal with the keys, the class Bitmap_cubical_complex have extra vectors: keyAssociatedToSimplex and + // simplexAssociatedToKey that allow to move between actual cell and the key assigned to it. }; - //*********************************************************************************************************************************// - //Constructors - //*********************************************************************************************************************************// - //Over here we need to definie various input types. I am proposing the following ones: - //Perseus style - //H5 files? TODO - //binary files with little endiangs / big endians? TODO - //constructor from a vector of elements of a type T. TODO + //******************************************************************************************************************// + // Constructors + //******************************************************************************************************************// + // Over here we need to definie various input types. I am proposing the following ones: + // Perseus style + // TODO(Pawel Dlotko): H5 files? + // TODO(Pawel Dlotko): binary files with little endiangs / big endians? + // TODO(Pawel Dlotko): constructor from a vector of elements of a type T. /** * Constructor form a Perseus-style file. **/ Bitmap_cubical_complex(char* perseusStyleFile) : Bitmap_cubical_complex_base(perseusStyleFile) { if (globalDbg) { - cerr << "Bitmap_cubical_complex( char* perseusStyleFile )\n"; + std::cerr << "Bitmap_cubical_complex( char* perseusStyleFile )\n"; } std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); @@ -125,16 +129,17 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { } this->keyAssociatedToSimplex = keyAssociatedToSimplex; this->simplexAssociatedToKey = simplexAssociatedToKey; - //we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. + // we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change + // some elements of the bitmap, then this procedure need to be called again. this->initializeElementsOrderedAccordingToFiltration(); } /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells in the following directions and vector of element of a type T - * with filtration on top dimensional cells. + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells in the + * following directions and vector of element of a type T with filtration on top dimensional cells. **/ - Bitmap_cubical_complex(std::vector dimensions, std::vector topDimensionalCells) : Bitmap_cubical_complex_base(dimensions, topDimensionalCells) { + Bitmap_cubical_complex(std::vector dimensions, std::vector topDimensionalCells) + : Bitmap_cubical_complex_base(dimensions, topDimensionalCells) { std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); @@ -143,14 +148,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { } this->keyAssociatedToSimplex = keyAssociatedToSimplex; this->simplexAssociatedToKey = simplexAssociatedToKey; - //we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. + // we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change + // some elements of the bitmap, then this procedure need to be called again. this->initializeElementsOrderedAccordingToFiltration(); } - //*********************************************************************************************************************************// - //Other 'easy' functions - //*********************************************************************************************************************************// + //******************************************************************************************************************// + // Other 'easy' functions + //******************************************************************************************************************// /** * Returns number of all cubes in the complex. @@ -178,7 +183,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ size_t dimension(const Simplex_handle& sh) { if (globalDbg) { - cerr << "int dimension(const Simplex_handle& sh)\n"; + std::cerr << "int dimension(const Simplex_handle& sh)\n"; } if (sh.position != this->data.size()) return sh.b->get_dimension_of_a_cell(sh.position); return std::numeric_limits::max(); @@ -189,9 +194,9 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ T filtration(const Simplex_handle& sh) { if (globalDbg) { - cerr << "T filtration(const Simplex_handle& sh)\n"; + std::cerr << "T filtration(const Simplex_handle& sh)\n"; } - //Returns the filtration value of a simplex. + // Returns the filtration value of a simplex. if (sh.position != this->data.size()) return sh.b->data[ sh.position ]; return INT_MAX; } @@ -201,7 +206,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ Simplex_key null_key() { if (globalDbg) { - cerr << "Simplex_key null_key()\n"; + std::cerr << "Simplex_key null_key()\n"; } return this->data.size(); } @@ -211,7 +216,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ Simplex_key key(const Simplex_handle& sh) { if (globalDbg) { - cerr << "Simplex_key key(const Simplex_handle& sh)\n"; + std::cerr << "Simplex_key key(const Simplex_handle& sh)\n"; } return sh.b->keyAssociatedToSimplex[ sh.position ]; } @@ -221,7 +226,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ Simplex_handle simplex(Simplex_key key) { if (globalDbg) { - cerr << "Simplex_handle simplex(Simplex_key key)\n"; + std::cerr << "Simplex_handle simplex(Simplex_key key)\n"; } return Simplex_handle(this, this->simplexAssociatedToKey[ key ]); } @@ -231,7 +236,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ void assign_key(Simplex_handle& sh, Simplex_key key) { if (globalDbg) { - cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; + std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; } this->keyAssociatedToSimplex[sh.position] = key; this->simplexAssociatedToKey[key] = sh.position; @@ -244,9 +249,9 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { - //*********************************************************************************************************************************// - //Iterators - //*********************************************************************************************************************************// + //******************************************************************************************************************// + // Iterators + //******************************************************************************************************************// /** * Boundary_simplex_iterator class allows iteration on boundary of each cube. @@ -254,13 +259,12 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { class Boundary_simplex_range; class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - //Iterator on the simplices belonging to the boundary of a simplex. - //value_type must be 'Simplex_handle'. + // Iterator on the simplices belonging to the boundary of a simplex. + // value_type must be 'Simplex_handle'. public: - Boundary_simplex_iterator(Simplex_handle& sh) : sh(sh) { if (globalDbg) { - cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n"; + std::cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n"; } this->position = 0; this->boundaryElements = this->sh.b->get_boundary_of_a_cell(this->sh.position); @@ -268,7 +272,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Boundary_simplex_iterator operator++() { if (globalDbg) { - cerr << "Boundary_simplex_iterator operator++()\n"; + std::cerr << "Boundary_simplex_iterator operator++()\n"; } ++this->position; return *this; @@ -282,16 +286,17 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Boundary_simplex_iterator operator=(const Boundary_simplex_iterator& rhs) { if (globalDbg) { - cerr << "Boundary_simplex_iterator operator =\n"; + std::cerr << "Boundary_simplex_iterator operator =\n"; } this->sh = rhs.sh; this->boundaryElements.clear(); - this->boundaryElementsinsert(this->boundaryElements.end(), rhs.boundaryElements.begin(), rhs.boundaryElements.end()); + this->boundaryElementsinsert(this->boundaryElements.end(), + rhs.boundaryElements.begin(), rhs.boundaryElements.end()); } bool operator==(const Boundary_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator ==\n"; + std::cerr << "bool operator ==\n"; } if (this->position == rhs.position) { if (this->boundaryElements.size() != rhs.boundaryElements.size())return false; @@ -305,14 +310,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator!=(const Boundary_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator != \n"; + std::cerr << "bool operator != \n"; } return !(*this == rhs); } Simplex_handle operator*() { if (globalDbg) { - cerr << "Simplex_handle operator*\n"; + std::cerr << "Simplex_handle operator*\n"; } return Simplex_handle(this->sh.b, this->boundaryElements[this->position]); } @@ -328,15 +333,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { * Boundary_simplex_range class provides ranges for boundary iterators. **/ class Boundary_simplex_range { - //Range giving access to the simplices in the boundary of a simplex. - //.begin() and .end() return type Boundary_simplex_iterator. + // Range giving access to the simplices in the boundary of a simplex. + // .begin() and .end() return type Boundary_simplex_iterator. public: - - Boundary_simplex_range(const Simplex_handle& sh) : sh(sh) { }; + Boundary_simplex_range(const Simplex_handle& sh) : sh(sh) { } Boundary_simplex_iterator begin() { if (globalDbg) { - cerr << "Boundary_simplex_iterator begin\n"; + std::cerr << "Boundary_simplex_iterator begin\n"; } Boundary_simplex_iterator it(this->sh); return it; @@ -344,12 +348,13 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Boundary_simplex_iterator end() { if (globalDbg) { - cerr << "Boundary_simplex_iterator end()\n"; + std::cerr << "Boundary_simplex_iterator end()\n"; } Boundary_simplex_iterator it(this->sh); it.position = it.boundaryElements.size(); return it; } + private: Simplex_handle sh; }; @@ -363,17 +368,16 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { class Filtration_simplex_range; class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - //Iterator over all simplices of the complex in the order of the indexing scheme. - //'value_type' must be 'Simplex_handle'. + // Iterator over all simplices of the complex in the order of the indexing scheme. + // 'value_type' must be 'Simplex_handle'. public: + Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { } - Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { }; - - Filtration_simplex_iterator() : b(NULL) { }; + Filtration_simplex_iterator() : b(NULL) { } Filtration_simplex_iterator operator++() { if (globalDbg) { - cerr << "Filtration_simplex_iterator operator++\n"; + std::cerr << "Filtration_simplex_iterator operator++\n"; } ++this->position; return (*this); @@ -387,7 +391,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Filtration_simplex_iterator operator=(const Filtration_simplex_iterator& rhs) { if (globalDbg) { - cerr << "Filtration_simplex_iterator operator =\n"; + std::cerr << "Filtration_simplex_iterator operator =\n"; } this->b = rhs.b; this->position = rhs.position; @@ -395,7 +399,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator==(const Filtration_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; + std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; } if (this->position == rhs.position) { return true; @@ -405,14 +409,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator!=(const Filtration_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; + std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; } return !(*this == rhs); } Simplex_handle operator*() { if (globalDbg) { - cerr << "Simplex_handle operator*()\n"; + std::cerr << "Simplex_handle operator*()\n"; } return Simplex_handle(this->b, this->b->elementsOrderedAccordingToFiltration[ this->position ]); } @@ -427,22 +431,21 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. **/ class Filtration_simplex_range { - //Range over the simplices of the complex in the order of the filtration. - //.begin() and .end() return type Filtration_simplex_iterator. + // Range over the simplices of the complex in the order of the filtration. + // .begin() and .end() return type Filtration_simplex_iterator. public: - - Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { }; + Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { } Filtration_simplex_iterator begin() { if (globalDbg) { - cerr << "Filtration_simplex_iterator begin() \n"; + std::cerr << "Filtration_simplex_iterator begin() \n"; } return Filtration_simplex_iterator(this->b); } Filtration_simplex_iterator end() { if (globalDbg) { - cerr << "Filtration_simplex_iterator end()\n"; + std::cerr << "Filtration_simplex_iterator end()\n"; } Filtration_simplex_iterator it(this->b); it.position = this->b->elementsOrderedAccordingToFiltration.size(); @@ -454,40 +457,44 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { - //*********************************************************************************************************************************// - //Methods to access iterators from the container: + //******************************************************************************************************************// + // Methods to access iterators from the container: /** * boundary_simplex_range creates an object of a Boundary_simplex_range class that provides ranges for the Boundary_simplex_iterator. **/ Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) { if (globalDbg) { - cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n"; + std::cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n"; } - //Returns a range giving access to all simplices of the boundary of a simplex, i.e. the set of codimension 1 subsimplices of the Simplex. + // Returns a range giving access to all simplices of the boundary of a simplex, i.e. the set of + // codimension 1 subsimplices of the Simplex. return Boundary_simplex_range(sh); } /** - * filtration_simplex_range creates an object of a Filtration_simplex_range class that provides ranges for the Filtration_simplex_iterator. + * filtration_simplex_range creates an object of a Filtration_simplex_range class that provides ranges for the + * Filtration_simplex_iterator. **/ Filtration_simplex_range filtration_simplex_range() { if (globalDbg) { - cerr << "Filtration_simplex_range filtration_simplex_range()\n"; + std::cerr << "Filtration_simplex_range filtration_simplex_range()\n"; } - //Returns a range over the simplices of the complex in the order of the filtration + // Returns a range over the simplices of the complex in the order of the filtration return Filtration_simplex_range(this); } - //*********************************************************************************************************************************// + //******************************************************************************************************************// - //*********************************************************************************************************************************// - //Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. - //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so I understand that this is something that was planned (for simplicial maps?) - //but was never finished. The only idea I have here is to use the same empty structure from IndexingTag.h file, but only if the compiler needs it. If the compiler - //do not need it, then I would rather not add here elements which I do not understand. - //typedef Indexing_tag + //******************************************************************************************************************// + // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are + // there. + // TODO(Pawel Dlotko): The file IndexingTag.h in the Gudhi library contains an empty structure, so I understand that + // this is something that was planned (for simplicial maps?) but was never finished. The only idea I have here is + // to use the same empty structure from IndexingTag.h file, but only if the compiler needs it. If the compiler + // do not need it, then I would rather not add here elements which I do not understand. + // typedef Indexing_tag /** * Function needed for compatibility with Gudhi. Not useful for other purposes. @@ -495,11 +502,13 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { std::pair endpoints(Simplex_handle sh) { std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh.position); if (globalDbg) { - cerr << "std::pair endpoints( Simplex_handle sh )\n"; - cerr << "bdry.size() : " << bdry.size() << endl; + std::cerr << "std::pair endpoints( Simplex_handle sh )\n"; + std::cerr << "bdry.size() : " << bdry.size() << std::endl; } - //this method returns two first elements from the boundary of sh. - if (bdry.size() < 2)throw ("Error in endpoints in Bitmap_cubical_complex class. The cell for which this method was called have less than two elements in the boundary."); + // this method returns two first elements from the boundary of sh. + if (bdry.size() < 2) + throw("Error in endpoints in Bitmap_cubical_complex class. " + "The cell for which this method was called have less than two elements in the boundary."); return std::make_pair(Simplex_handle(this, bdry[0]), Simplex_handle(this, bdry[1])); } @@ -510,30 +519,31 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { class Skeleton_simplex_range; class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - //Iterator over all simplices of the complex in the order of the indexing scheme. - //'value_type' must be 'Simplex_handle'. + // Iterator over all simplices of the complex in the order of the indexing scheme. + // 'value_type' must be 'Simplex_handle'. public: - Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) { if (globalDbg) { - cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; + std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; } - //find the position of the first simplex of a dimension d + // find the position of the first simplex of a dimension d this->position = 0; - while ((this->position != b->data.size()) && (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { + while ((this->position != b->data.size()) && + (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { ++this->position; } - }; + } - Skeleton_simplex_iterator() : b(NULL), dimension(0) { }; + Skeleton_simplex_iterator() : b(NULL), dimension(0) { } Skeleton_simplex_iterator operator++() { if (globalDbg) { - cerr << "Skeleton_simplex_iterator operator++()\n"; + std::cerr << "Skeleton_simplex_iterator operator++()\n"; } - //increment the position as long as you did not get to the next element of the dimension dimension. + // increment the position as long as you did not get to the next element of the dimension dimension. ++this->position; - while ((this->position != this->b->data.size()) && (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { + while ((this->position != this->b->data.size()) && + (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { ++this->position; } return (*this); @@ -547,7 +557,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { Skeleton_simplex_iterator operator=(const Skeleton_simplex_iterator& rhs) { if (globalDbg) { - cerr << "Skeleton_simplex_iterator operator =\n"; + std::cerr << "Skeleton_simplex_iterator operator =\n"; } this->b = rhs.b; this->position = rhs.position; @@ -555,7 +565,7 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator==(const Skeleton_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator ==\n"; + std::cerr << "bool operator ==\n"; } if (this->position == rhs.position) { return true; @@ -565,14 +575,14 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { bool operator!=(const Skeleton_simplex_iterator& rhs) { if (globalDbg) { - cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; + std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; } return !(*this == rhs); } Simplex_handle operator*() { if (globalDbg) { - cerr << "Simplex_handle operator*() \n"; + std::cerr << "Simplex_handle operator*() \n"; } return Simplex_handle(this->b, this->position); } @@ -588,27 +598,27 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { * Class needed for compatibility with Gudhi. Not useful for other purposes. **/ class Skeleton_simplex_range { - //Range over the simplices of the complex in the order of the filtration. - //.begin() and .end() return type Filtration_simplex_iterator. + // Range over the simplices of the complex in the order of the filtration. + // .begin() and .end() return type Filtration_simplex_iterator. public: - - Skeleton_simplex_range(Bitmap_cubical_complex* b, int dimension) : b(b), dimension(dimension) { }; + Skeleton_simplex_range(Bitmap_cubical_complex* b, int dimension) : b(b), dimension(dimension) { } Skeleton_simplex_iterator begin() { if (globalDbg) { - cerr << "Skeleton_simplex_iterator begin()\n"; + std::cerr << "Skeleton_simplex_iterator begin()\n"; } return Skeleton_simplex_iterator(this->b, this->dimension); } Skeleton_simplex_iterator end() { if (globalDbg) { - cerr << "Skeleton_simplex_iterator end()\n"; + std::cerr << "Skeleton_simplex_iterator end()\n"; } Skeleton_simplex_iterator it(this->b, this->dimension); it.position = this->b->data.size(); return it; } + private: Bitmap_cubical_complex* b; int dimension; @@ -619,22 +629,22 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { **/ Skeleton_simplex_range skeleton_simplex_range(int dimension) { if (globalDbg) { - cerr << "Skeleton_simplex_range skeleton_simplex_range( int dimension )\n"; + std::cerr << "Skeleton_simplex_range skeleton_simplex_range( int dimension )\n"; } return Skeleton_simplex_range(this, dimension); } - //*********************************************************************************************************************************// - //functions used for debugging: + //******************************************************************************************************************// + // functions used for debugging: /** * Function used for debugging purposes. **/ void printKeyAssociatedToSimplex() { for (size_t i = 0; i != this->data.size(); ++i) { - cerr << i << " -> " << this->simplexAssociatedToKey[i] << endl; + std::cerr << i << " -> " << this->simplexAssociatedToKey[i] << std::endl; } } @@ -648,13 +658,17 @@ class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { private: std::vector< size_t > keyAssociatedToSimplex; std::vector< size_t > simplexAssociatedToKey; - std::vector< size_t > elementsOrderedAccordingToFiltration; //needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. -}; //Bitmap_cubical_complex + // needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. + std::vector< size_t > elementsOrderedAccordingToFiltration; +}; template -bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< size_t, std::pair< T, char > >& f, const std::pair< size_t, std::pair< T, char > >& s) { +bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< size_t, + std::pair< T, char > >& f, + const std::pair< size_t, + std::pair< T, char > >& s) { if (globalDbg) { - cerr << "ompareElementsForElementsOrderedAccordingToFiltration\n"; + std::cerr << "ompareElementsForElementsOrderedAccordingToFiltration\n"; } if (f.second.first < s.second.first) { return true; @@ -662,14 +676,15 @@ bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< siz if (f.second.first > s.second.first) { return false; } else { - //in this case f.second.first == s.second.first, and we use dimension to compare: + // in this case f.second.first == s.second.first, and we use dimension to compare: if (f.second.second < s.second.second) { return true; } else { if (f.second.second > s.second.second) { return false; } else { - //in this case, both the filtration value and the dimensions for those cells are the same. Since it may be nice to have a stable sorting procedure, in this case, we compare positions in the bitmap: + // in this case, both the filtration value and the dimensions for those cells are the same. + // Since it may be nice to have a stable sorting procedure, in this case, we compare positions in the bitmap: return ( f.first < s.first); } } @@ -680,21 +695,24 @@ bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< siz template void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() { if (globalDbg) { - cerr << "void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() \n"; + std::cerr << "void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() \n"; } - //( position , (filtration , dimension) ) + // ( position , (filtration , dimension) ) std::vector< std::pair< size_t, std::pair< T, char > > > dataOfElementsFromBitmap(this->data.size()); for (size_t i = 0; i != this->data.size(); ++i) { - //TODO -- this can be optimized by having a counter here. We do not need to re-compute the dimension for every cell from scratch + // TODO(Pawel Dlotko): This can be optimized by having a counter here. We do not need to re-compute the dimension + // for every cell from scratch dataOfElementsFromBitmap[i] = std::make_pair(i, std::make_pair(this->data[i], this->get_dimension_of_a_cell(i))); } - std::sort(dataOfElementsFromBitmap.begin(), dataOfElementsFromBitmap.end(), compareElementsForElementsOrderedAccordingToFiltration); + std::sort(dataOfElementsFromBitmap.begin(), dataOfElementsFromBitmap.end(), + compareElementsForElementsOrderedAccordingToFiltration); - std::vector< size_t > elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap(this->data.size()); + // Elements of bitmap ordered according to filtration then according to dimension then according to position in bitmap + std::vector< size_t > elements_of_bitmap_ordered(this->data.size()); for (size_t i = 0; i != dataOfElementsFromBitmap.size(); ++i) { - elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap[i] = dataOfElementsFromBitmap[i].first; + elements_of_bitmap_ordered[i] = dataOfElementsFromBitmap[i].first; } - this->elementsOrderedAccordingToFiltration = elementsOfBitmapOrderedAccordingToFiltrationThenAccordingToDimensionThenAccordingToPositionInBitmap; + this->elementsOrderedAccordingToFiltration = elements_of_bitmap_ordered; } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 26c97872..d9c91832 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -23,20 +23,17 @@ #ifndef BITMAP_CUBICAL_COMPLEX_BASE_H_ #define BITMAP_CUBICAL_COMPLEX_BASE_H_ +#include + #include #include #include -#include #include #include #include #include #include -#include - -using namespace std; - /** * This is a class implementing a basic bitmap data structure to store cubical complexes. It implements only the most basic subroutines. * The idea of the bitmap is the following. Our aim is to have a memory efficient data structure to store d-dimensional cubical complex C being a cubical decomposition @@ -89,7 +86,7 @@ class Bitmap_cubical_complex_base { * cells. The most typical one is by so called lower star filtration. This function is always called by any constructor which takes the top dimensional cells. If you use such a constructor, * then there is no need to call this function. Call it only if you are putting the filtration of the cells by your own (for instance by using topDimensionalCellsIterator). **/ - void impose_lower_star_filtration(); //assume that top dimensional cells are already set. + void impose_lower_star_filtration(); // assume that top dimensional cells are already set. /** * Returns dimension of a complex. @@ -109,9 +106,9 @@ class Bitmap_cubical_complex_base { * Writing to stream operator. **/ template - friend ostream& operator<<(ostream & os_, const Bitmap_cubical_complex_base& b_); + friend std::ostream& operator<<(std::ostream & os_, const Bitmap_cubical_complex_base& b_); - //ITERATORS + // ITERATORS /** * Iterator through all cells in the complex (in order they appear in the structure -- i.e. in lexicographical order). @@ -142,7 +139,6 @@ class Bitmap_cubical_complex_base { **/ class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > { public: - Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b_) : b(b_) { for (size_t i = 0; i != b_.dimension(); ++i) { this->counter.push_back(0); @@ -150,7 +146,7 @@ class Bitmap_cubical_complex_base { } Top_dimensional_cells_iterator operator++() { - //first find first element of the counter that can be increased: + // first find first element of the counter that can be increased: size_t dim = 0; while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; @@ -191,7 +187,7 @@ class Bitmap_cubical_complex_base { } T& operator*() { - //given the counter, compute the index in the array and return this element. + // given the counter, compute the index in the array and return this element. unsigned index = 0; for (size_t i = 0; i != this->counter.size(); ++i) { index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; @@ -209,7 +205,7 @@ class Bitmap_cubical_complex_base { void printCounter() { for (size_t i = 0; i != this->counter.size(); ++i) { - cout << this->counter[i] << " "; + std::cout << this->counter[i] << " "; } } friend class Bitmap_cubical_complex_base; @@ -255,10 +251,10 @@ class Bitmap_cubical_complex_base { for (size_t i = 0; i != sizes_.size(); ++i) { this->sizes.push_back(sizes_[i]); this->multipliers.push_back(multiplier); - //multiplier *= 2*(sizes[i]+1)+1; + // multiplier *= 2*(sizes[i]+1)+1; multiplier *= 2 * sizes_[i] + 1; } - //std::reverse( this->sizes.begin() , this->sizes.end() ); + // std::reverse( this->sizes.begin() , this->sizes.end() ); std::vector data(multiplier); std::fill(data.begin(), data.end(), INT_MAX); this->totalNumberOfCells = multiplier; @@ -287,9 +283,11 @@ class Bitmap_cubical_complex_base { }; template -ostream& operator<<(ostream & out_, const Bitmap_cubical_complex_base& b_) { - //for ( typename bitmap::all_cells_const_iterator it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) - for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b_.all_cells_const_begin(); it != b_.all_cells_const_end(); ++it) { +std::ostream& operator<<(std::ostream & out_, const Bitmap_cubical_complex_base& b_) { + // for ( typename bitmap::all_cells_const_iterator it = b.all_cells_const_begin() ; + // it != b.all_cells_const_end() ; ++it ) + for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b_.all_cells_const_begin(); + it != b_.all_cells_const_end(); ++it) { out_ << *it << " "; } return out_; @@ -301,7 +299,8 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_, std::vector topDimensionalCells_) { +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_, + std::vector topDimensionalCells_) { this->set_up_containers(sizesInFollowingDirections_); size_t numberOfTopDimensionalElements = 1; @@ -309,8 +308,12 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_ , std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from sizesInFollowingDirections vector is different than the size of topDimensionalCells vector." << endl; - throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from sizesInFollowingDirections vector is different than the size of topDimensionalCells vector."); + std::cerr << "Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , " + "std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from " + "sizesInFollowingDirections vector is different than the size of topDimensionalCells vector." << std::endl; + throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , " + "std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from " + "sizesInFollowingDirections vector is different than the size of topDimensionalCells vector."); } Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); @@ -325,13 +328,13 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFile_) { bool dbg = false; - ifstream inFiltration, inIds; + std::ifstream inFiltration, inIds; inFiltration.open(perseusStyleFile_); unsigned dimensionOfData; inFiltration >> dimensionOfData; if (dbg) { - cerr << "dimensionOfData : " << dimensionOfData << endl; + std::cerr << "dimensionOfData : " << dimensionOfData << std::endl; } std::vector sizes; @@ -341,7 +344,7 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFi sizeInThisDimension = abs(sizeInThisDimension); sizes.push_back(sizeInThisDimension); if (dbg) { - cerr << "sizeInThisDimension : " << sizeInThisDimension << endl; + std::cerr << "sizeInThisDimension : " << sizeInThisDimension << std::endl; } } this->set_up_containers(sizes); @@ -349,12 +352,14 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFi Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); it = this->top_dimensional_cells_begin(); - //TODO -- over here we also need to read id's of cell and put them to bitmapElement structure! + // TODO(Pawel Dlotko): Over here we also need to read id's of cell and put them to bitmapElement structure! while (!inFiltration.eof()) { double filtrationLevel; inFiltration >> filtrationLevel; if (dbg) { - cerr << "Cell of an index : " << it.computeIndexInBitmap() << " and dimension: " << this->get_dimension_of_a_cell(it.computeIndexInBitmap()) << " get the value : " << filtrationLevel << endl; + std::cerr << "Cell of an index : " << it.computeIndexInBitmap() << " and dimension: " << + this->get_dimension_of_a_cell(it.computeIndexInBitmap()) << " get the value : " << + filtrationLevel << std::endl; } *it = filtrationLevel; ++it; @@ -366,7 +371,8 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFi template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell_) { bool bdg = false; - //first of all, we need to take the list of coordinates in which the cell has nonzero length. We do it by using modified version to compute dimension of a cell: + // First of all, we need to take the list of coordinates in which the cell has nonzero length. + // We do it by using modified version to compute dimension of a cell: std::vector< unsigned > dimensionsInWhichCellHasNonzeroLength; unsigned dimension = 0; size_t cell1 = cell_; @@ -380,9 +386,9 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(siz } if (bdg) { - cerr << "dimensionsInWhichCellHasNonzeroLength : \n"; + std::cerr << "dimensionsInWhichCellHasNonzeroLength : \n"; for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { - cerr << dimensionsInWhichCellHasNonzeroLength[i] << endl; + std::cerr << dimensionsInWhichCellHasNonzeroLength[i] << std::endl; } getchar(); } @@ -393,9 +399,12 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(siz boundaryElements.push_back(cell_ - multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); boundaryElements.push_back(cell_ + multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); - if (bdg) cerr << "multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; - if (bdg) cerr << "cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; - if (bdg) cerr << "cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << endl; + if (bdg) std::cerr << "multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; + if (bdg) std::cerr << "cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << + cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; + if (bdg) std::cerr << "cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << + cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; } return boundaryElements; } @@ -403,7 +412,8 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(siz template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(size_t cell_) { bool bdg = false; - //first of all, we need to take the list of coordinates in which the cell has nonzero length. We do it by using modified version to compute dimension of a cell: + // First of all, we need to take the list of coordinates in which the cell has nonzero length. + // We do it by using modified version to compute dimension of a cell: std::vector< unsigned > dimensionsInWhichCellHasZeroLength; unsigned dimension = 0; size_t cell1 = cell_; @@ -417,16 +427,16 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(s } std::vector counter = this->compute_counter_for_given_cell(cell_); - //reverse(counter.begin() , counter.end()); + // reverse(counter.begin() , counter.end()); if (bdg) { - cerr << "dimensionsInWhichCellHasZeroLength : \n"; + std::cerr << "dimensionsInWhichCellHasZeroLength : \n"; for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { - cerr << dimensionsInWhichCellHasZeroLength[i] << endl; + std::cerr << dimensionsInWhichCellHasZeroLength[i] << std::endl; } - cerr << "\n counter : " << endl; + std::cerr << "\n counter : " << std::endl; for (size_t i = 0; i != counter.size(); ++i) { - cerr << counter[i] << endl; + std::cerr << counter[i] << std::endl; } getchar(); } @@ -435,27 +445,29 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(s if (dimensionsInWhichCellHasZeroLength.size() == 0)return coboundaryElements; for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { if (bdg) { - cerr << "Dimension : " << i << endl; + std::cerr << "Dimension : " << i << std::endl; if (counter[dimensionsInWhichCellHasZeroLength[i]] == 0) { - cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + std::cerr << "In dimension : " << i << + " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; } if (counter[dimensionsInWhichCellHasZeroLength[i]] == 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]]) { - cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + std::cerr << "In dimension : " << i << + " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; } } - if ((cell_ > multipliers[dimensionsInWhichCellHasZeroLength[i]]) && (counter[dimensionsInWhichCellHasZeroLength[i]] != 0)) - //if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 0 ) - { - if (bdg)cerr << "Subtracting : " << cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]] << endl; + if ((cell_ > multipliers[dimensionsInWhichCellHasZeroLength[i]]) && + (counter[dimensionsInWhichCellHasZeroLength[i]] != 0)) { + // if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 0 ) + if (bdg)std::cerr << "Subtracting : " << cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]] << std::endl; coboundaryElements.push_back(cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]]); } - if ((cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] < this->data.size()) && (counter[dimensionsInWhichCellHasZeroLength[i]] != 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]])) - //if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 2*this->sizes[dimensionsInWhichCellHasZeroLength[i]] ) - { + if ((cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] < this->data.size()) && + (counter[dimensionsInWhichCellHasZeroLength[i]] != 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]])) { + // if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 2*this->sizes[dimensionsInWhichCellHasZeroLength[i]] ) coboundaryElements.push_back(cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]]); - if (bdg)cerr << "Adding : " << cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] << endl; + if (bdg)std::cerr << "Adding : " << cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] << std::endl; } } return coboundaryElements; @@ -464,19 +476,19 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(s template unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell(size_t cell_) { bool dbg = false; - if (dbg)cerr << "\n\n\n Computing position o a cell of an index : " << cell_ << endl; + if (dbg)std::cerr << "\n\n\n Computing position o a cell of an index : " << cell_ << std::endl; unsigned dimension = 0; for (size_t i = this->multipliers.size(); i != 0; --i) { unsigned position = cell_ / multipliers[i - 1]; - if (dbg)cerr << "i-1 :" << i - 1 << endl; - if (dbg)cerr << "cell_ : " << cell_ << endl; - if (dbg)cerr << "position : " << position << endl; - if (dbg)cerr << "multipliers[" << i - 1 << "] = " << multipliers[i - 1] << endl; + if (dbg)std::cerr << "i-1 :" << i - 1 << std::endl; + if (dbg)std::cerr << "cell_ : " << cell_ << std::endl; + if (dbg)std::cerr << "position : " << position << std::endl; + if (dbg)std::cerr << "multipliers[" << i - 1 << "] = " << multipliers[i - 1] << std::endl; if (dbg)getchar(); if (position % 2 == 1) { - if (dbg)cerr << "Nonzero length in this direction \n"; + if (dbg)std::cerr << "Nonzero length in this direction \n"; dimension++; } cell_ = cell_ % multipliers[i - 1]; @@ -493,11 +505,12 @@ template void Bitmap_cubical_complex_base::impose_lower_star_filtration() { bool dbg = false; - //this vector will be used to check which elements have already been taken care of in imposing lower star filtration: + // this vector will be used to check which elements have already been taken care of in imposing lower star filtration: std::vector isThisCellConsidered(this->data.size(), false); std::vector indicesToConsider; - //we assume here that we already have a filtration on the top dimensional cells and we have to extend it to lower ones. + // we assume here that we already have a filtration on the top dimensional cells + // and we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { indicesToConsider.push_back(it.computeIndexInBitmap()); @@ -505,9 +518,9 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { while (indicesToConsider.size()) { if (dbg) { - cerr << "indicesToConsider in this iteration \n"; + std::cerr << "indicesToConsider in this iteration \n"; for (size_t i = 0; i != indicesToConsider.size(); ++i) { - cout << indicesToConsider[i] << " "; + std::cout << indicesToConsider[i] << " "; } getchar(); } @@ -529,9 +542,12 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { } template -std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_) { +std::vector< size_t > +Bitmap_cubical_complex_base::generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_) { bool dbg = false; - if (this->sizes.size() != directionsForPeriodicBCond_.size())throw "directionsForPeriodicBCond_ vector size is different from the size of the bitmap. The program will now terminate \n"; + if (this->sizes.size() != directionsForPeriodicBCond_.size()) + throw ("directionsForPeriodicBCond_ vector size is different from the size of the bitmap. " + "The program will now terminate \n"); std::vector sizes(this->sizes.size()); for (size_t i = 0; i != this->sizes.size(); ++i)sizes[i] = 2 * this->sizes[i]; @@ -544,7 +560,7 @@ std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_ size_t position; if (!c.isFinal()) { position = i; - //result.push_back( i ); + // result.push_back( i ); } else { std::vector< bool > finals = c.directionsOfFinals(); bool jumpInPosition = false; @@ -555,7 +571,7 @@ std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_ } } if (jumpInPosition == true) { - //in this case this guy is final, so we need to find 'the opposite one' + // in this case this guy is final, so we need to find 'the opposite one' position = compute_position_in_bitmap(c.findOpposite(directionsForPeriodicBCond_)); } else { position = i; @@ -563,8 +579,8 @@ std::vector< size_t > Bitmap_cubical_complex_base::generate_vector_of_shifts_ } result.push_back(position); if (dbg) { - cerr << " position : " << position << endl; - cerr << c << endl; + std::cerr << " position : " << position << std::endl; + std::cerr << c << std::endl; getchar(); } diff --git a/src/Bitmap_cubical_complex/include/gudhi/counter.h b/src/Bitmap_cubical_complex/include/gudhi/counter.h index 9df819b2..9445a422 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/counter.h @@ -26,17 +26,15 @@ #include #include -using namespace std; - /** * This is an implementation of a simple counter. It is needed for the implementation of a bitmapCubicalComplex. **/ class counter { public: - /** - * Constructor of a counter class. It takes only the parameter which is the end value of the counter. The default beginning value is a vector of the same length as the endd, filled-in with zeros. + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. + * The default beginning value is a vector of the same length as the end, filled-in with zeros. **/ counter(std::vector< int > endd) { for (size_t i = 0; i != endd.size(); ++i) { @@ -47,10 +45,12 @@ class counter { } /** - * Constructor of a counter class. It takes as the input beginn and end vector. It assumes that begin vector is lexicographically below the end vector. + * Constructor of a counter class. It takes as the input beginn and endd vector. It assumes that begin vector is + * lexicographically below the end vector. **/ counter(std::vector< int > beginn, std::vector< int > endd) { - if (beginn.size() != endd.size())throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + if (beginn.size() != endd.size()) + throw("In constructor of a counter, begin and end vectors do not have the same size. Program terminate"); for (size_t i = 0; i != endd.size(); ++i) { this->current.push_back(0); this->begin.push_back(0); @@ -59,7 +59,8 @@ class counter { } /** - * Function to increment the counter. If the value returned by the function is true, then the incrementation process was successful. + * Function to increment the counter. If the value returned by the function is true, then the incrementation process + * was successful. * If the value of the function is false, that means, that the counter have reached its end-value. **/ bool increment() { @@ -87,8 +88,9 @@ class counter { } /** - * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. Its aim is to find an counter corresponding to the element the following - * boundary element is identified with when periodic boundary conditions are imposed. + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. + * Its aim is to find an counter corresponding to the element the following boundary element is identified with + * when periodic boundary conditions are imposed. **/ std::vector< int > findOpposite(std::vector< bool > directionsForPeriodicBCond) { std::vector< int > result; @@ -121,12 +123,13 @@ class counter { * Function to write counter to the stream. **/ friend std::ostream& operator<<(std::ostream& out, const counter& c) { - //cerr << "c.current.size() : " << c.current.size() << endl; + // std::cerr << "c.current.size() : " << c.current.size() << std::endl; for (size_t i = 0; i != c.current.size(); ++i) { out << c.current[i] << " "; } return out; } + private: std::vector< int > begin; std::vector< int > end; -- cgit v1.2.3 From ba47def14a25fb1299ef0980366c2c5479fb1ccc Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 2 Oct 2015 09:34:09 +0000 Subject: Review fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@816 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d112bf6b1b07a75947392576baa53321326e65c4 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 8 ++++---- .../example/Alpha_complex_from_off.cpp | 8 +++----- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 4 ++-- .../example/Delaunay_triangulation_off_rw.cpp | 5 ++--- .../include/gudhi/Delaunay_triangulation_off_io.h | 24 +++++++++++----------- 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index d266219b..2cb37578 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -93,8 +93,8 @@ namespace alphacomplex { * \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 + * 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 * 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], ...), @@ -105,8 +105,8 @@ namespace alphacomplex { * * \section alpha-shape Alpha shape * - * In the example above, the alpha shape of \f$\alpha^2_{74} < \alpha^2 < \alpha^2_{73}\f$ is the alpha complex where the - * \f$\alpha^2_{74} <\f$ filtration value \f$< \alpha^2_{73}\f$ as described in \cite AlphaShapesIntroduction + * 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 * * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" * \copyright GNU General Public License v3. diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index b698d6d7..e140fe3d 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,11 +1,9 @@ -#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" +#include +#include void usage(char * const progName) { std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value" << std::endl; diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 7a0800e4..b630e999 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -33,8 +33,8 @@ #include // to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" +#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; diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp index d1aa7988..75e4fafb 100644 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -1,11 +1,10 @@ // to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" +#include #include #include -#include -#include +#include #include // Use dynamic_dimension_tag for the user to be able to set dimension diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index de5fa2af..0c5474c9 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -39,7 +39,7 @@ namespace Gudhi { template class Delaunay_triangulation_off_visitor_reader { private: - Complex* _complex; + Complex* complex_; typedef typename Complex::Point Point; public: @@ -48,10 +48,10 @@ class Delaunay_triangulation_off_visitor_reader { /** \brief Delaunay_triangulation_off_visitor_reader constructor * - * @param[in] _complex_ptr pointer on a Delaunay triangulation. + * @param[in] complex_ptr_ pointer on a Delaunay triangulation. */ - Delaunay_triangulation_off_visitor_reader(Complex* _complex_ptr) - : _complex(nullptr) { } + Delaunay_triangulation_off_visitor_reader(Complex* complex_ptr_) + : complex_(nullptr) { } /** \brief Off_reader visitor init implementation. * @@ -77,7 +77,7 @@ class Delaunay_triangulation_off_visitor_reader { "file for Delaunay triangulation - edges are computed." << std::endl; } // Complex construction with dimension from file - _complex = new Complex(dim); + complex_ = new Complex(dim); } /** \brief Off_reader visitor point implementation. @@ -95,7 +95,7 @@ class Delaunay_triangulation_off_visitor_reader { } std::cout << std::endl; #endif // DEBUG_TRACES - _complex->insert(Point(point.size(), point.begin(), point.end())); + complex_->insert(Point(point.size(), point.begin(), point.end())); } // Off_reader visitor maximal_face implementation - not used @@ -115,7 +115,7 @@ class Delaunay_triangulation_off_visitor_reader { * @warning The returned pointer can be nullptr. */ Complex* get_complex() const { - return _complex; + return complex_; } }; @@ -157,12 +157,12 @@ class Delaunay_triangulation_off_reader { : valid_(false) { std::ifstream stream(name_file); if (stream.is_open()) { - Delaunay_triangulation_off_visitor_reader off_visitor(_complex); + 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) { + 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; } @@ -190,7 +190,7 @@ class Delaunay_triangulation_off_reader { */ Complex* get_complex() const { if (valid_) - return _complex; + return complex_; return nullptr; } @@ -199,7 +199,7 @@ class Delaunay_triangulation_off_reader { /** \brief OFF file read status.*/ bool valid_; /** \brief A pointer on the Delaunay triangulation.*/ - Complex* _complex; + Complex* complex_; }; /** \brief OFF file writer from a Delaunay triangulation. -- cgit v1.2.3 From 2f54f68e92f2a953f49c4864e9c55f5f55c9cf15 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 2 Oct 2015 12:46:09 +0000 Subject: revert commit git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@818 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: cbb03379cd5d8dac58204430b9e80c05497f1db8 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 124 ++++++++++---------------- 1 file changed, 49 insertions(+), 75 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 28c6fee4..279327f7 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -450,16 +450,43 @@ class Simplex_tree { Simplex_handle find_vertex(Vertex_handle v) { return root_.members_.begin() + v; } + + /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. + * + * @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 + * 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 filed of the + * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to + * null_simplex. + * + * All subsimplices do not necessary need to be already in the simplex tree to proceed to an + * insertion. However, the property of being a simplicial complex will be violated. This allows + * us to insert a stream of simplices contained in a simplicial complex without considering any + * order on them. + * + * The filtration value + * assigned to the new simplex must preserve the monotonicity of the filtration. + * + * The type RandomAccessVertexRange must be a range for which .begin() and + * .end() return random access iterators, with 'value_type' Vertex_handle. */ + template + std::pair insert_simplex(RandomAccessVertexRange & simplex, + Filtration_value filtration) { + if (simplex.empty()) { + return std::pair(null_simplex(), true); + } + // must be sorted in increasing order + sort(simplex.begin(), simplex.end()); - private: - /** \brief Inserts a simplex represented by a vector of vertex. - \warning the vector must be sorted by increasing vertex handle order */ - std::pair insert_vertex_vector(const std::vector& simplex, - Filtration_value filtration) { Siblings * curr_sib = &root_; std::pair res_insert; - auto vi = simplex.begin(); - for (; vi != simplex.end() - 1; ++vi) { + typename RandomAccessVertexRange::iterator vi; + for (vi = simplex.begin(); vi != simplex.end() - 1; ++vi) { res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration)); if (!(has_children(res_insert.first))) { res_insert.first->second.assign_children(new Siblings(curr_sib, *vi)); @@ -481,77 +508,24 @@ class Simplex_tree { return res_insert; } - public: - /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. - * - * @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 - * 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. - * - * All subsimplices do not necessary need to be already in the simplex tree to proceed to an - * insertion. However, the property of being a simplicial complex will be violated. This allows - * us to insert a stream of simplices contained in a simplicial complex without considering any - * order on them. - * - * The filtration value - * assigned to the new simplex must preserve the monotonicity of the filtration. - * - * The type InputVertexRange must be a range for which .begin() and - * .end() return input iterators, with 'value_type' Vertex_handle. */ - template - std::pair insert_simplex(const InputVertexRange & simplex, - Filtration_value filtration = 0) { - auto first = std::begin(simplex); - auto last = std::end(simplex); - - if (first == last) - return std::pair(null_simplex(), true); // ----->> - - // Copy before sorting - std::vector copy(first, last); - std::sort(std::begin(copy), std::end(copy)); - return insert_vertex_vector(copy, filtration); - } - - /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of + /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of * Vertex_handles, in the simplicial complex. * * @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 - * 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. */ - template - std::pair insert_simplex_and_subfaces(const InputVertexRange& Nsimplex, - Filtration_value filtration = 0) { - auto first = std::begin(Nsimplex); - auto last = std::end(Nsimplex); - - if (first == last) - return std::pair(null_simplex(), true); // ----->> - - // Copy before sorting - std::vector copy(first, last); - std::sort(std::begin(copy), std::end(copy)); - + template + std::pair insert_simplex_and_subfaces(const RandomAccessVertexRange& Nsimplex, + Filtration_value filtration = 0.0) { + // 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(copy, to_be_inserted, to_be_propagated, filtration); + 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, @@ -560,7 +534,7 @@ class Simplex_tree { std::pair insert_result; if (the_simplex.size() > 1) { // Get and remove last vertex - Vertex_handle last_vertex = the_simplex.back(); + 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); @@ -583,21 +557,21 @@ class Simplex_tree { // insert all to_be_inserted for (auto& simplex_tbi : to_be_inserted) { - insert_result = insert_vertex_vector(simplex_tbi, filtration); + insert_result = insert_simplex(simplex_tbi, filtration); } } 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)) { + 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()); // i.e. (0,1,2) => [to_be_inserted | to_be_propagated] = [(0) | ] to_be_inserted.push_back(first_simplex); - - insert_result = insert_vertex_vector(first_simplex, filtration); + + insert_result = insert_simplex(first_simplex, filtration); } else { std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error" << std::endl; exit(-1); -- cgit v1.2.3 -- cgit v1.2.3 From c14909eae41883308428095758360de3a7202a0d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 2 Oct 2015 13:13:38 +0000 Subject: Backmerge of trunk git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@820 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 812e0b84d187dd5e30a6a18c12612ebc9bf9206a --- src/GudhUI/gui/MainWindow.h | 2 + src/GudhUI/gui/Menu_edge_contraction.h | 2 + src/GudhUI/view/Viewer.h | 3 + src/GudhUI/view/Viewer_instructor.h | 2 + .../include/gudhi/Persistent_cohomology.h | 28 +- .../Persistent_cohomology_column.h | 14 +- src/Simplex_tree/concept/IndexingTag.h | 2 +- src/Simplex_tree/concept/SimplexKey.h | 4 +- src/Simplex_tree/concept/SimplexTreeOptions.h | 41 +++ src/Simplex_tree/concept/VertexHandle.h | 3 +- src/Simplex_tree/example/CMakeLists.txt | 9 +- src/Simplex_tree/example/mini_simplex_tree.cpp | 68 ++++ src/Simplex_tree/include/gudhi/Simplex_tree.h | 354 ++++++++++++++------- .../Simplex_tree_node_explicit_storage.h | 43 +-- .../gudhi/Simplex_tree/Simplex_tree_siblings.h | 6 +- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 276 +++++++++------- src/common/include/gudhi/Simple_object_pool.h | 64 ++++ 17 files changed, 629 insertions(+), 292 deletions(-) create mode 100644 src/Simplex_tree/concept/SimplexTreeOptions.h create mode 100644 src/Simplex_tree/example/mini_simplex_tree.cpp create mode 100644 src/common/include/gudhi/Simple_object_pool.h diff --git a/src/GudhUI/gui/MainWindow.h b/src/GudhUI/gui/MainWindow.h index 587f1c6f..e46b72a3 100644 --- a/src/GudhUI/gui/MainWindow.h +++ b/src/GudhUI/gui/MainWindow.h @@ -1,6 +1,8 @@ #ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H +// Workaround for moc-qt4 not parsing boost headers +#include #include #include "ui_main_window.h" diff --git a/src/GudhUI/gui/Menu_edge_contraction.h b/src/GudhUI/gui/Menu_edge_contraction.h index e497a90f..81d37bd8 100644 --- a/src/GudhUI/gui/Menu_edge_contraction.h +++ b/src/GudhUI/gui/Menu_edge_contraction.h @@ -8,6 +8,8 @@ #ifndef MENU_EDGE_CONTRACTION_H_ #define MENU_EDGE_CONTRACTION_H_ +// Workaround for moc-qt4 not parsing boost headers +#include #include "gui/MainWindow.h" #include "gui/ui_MenuEdgeContraction.h" diff --git a/src/GudhUI/view/Viewer.h b/src/GudhUI/view/Viewer.h index 5639aa56..00f9b245 100644 --- a/src/GudhUI/view/Viewer.h +++ b/src/GudhUI/view/Viewer.h @@ -1,6 +1,9 @@ #ifndef VIEWER_H #define VIEWER_H +// Workaround for moc-qt4 not parsing boost headers +#include + #include #include "View_parameter.h" #include "model/Complex_typedefs.h" diff --git a/src/GudhUI/view/Viewer_instructor.h b/src/GudhUI/view/Viewer_instructor.h index 9a2a236b..62b3755e 100644 --- a/src/GudhUI/view/Viewer_instructor.h +++ b/src/GudhUI/view/Viewer_instructor.h @@ -3,6 +3,8 @@ // todo do a viewer instructor that have directely a pointer to a QGLviewer and buffer ot not triangles +// Workaround for moc-qt4 not parsing boost headers +#include #include diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index 4c818ffa..5f399f1a 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -25,12 +25,12 @@ #include #include +#include #include #include #include #include -#include #include #include @@ -243,7 +243,7 @@ class Persistent_cohomology { column_pool_(), // memory pools for the CAM cell_pool_() { Simplex_key idx_fil = 0; - for (auto & sh : cpx_->filtration_simplex_range()) { + for (auto sh : cpx_->filtration_simplex_range()) { cpx_->assign_key(sh, idx_fil); ++idx_fil; dsets_.make_set(cpx_->key(sh)); @@ -266,13 +266,10 @@ class Persistent_cohomology { } ~Persistent_cohomology() { -// Clean the remaining columns in the matrix. - for (auto & cam_ref : cam_) { - cam_ref.col_.clear(); - } -// Clean the transversal lists + // Clean the transversal lists for (auto & transverse_ref : transverse_idx_) { - transverse_ref.second.row_->clear(); + // Destruct all the cells + transverse_ref.second.row_->clear_and_dispose([&](Cell*p){p->~Cell();}); delete transverse_ref.second.row_; } } @@ -572,9 +569,8 @@ class Persistent_cohomology { Column * curr_col = row_cell_it->self_col_; ++row_cell_it; // Disconnect the column from the rows in the CAM. - for (auto col_cell_it = curr_col->col_.begin(); - col_cell_it != curr_col->col_.end(); ++col_cell_it) { - col_cell_it->base_hook_cam_h::unlink(); + for (auto& col_cell : curr_col->col_) { + col_cell.base_hook_cam_h::unlink(); } // Remove the column from the CAM before modifying its value @@ -589,9 +585,9 @@ class Persistent_cohomology { // Find whether the column obtained is already in the CAM result_insert_cam = cam_.insert(*curr_col); if (result_insert_cam.second) { // If it was not in the CAM before: insertion has succeeded - for (auto col_cell_it = curr_col->col_.begin(); col_cell_it != curr_col->col_.end(); ++col_cell_it) { + for (auto& col_cell : curr_col->col_) { // re-establish the row links - transverse_idx_[col_cell_it->key_].row_->push_front(*col_cell_it); + transverse_idx_[col_cell.key_].row_->push_front(col_cell); } } else { // There is already an identical column in the CAM: // merge two disjoint sets. @@ -601,6 +597,8 @@ class Persistent_cohomology { Simplex_key key_tmp = dsets_.find_set(curr_col->class_key_); ds_repr_[key_tmp] = &(*(result_insert_cam.first)); result_insert_cam.first->class_key_ = key_tmp; + // intrusive containers don't own their elements, we have to release them manually + curr_col->col_.clear_and_dispose([&](Cell*p){cell_pool_.destroy(p);}); column_pool_.destroy(curr_col); // delete curr_col; } } @@ -766,8 +764,8 @@ class Persistent_cohomology { std::vector persistent_pairs_; length_interval interval_length_policy; - boost::object_pool column_pool_; - boost::object_pool cell_pool_; + Simple_object_pool column_pool_; + Simple_object_pool cell_pool_; }; /** @} */ // end defgroup persistent_cohomology diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h index fcec819a..5ffd1776 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h @@ -93,27 +93,25 @@ class Persistent_cohomology_column : public boost::intrusive::set_base_hook< boost::intrusive::base_hook > Col_type; /** \brief Creates an empty column.*/ - explicit Persistent_cohomology_column(SimplexKey key) { - class_key_ = key; - col_ = Col_type(); - } + explicit Persistent_cohomology_column(SimplexKey key) + : col_(), + class_key_(key) {} public: /** Copy constructor.*/ Persistent_cohomology_column(Persistent_cohomology_column const &other) : col_(), class_key_(other.class_key_) { - if (!other.col_.empty()) - std::cerr << "Copying a non-empty column.\n"; + assert(other.col_.empty()); } /** \brief Returns true iff the column is null.*/ - bool is_null() { + bool is_null() const { return col_.empty(); } /** \brief Returns the key of the representative simplex of * the set of simplices having this column as annotation vector * in the compressed annotation matrix.*/ - SimplexKey class_key() { + SimplexKey class_key() const { return class_key_; } diff --git a/src/Simplex_tree/concept/IndexingTag.h b/src/Simplex_tree/concept/IndexingTag.h index d690da11..1dcdd756 100644 --- a/src/Simplex_tree/concept/IndexingTag.h +++ b/src/Simplex_tree/concept/IndexingTag.h @@ -25,6 +25,6 @@ * continuous maps to a cell complex, and compute its persistent * homology. * - * Must be linear_indexing_tag. + * Must be `Gudhi::linear_indexing_tag`. */ struct IndexingTag {}; diff --git a/src/Simplex_tree/concept/SimplexKey.h b/src/Simplex_tree/concept/SimplexKey.h index ce5b2382..7fdbdd84 100644 --- a/src/Simplex_tree/concept/SimplexKey.h +++ b/src/Simplex_tree/concept/SimplexKey.h @@ -22,7 +22,7 @@ /** \brief Key type used as simplex identifier. * - * Must be int + * Must be a signed integer type. */ struct SimplexKey {}; - \ No newline at end of file + diff --git a/src/Simplex_tree/concept/SimplexTreeOptions.h b/src/Simplex_tree/concept/SimplexTreeOptions.h new file mode 100644 index 00000000..a50a2bf1 --- /dev/null +++ b/src/Simplex_tree/concept/SimplexTreeOptions.h @@ -0,0 +1,41 @@ + /* 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): Marc Glisse + * + * Copyright (C) 2015 INRIA Saclay - Ile-de-France (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 . + */ + +/** \brief Concept of the template parameter for the class `Gudhi::Simplex_tree`. + * + * One model for this is `Gudhi::Simplex_tree_options_full_featured`. If you want to provide your own, it is recommended that you derive from it and override some parts instead of writing a class from scratch. + */ +struct SimplexTreeOptions { + /// Forced for now. + typedef IndexingTag Indexing_tag; + /// Must be a signed integer type. It admits a total order <. + typedef VertexHandle Vertex_handle; + /// Must be comparable with operator<. + typedef FiltrationValue Filtration_value; + /// Must be a signed integer type. + typedef SimplexKey Simplex_key; + /// If true, each simplex has extra storage for one `Simplex_key`. Necessary for `Persistent_cohomology`. + static constexpr bool store_key; + /// If true, each simplex has extra storage for one `Filtration_value`, and this value is propagated by operations like `Gudhi::Simplex_tree::expansion`. Without it, `Persistent_cohomology` degenerates to computing usual (non-persistent) cohomology. + static constexpr bool store_filtration; +}; + diff --git a/src/Simplex_tree/concept/VertexHandle.h b/src/Simplex_tree/concept/VertexHandle.h index 491f0f56..3efbba61 100644 --- a/src/Simplex_tree/concept/VertexHandle.h +++ b/src/Simplex_tree/concept/VertexHandle.h @@ -22,5 +22,6 @@ /** \brief Handle type for the vertices of a cell complex. * - * Must be int.*/ + * Must be a signed integer type. operator< defines a total order on it. + */ struct VertexHandle {}; diff --git a/src/Simplex_tree/example/CMakeLists.txt b/src/Simplex_tree/example/CMakeLists.txt index 1a3cdfbf..2f924490 100644 --- a/src/Simplex_tree/example/CMakeLists.txt +++ b/src/Simplex_tree/example/CMakeLists.txt @@ -7,15 +7,18 @@ add_test(simplex_tree_from_file_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_ add_executable ( simple_simplex_tree simple_simplex_tree.cpp ) add_test(simple_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/simple_simplex_tree) - + +add_executable ( mini_simplex_tree mini_simplex_tree.cpp ) +add_test(mini_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/mini_simplex_tree) + # An example with Simplex-tree using CGAL alpha_shapes_3 if(GMP_FOUND AND CGAL_FOUND) message("CGAL_lib = ${CGAL_LIBRARIES_DIR}") - message("GMP_LIBRARIES = ${GMP_LIBRARIES}") + message("GMP_LIBRARIES = ${GMP_LIBRARIES}") INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) add_executable ( simplex_tree_from_alpha_shapes_3 simplex_tree_from_alpha_shapes_3.cpp ) target_link_libraries(simplex_tree_from_alpha_shapes_3 ${GMP_LIBRARIES} ${CGAL_LIBRARY}) add_test(simplex_tree_from_alpha_shapes_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_alpha_shapes_3 ${CMAKE_SOURCE_DIR}/data/points/bunny_5000) -endif() +endif() diff --git a/src/Simplex_tree/example/mini_simplex_tree.cpp b/src/Simplex_tree/example/mini_simplex_tree.cpp new file mode 100644 index 00000000..08d626d3 --- /dev/null +++ b/src/Simplex_tree/example/mini_simplex_tree.cpp @@ -0,0 +1,68 @@ +/* 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): Marc Glisse + * + * Copyright (C) 2015 INRIA Saclay - Ile-de-France (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 +#include +#include + +using namespace Gudhi; + +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 ST; + +// Dictionary should be private, but for now this is the easiest way. +static_assert(sizeof(ST::Dictionary::value_type) < sizeof(Simplex_tree<>::Dictionary::value_type), + "Not storing the filtration and key should save some space"); + +int main() { + ST st; + + /* Complex to build. */ + /* 1 */ + /* o */ + /* /X\ */ + /* o---o---o */ + /* 2 0 3 */ + + auto triangle012 = {0, 1, 2}; + auto edge03 = {0, 3}; + st.insert_simplex_and_subfaces(triangle012); + st.insert_simplex_and_subfaces(edge03); + // FIXME: Remove this line + st.set_dimension(2); + + auto edge02 = {0, 2}; + ST::Simplex_handle e = st.find(edge02); + assert(st.filtration(e) == 0); // We are not using filtrations so everything has value 0 + for(ST::Simplex_handle t : st.cofaces_simplex_range(e, 1)) // Only coface is 012 + { + for(ST::Vertex_handle v : st.simplex_vertex_range(t)) // v in { 0, 1, 2 } + std::cout << v; + std::cout << '\n'; + } +} diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 279327f7..6a47083c 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -28,6 +28,9 @@ #include #include +#include +#include + #include #include #include @@ -72,6 +75,17 @@ namespace Gudhi { * \copyright GNU General Public License v3. * @{ */ + +/// Model of SimplexTreeOptions. +struct Simplex_tree_options_full_featured { + typedef linear_indexing_tag Indexing_tag; + typedef int Vertex_handle; + typedef double Filtration_value; + typedef int Simplex_key; + static const bool store_key = true; + static const bool store_filtration = true; +}; + /** * \brief Simplex Tree data structure for representing simplicial complexes. * @@ -83,35 +97,63 @@ namespace Gudhi { * \implements FilteredComplex * */ -template + +template class Simplex_tree { public: - typedef IndexingTag Indexing_tag; + typedef SimplexTreeOptions Options; + typedef typename Options::Indexing_tag Indexing_tag; /** \brief Type for the value of the filtration function. * * Must be comparable with <. */ - typedef FiltrationValue Filtration_value; + typedef typename Options::Filtration_value Filtration_value; /** \brief Key associated to each simplex. * * Must be a signed integer type. */ - typedef SimplexKey Simplex_key; + typedef typename Options::Simplex_key Simplex_key; /** \brief Type for the vertex handle. * * Must be a signed integer type. It admits a total order <. */ - typedef VertexHandle Vertex_handle; + typedef typename Options::Vertex_handle Vertex_handle; /* Type of node in the simplex tree. */ typedef Simplex_tree_node_explicit_storage Node; /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ + // Note: this wastes space when Vertex_handle is 32 bits and Node is aligned on 64 bits. It would be better to use a flat_set (with our own comparator) where we can control the layout of the struct (put Vertex_handle and Simplex_key next to each other). typedef typename boost::container::flat_map Dictionary; /* \brief Set of nodes sharing a same parent in the simplex tree. */ /* \brief Set of nodes sharing a same parent in the simplex tree. */ typedef Simplex_tree_siblings Siblings; + struct Key_simplex_base_real { + Key_simplex_base_real() : key_(-1) {} + void assign_key(Simplex_key k) { key_ = k; } + Simplex_key key() const { return key_; } + private: + Simplex_key key_; + }; + struct Key_simplex_base_dummy { + Key_simplex_base_dummy() {} + void assign_key(Simplex_key) { } + Simplex_key key() const { assert(false); return -1; } + }; + typedef typename std::conditional::type Key_simplex_base; + + struct Filtration_simplex_base_real { + Filtration_simplex_base_real() : filt_(0) {} + void assign_filtration(Filtration_value f) { filt_ = f; } + Filtration_value filtration() const { return filt_; } + private: + Filtration_value filt_; + }; + struct Filtration_simplex_base_dummy { + Filtration_simplex_base_dummy() {} + void assign_filtration(Filtration_value f) { assert(f == 0); } + Filtration_value filtration() const { return 0; } + }; + typedef typename std::conditional::type Filtration_simplex_base; + public: /** \brief Handle type to a simplex contained in the simplicial complex represented * by the simplex tree. */ @@ -170,12 +212,12 @@ class Simplex_tree { /** \brief Range over the simplices of the skeleton of the simplicial complex, for a given * dimension. */ typedef boost::iterator_range Skeleton_simplex_range; + /** \brief Range over the simplices of the simplicial complex, ordered by the filtration. */ + typedef std::vector Filtration_simplex_range; /** \brief Iterator over the simplices of the simplicial complex, ordered by the filtration. * * 'value_type' is Simplex_handle. */ - typedef typename std::vector::iterator Filtration_simplex_iterator; - /** \brief Range over the simplices of the simplicial complex, ordered by the filtration. */ - typedef boost::iterator_range Filtration_simplex_range; + typedef typename Filtration_simplex_range::const_iterator Filtration_simplex_iterator; /* @} */ // end name range and iterator types /** \name Range and iterator methods @@ -226,17 +268,13 @@ class Simplex_tree { * order is used. * * The filtration must be valid. If the filtration has not been initialized yet, the - * method initializes it (i.e. order the simplices). */ - Filtration_simplex_range filtration_simplex_range(Indexing_tag) { + * 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. */ + Filtration_simplex_range const& filtration_simplex_range(Indexing_tag=Indexing_tag()) { if (filtration_vect_.empty()) { initialize_filtration(); } - return Filtration_simplex_range(filtration_vect_.begin(), - filtration_vect_.end()); - } - - Filtration_simplex_range filtration_simplex_range() { - return filtration_simplex_range(Indexing_tag()); + return filtration_vect_; } /** \brief Returns a range over the vertices of a simplex. @@ -278,9 +316,47 @@ class Simplex_tree { Simplex_tree() : null_vertex_(-1), threshold_(0), - root_(NULL, null_vertex_), + root_(nullptr, null_vertex_), + filtration_vect_(), + dimension_(-1) { } + + /** \brief User-defined copy constructor reproduces the whole tree structure. */ + Simplex_tree(const Simplex_tree& simplex_source) + : null_vertex_(simplex_source.null_vertex_), + threshold_(simplex_source.threshold_), filtration_vect_(), - dimension_(-1) { + dimension_(simplex_source.dimension_) { + auto root_source = simplex_source.root_; + auto memb_source = root_source.members(); + root_ = Siblings(nullptr, null_vertex_, memb_source); + rec_copy(&root_, &root_source); + } + + /** \brief depth first search, inserts simplices when reaching a leaf. */ + void rec_copy(Siblings *sib, Siblings *sib_source) { + for (auto sh = sib->members().begin(), sh_source = sib_source->members().begin(); + sh != sib->members().end(); ++sh, ++sh_source) { + if (has_children(sh_source)) { + Siblings * newsib = new Siblings(sib, sh_source->first); + newsib->members_.reserve(sh_source->second.children()->members().size()); + for (auto & child : sh_source->second.children()->members()) + newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(sib, child.second.filtration())); + rec_copy(newsib, sh_source->second.children()); + sh->second.assign_children(newsib); + } + } + } + + /** \brief User-defined move constructor moves the whole tree structure. */ + Simplex_tree(Simplex_tree && old) + : null_vertex_(std::move(old.null_vertex_)), + threshold_(std::move(old.threshold_)), + root_(std::move(old.root_)), + filtration_vect_(std::move(old.filtration_vect_)), + dimension_(std::move(old.dimension_)) { + old.dimension_ = -1; + old.threshold_ = 0; + old.root_ = Siblings(nullptr, null_vertex_); } /** \brief Destructor; deallocates the whole tree structure. */ @@ -303,24 +379,64 @@ class Simplex_tree { delete sib; } + public: + /** \brief Checks if two simplex trees are equal. */ + bool operator==(Simplex_tree& st2) { + if ((null_vertex_ != st2.null_vertex_) || + (threshold_ != st2.threshold_) || + (dimension_ != st2.dimension_)) + return false; + return rec_equal(&root_, &st2.root_); + } + + /** \brief Checks if two simplex trees are different. */ + bool operator!=(Simplex_tree& st2) { + return (!(*this == st2)); + } + + private: + /** rec_equal: Checks recursively whether or not two simplex trees are equal, using depth first search. */ + bool rec_equal(Siblings* s1, Siblings* s2) { + if (s1->members().size() != s2->members().size()) + return false; + for (auto sh1 = s1->members().begin(), sh2 = s2->members().begin(); + (sh1 != s1->members().end() && sh2 != s2->members().end()); ++sh1, ++sh2) { + if (sh1->first != sh2->first || sh1->second.filtration() != sh2->second.filtration()) + return false; + if (has_children(sh1) != has_children(sh2)) + return false; + // Recursivity on children only if both have children + else if (has_children(sh1)) + if (!rec_equal(sh1->second.children(), sh2->second.children())) + return false; + } + return true; + } + public: /** \brief Returns the key associated to a simplex. * - * The filtration must be initialized. */ + * The filtration must be initialized. + * \pre SimplexTreeOptions::store_key + */ static Simplex_key key(Simplex_handle sh) { return sh->second.key(); } /** \brief Returns the simplex associated to a key. * - * The filtration must be initialized. */ + * The filtration must be initialized. + * \pre SimplexTreeOptions::store_key + */ Simplex_handle simplex(Simplex_key key) const { return filtration_vect_[key]; } /** \brief Returns the filtration value of a simplex. * - * Called on the null_simplex, returns INFINITY. */ + * Called on the null_simplex, returns INFINITY. + * If SimplexTreeOptions::store_filtration is false, returns 0. + */ static Filtration_value filtration(Simplex_handle sh) { if (sh != null_simplex()) { return sh->second.filtration(); @@ -348,7 +464,7 @@ class Simplex_tree { * * One can call filtration(null_simplex()). */ static Simplex_handle null_simplex() { - return Dictionary_it(NULL); + return Dictionary_it(nullptr); } /** \brief Returns a key different for all keys associated to the @@ -395,7 +511,7 @@ class Simplex_tree { int dimension(Simplex_handle sh) { Siblings * curr_sib = self_siblings(sh); int dim = 0; - while (curr_sib != NULL) { + while (curr_sib != nullptr) { ++dim; curr_sib = curr_sib->oncles(); } @@ -413,26 +529,34 @@ class Simplex_tree { return (sh->second.children()->parent() == sh->first); } - public: - /** \brief Given a range of Vertex_handles, returns the Simplex_handle + /** \brief Given a range of Vertex_handles, returns the Simplex_handle * of the simplex in the simplicial complex containing the corresponding * vertices. Return null_simplex() if the simplex is not in the complex. * - * The type RandomAccessVertexRange must be a range for which .begin() and - * .end() return random access iterators, with value_type - * Vertex_handle. + * The type InputVertexRange must be a range of Vertex_handle + * on which we can call std::begin() function */ - template - Simplex_handle find(RandomAccessVertexRange & s) { - if (s.begin() == s.end()) // Empty simplex - return null_simplex(); - - sort(s.begin(), s.end()); + template + Simplex_handle find(const InputVertexRange & s) { + auto first = std::begin(s); + auto last = std::end(s); + + if (first == last) + return null_simplex(); // ----->> + + // Copy before sorting + std::vector copy(first, last); + std::sort(std::begin(copy), std::end(copy)); + return find_simplex(copy); + } + private: + /** Find function, with a sorted range of vertices. */ + Simplex_handle find_simplex(const std::vector & simplex) { Siblings * tmp_sib = &root_; Dictionary_it tmp_dit; - Vertex_handle last = s[s.size() - 1]; - for (auto v : s) { + Vertex_handle last = simplex.back(); + for (auto v : simplex) { tmp_dit = tmp_sib->members_.find(v); if (tmp_dit == tmp_sib->members_.end()) { return null_simplex(); @@ -450,43 +574,17 @@ class Simplex_tree { Simplex_handle find_vertex(Vertex_handle v) { return root_.members_.begin() + v; } - - /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. - * - * @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 - * 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 filed of the - * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to - * null_simplex. - * - * All subsimplices do not necessary need to be already in the simplex tree to proceed to an - * insertion. However, the property of being a simplicial complex will be violated. This allows - * us to insert a stream of simplices contained in a simplicial complex without considering any - * order on them. - * - * The filtration value - * assigned to the new simplex must preserve the monotonicity of the filtration. - * - * The type RandomAccessVertexRange must be a range for which .begin() and - * .end() return random access iterators, with 'value_type' Vertex_handle. */ - template - std::pair insert_simplex(RandomAccessVertexRange & simplex, - Filtration_value filtration) { - if (simplex.empty()) { - return std::pair(null_simplex(), true); - } - // must be sorted in increasing order - sort(simplex.begin(), simplex.end()); + //{ return root_.members_.find(v); } + private: + /** \brief Inserts a simplex represented by a vector of vertex. + \warning the vector must be sorted by increasing vertex handle order */ + std::pair insert_vertex_vector(const std::vector& simplex, + Filtration_value filtration) { Siblings * curr_sib = &root_; std::pair res_insert; - typename RandomAccessVertexRange::iterator vi; - for (vi = simplex.begin(); vi != simplex.end() - 1; ++vi) { + auto vi = simplex.begin(); + for (; vi != simplex.end() - 1; ++vi) { res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration)); if (!(has_children(res_insert.first))) { res_insert.first->second.assign_children(new Siblings(curr_sib, *vi)); @@ -508,24 +606,77 @@ class Simplex_tree { return res_insert; } - /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of + public: + /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. + * + * @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 + * 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. + * + * All subsimplices do not necessary need to be already in the simplex tree to proceed to an + * insertion. However, the property of being a simplicial complex will be violated. This allows + * us to insert a stream of simplices contained in a simplicial complex without considering any + * order on them. + * + * The filtration value + * assigned to the new simplex must preserve the monotonicity of the filtration. + * + * The type InputVertexRange must be a range for which .begin() and + * .end() return input iterators, with 'value_type' Vertex_handle. */ + template + std::pair insert_simplex(const InputVertexRange & simplex, + Filtration_value filtration = 0) { + auto first = std::begin(simplex); + auto last = std::end(simplex); + + if (first == last) + return std::pair(null_simplex(), true); // ----->> + + // Copy before sorting + std::vector copy(first, last); + std::sort(std::begin(copy), std::end(copy)); + return insert_vertex_vector(copy, filtration); + } + + /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of * Vertex_handles, in the simplicial complex. * * @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 + * 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. */ - template - std::pair insert_simplex_and_subfaces(const RandomAccessVertexRange& Nsimplex, - Filtration_value filtration = 0.0) { - // Simplex copy - std::vector the_simplex(Nsimplex.begin(), Nsimplex.end()); - // must be sorted in increasing order - std::sort(the_simplex.begin(), the_simplex.end()); + template + std::pair insert_simplex_and_subfaces(const InputVertexRange& Nsimplex, + Filtration_value filtration = 0) { + auto first = std::begin(Nsimplex); + auto last = std::end(Nsimplex); + + if (first == last) + return std::pair(null_simplex(), true); // ----->> + + // Copy before sorting + std::vector copy(first, last); + std::sort(std::begin(copy), std::end(copy)); + 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); + return rec_insert_simplex_and_subfaces(copy, to_be_inserted, to_be_propagated, filtration); } - + private: std::pair rec_insert_simplex_and_subfaces(std::vector& the_simplex, std::vector>& to_be_inserted, @@ -534,15 +685,15 @@ class Simplex_tree { std::pair insert_result; if (the_simplex.size() > 1) { // Get and remove last vertex - Vertex_handle last_vertex= the_simplex.back(); + 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.begin(), 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); @@ -557,26 +708,23 @@ class Simplex_tree { // insert all to_be_inserted for (auto& simplex_tbi : to_be_inserted) { - insert_result = insert_simplex(simplex_tbi, filtration); + insert_result = insert_vertex_vector(simplex_tbi, filtration); } - - } 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)){ + 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()); // i.e. (0,1,2) => [to_be_inserted | to_be_propagated] = [(0) | ] to_be_inserted.push_back(first_simplex); - - insert_result = insert_simplex(first_simplex, filtration); + + insert_result = insert_vertex_vector(first_simplex, filtration); } else { std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error" << std::endl; exit(-1); } - return insert_result; } @@ -603,17 +751,6 @@ class Simplex_tree { return sh->second.children(); } - // void display_simplex(Simplex_handle sh) - // { - // std::cout << " " << "[" << filtration(sh) << "] "; - // for( auto vertex : simplex_vertex_range(sh) ) - // { std::cout << vertex << " "; } - // } - - // void print(Simplex_handle sh, std::ostream& os = std::cout) - // { for(auto v : simplex_vertex_range(sh)) {os << v << " ";} - // os << std::endl; } - public: /** Returns a pointer to the root nodes of the simplex tree. */ Siblings * root() { @@ -778,8 +915,9 @@ class Simplex_tree { : st_(st) { } bool operator()(const Simplex_handle sh1, const Simplex_handle sh2) const { - if (st_->filtration(sh1) != st_->filtration(sh2)) { - return st_->filtration(sh1) < st_->filtration(sh2); + // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. + if (sh1->second.filtration() != sh2->second.filtration()) { + return sh1->second.filtration() < sh2->second.filtration(); } // is sh1 a proper subface of sh2 return st_->reverse_lexicographic_order(sh1, sh2); @@ -925,7 +1063,7 @@ class Simplex_tree { while (true) { if (begin1->first == begin2->first) { Filtration_value filt = (std::max)({begin1->second.filtration(), begin2->second.filtration(), filtration_}); - intersection.emplace_back(begin1->first, Node(NULL, filt)); + intersection.emplace_back(begin1->first, Node(nullptr, filt)); if (++begin1 == end1 || ++begin2 == end2) return; // ----->> } else if (begin1->first < begin2->first) { @@ -947,7 +1085,7 @@ class Simplex_tree { * of the simplex, and fil is its filtration value. */ void print_hasse(std::ostream& os) { os << num_simplices() << " " << std::endl; - for (auto sh : filtration_simplex_range(Indexing_tag())) { + for (auto sh : filtration_simplex_range()) { os << dimension(sh) << " "; for (auto b_sh : boundary_simplex_range(sh)) { os << key(b_sh) << " "; diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h index 1f1a34cc..c49e30b9 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h @@ -39,62 +39,31 @@ namespace Gudhi { * It stores explicitely its own filtration value and its own Simplex_key. */ template -class Simplex_tree_node_explicit_storage { - public: +struct Simplex_tree_node_explicit_storage : SimplexTree::Filtration_simplex_base, SimplexTree::Key_simplex_base { typedef typename SimplexTree::Siblings Siblings; typedef typename SimplexTree::Filtration_value Filtration_value; typedef typename SimplexTree::Simplex_key Simplex_key; - // Default constructor. - Simplex_tree_node_explicit_storage() - : children_(NULL), - simplex_key_(-1), - filtration_(0) { - } - - Simplex_tree_node_explicit_storage(Siblings * sib, - Filtration_value filtration) - : children_(sib), - simplex_key_(-1), - filtration_(filtration) { - } - - void assign_key(Simplex_key key) { - simplex_key_ = key; + Simplex_tree_node_explicit_storage(Siblings * sib = nullptr, + Filtration_value filtration = 0) + : children_(sib) { + this->assign_filtration(filtration); } /* - * Assign a children to the node + * Assign children to the node */ void assign_children(Siblings * children) { children_ = children; } - /* - * - */ - void assign_filtration(double filtration_value) { - filtration_ = filtration_value; - } - - Filtration_value filtration() { - return filtration_; - } /* Careful -> children_ can be NULL*/ Siblings * children() { return children_; } - Simplex_key key() { - return simplex_key_; - } - private: Siblings * children_; - - // Data attached to simplex, explicit storage - Simplex_key simplex_key_; - Filtration_value filtration_; // value in the filtration }; /* @} */ // end addtogroup simplex_tree 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 de350f2d..d20a91d7 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 @@ -71,15 +71,15 @@ class Simplex_tree_siblings { /* \brief Constructor with initialized set of members. * * 'members' must be sorted and unique.*/ - Simplex_tree_siblings(Simplex_tree_siblings * oncles, Vertex_handle parent, - const std::vector > & members) + template + Simplex_tree_siblings(Simplex_tree_siblings * oncles, Vertex_handle parent, const RandomAccessVertexRange & members) : oncles_(oncles), parent_(parent), members_(boost::container::ordered_unique_range, members.begin(), members.end()) { for (auto& map_el : members_) { map_el.second.assign_children(this); - } + } } /* diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 9340aaa3..a4871cfd 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -9,8 +9,8 @@ #define BOOST_TEST_MODULE "simplex_tree" #include -#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/reader_utils.h" +// ^ +// /!\ Nothing else from Simplex_tree shall be included to test includes are well defined. #include "gudhi/Simplex_tree.h" using namespace Gudhi; @@ -59,7 +59,6 @@ void test_iterators_on_empty_simplex_tree(typeST& tst) { BOOST_AUTO_TEST_CASE(simplex_tree_when_empty) { const Filtration_value DEFAULT_FILTRATION_VALUE = 0; - // TEST OF DEFAULT CONSTRUCTOR std::cout << "********************************************************************" << std::endl; std::cout << "TEST OF DEFAULT CONSTRUCTOR" << std::endl; typeST st; @@ -126,6 +125,7 @@ void test_simplex_tree_contains(typeST& simplexTree, typeSimplex& simplex, int p BOOST_CHECK(AreAlmostTheSame(simplexTree.filtration(*f_simplex), simplex.second)); int simplexIndex = simplex.first.size() - 1; + std::sort(simplex.first.begin(), simplex.first.end()); // if the simplex wasn't sorted, the next test could fail for (auto vertex : simplexTree.simplex_vertex_range(*f_simplex)) { std::cout << "test_simplex_tree_contains - vertex=" << vertex << "||" << simplex.first.at(simplexIndex) << std::endl; BOOST_CHECK(vertex == simplex.first.at(simplexIndex)); @@ -170,22 +170,6 @@ void set_and_test_simplex_tree_dim_fil(typeST& simplexTree, int vectorSize, cons BOOST_CHECK(simplexTree.num_simplices() == num_simp); } -void test_cofaces(typeST& st, std::vector v, int dim, std::vector res) { - typeST::Cofaces_simplex_range cofaces; - if (dim == 0) - cofaces = st.star_simplex_range(st.find(v)); - else - cofaces = st.cofaces_simplex_range(st.find(v), dim); - for (auto simplex = cofaces.begin(); simplex != cofaces.end(); ++simplex) { - typeST::Simplex_vertex_range rg = st.simplex_vertex_range(*simplex); - for (auto vertex = rg.begin(); vertex != rg.end(); ++vertex) { - std::cout << "(" << *vertex << ")"; - } - std::cout << std::endl; - BOOST_CHECK(std::find(res.begin(), res.end(), *simplex) != res.end()); - } -} - BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { const Filtration_value FIRST_FILTRATION_VALUE = 0.1; const Filtration_value SECOND_FILTRATION_VALUE = 0.2; @@ -378,9 +362,8 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { bool sort_in_decr_order (Vertex_handle i,Vertex_handle j) { return (i>j); } BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { - // TEST OF INSERTION WITH SUBFACES std::cout << "********************************************************************" << std::endl; - std::cout << "TEST OF INSERTION WITH SUBFACES" << std::endl; + std::cout << "TEST OF RECURSIVE INSERTION" << std::endl; typeST st; typePairSimplexBool returnValue; int position = 0; @@ -569,114 +552,179 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { } std::cout << std::endl; } +} +void test_cofaces(typeST& st, std::vector expected, int dim, std::vector res) { + typeST::Cofaces_simplex_range cofaces; + if (dim == 0) + cofaces = st.star_simplex_range(st.find(expected)); + else + cofaces = st.cofaces_simplex_range(st.find(expected), dim); + for (auto simplex = cofaces.begin(); simplex != cofaces.end(); ++simplex) { + typeST::Simplex_vertex_range rg = st.simplex_vertex_range(*simplex); + for (auto vertex = rg.begin(); vertex != rg.end(); ++vertex) { + std::cout << "(" << *vertex << ")"; + } + std::cout << std::endl; + BOOST_CHECK(std::find(res.begin(), res.end(), *simplex) != res.end()); + } +} + +BOOST_AUTO_TEST_CASE(coface_on_simplex_tree) { std::cout << "********************************************************************" << std::endl; - // TEST COFACE ALGORITHM + std::cout << "TEST COFACE ALGORITHM" << std::endl; + typeST st; + + typeVectorVertex SimplexVector{2, 1, 0}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {3, 0}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {3, 4, 5}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {0, 1, 6, 7}; + st.insert_simplex_and_subfaces(SimplexVector); + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + // FIXME st.set_dimension(3); - std::cout << "COFACE ALGORITHM" << std::endl; - std::vector v; - std::vector simplex; + + std::vector simplex_result; std::vector result; - v.push_back(3); - std::cout << "First test : " << std::endl; - std::cout << "Star of (3):" << std::endl; - - simplex.push_back(3); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(3); - simplex.push_back(0); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(4); - simplex.push_back(3); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(5); - simplex.push_back(4); - simplex.push_back(3); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(5); - simplex.push_back(3); - result.push_back(st.find(simplex)); - simplex.clear(); - - test_cofaces(st, v, 0, result); - v.clear(); + std::cout << "First test - Star of (3):" << std::endl; + + simplex_result = {3}; + result.push_back(st.find(simplex_result)); + + simplex_result = {3, 0}; + result.push_back(st.find(simplex_result)); + + simplex_result = {4, 3}; + result.push_back(st.find(simplex_result)); + + simplex_result = {5, 4, 3}; + result.push_back(st.find(simplex_result)); + + simplex_result = {5, 3}; + result.push_back(st.find(simplex_result)); + simplex_result.clear(); + + std::vector vertex = {3}; + test_cofaces(st, vertex, 0, result); + vertex.clear(); result.clear(); - v.push_back(1); - v.push_back(7); - std::cout << "Second test : " << std::endl; - std::cout << "Star of (1,7): " << std::endl; - - simplex.push_back(7); - simplex.push_back(1); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(7); - simplex.push_back(6); - simplex.push_back(1); - simplex.push_back(0); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(7); - simplex.push_back(1); - simplex.push_back(0); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(7); - simplex.push_back(6); - simplex.push_back(1); - result.push_back(st.find(simplex)); - simplex.clear(); - - test_cofaces(st, v, 0, result); + vertex.push_back(1); + vertex.push_back(7); + std::cout << "Second test - Star of (1,7): " << std::endl; + + simplex_result = {7, 1}; + result.push_back(st.find(simplex_result)); + + simplex_result = {7, 6, 1, 0}; + result.push_back(st.find(simplex_result)); + + simplex_result = {7, 1, 0}; + result.push_back(st.find(simplex_result)); + + simplex_result = {7, 6, 1}; + result.push_back(st.find(simplex_result)); + + test_cofaces(st, vertex, 0, result); result.clear(); - std::cout << "Third test : " << std::endl; - std::cout << "2-dimension Cofaces of simplex(1,7) : " << std::endl; + std::cout << "Third test - 2-dimension Cofaces of simplex(1,7) : " << std::endl; - simplex.push_back(7); - simplex.push_back(1); - simplex.push_back(0); - result.push_back(st.find(simplex)); - simplex.clear(); + simplex_result = {7, 1, 0}; + result.push_back(st.find(simplex_result)); - simplex.push_back(7); - simplex.push_back(6); - simplex.push_back(1); - result.push_back(st.find(simplex)); - simplex.clear(); + simplex_result = {7, 6, 1}; + result.push_back(st.find(simplex_result)); - test_cofaces(st, v, 1, result); + test_cofaces(st, vertex, 1, result); result.clear(); std::cout << "Cofaces with a codimension too high (codimension + vetices > tree.dimension) :" << std::endl; - test_cofaces(st, v, 5, result); - // std::cout << "Cofaces with an empty codimension" << std::endl; - // test_cofaces(st, v, -1, result); + test_cofaces(st, vertex, 5, result); + + //std::cout << "Cofaces with an empty codimension" << std::endl; + //test_cofaces(st, vertex, -1, result); // std::cout << "Cofaces in an empty simplex tree" << std::endl; // typeST empty_tree; - // test_cofaces(empty_tree, v, 1, result); - // std::cout << "Cofaces of an empty simplex" << std::endl; - // v.clear(); - // test_cofaces(st, v, 1, result); - - /* - // TEST Off read - std::cout << "********************************************************************" << std::endl; - typeST st2; - st2.tree_from_off("test.off"); - std::cout << st2; - */ + // test_cofaces(empty_tree, vertex, 1, result); + //std::cout << "Cofaces of an empty simplex" << std::endl; + //vertex.clear(); + // test_cofaces(st, vertex, 1, result); + +} + +BOOST_AUTO_TEST_CASE(copy_move_on_simplex_tree) { + std::cout << "********************************************************************" << std::endl; + std::cout << "TEST COPY MOVE CONSTRUCTORS" << std::endl; + typeST st; + + typeVectorVertex SimplexVector{2, 1, 0}; + st.insert_simplex_and_subfaces(SimplexVector); + SimplexVector = {3, 0}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {3, 4, 5}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {0, 1, 6, 7}; + st.insert_simplex_and_subfaces(SimplexVector); + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + // FIXME + st.set_dimension(3); + + std::cout << "Printing st - address = " << &st << std::endl; + + // Copy constructor + typeST st_copy = st; + std::cout << "Printing a copy of st - address = " << &st_copy << std::endl; + + // Check the data are the same + BOOST_CHECK(st == st_copy); + // Check there is a new simplex tree reference + BOOST_CHECK(&st != &st_copy); + + // Move constructor + typeST st_move = std::move(st); + std::cout << "Printing a move of st - address = " << &st_move << std::endl; + + // Check the data are the same + BOOST_CHECK(st_move == st_copy); + // 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); + + std::cout << "Printing st once again- address = " << &st << std::endl; } diff --git a/src/common/include/gudhi/Simple_object_pool.h b/src/common/include/gudhi/Simple_object_pool.h new file mode 100644 index 00000000..fffcb2ef --- /dev/null +++ b/src/common/include/gudhi/Simple_object_pool.h @@ -0,0 +1,64 @@ +/* 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): Marc Glisse + * + * Copyright (C) 2015 INRIA Saclay - Ile de 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 +#include + +namespace Gudhi { + /** \private + * This is a simpler version of boost::object_pool, that requires + * that users explicitly destroy all objects. This lets the + * performance scale much better, see + * https://svn.boost.org/trac/boost/ticket/3789 . + */ +template +class Simple_object_pool : protected boost::pool +{ + protected: + typedef boost::pool Base; + typedef T* pointer; + Base& base(){return *this;} + Base const& base()const{return *this;} + public: + typedef T element_type; + typedef boost::default_user_allocator_malloc_free user_allocator; + typedef typename Base::size_type size_type; + typedef typename Base::difference_type difference_type; + template + Simple_object_pool(U&&...u) : Base(sizeof(T), std::forward(u)...) {} + template + pointer construct(U&&...u){ + void* p=base().malloc BOOST_PREVENT_MACRO_SUBSTITUTION(); + assert(p); + try { new(p) T(std::forward(u)...); } + catch(...) { + base().free BOOST_PREVENT_MACRO_SUBSTITUTION(p); + throw; + } + return static_cast(p); + } + void destroy(pointer p){ + p->~T(); + base().free BOOST_PREVENT_MACRO_SUBSTITUTION(p); + } +}; +} -- cgit v1.2.3 From 03b68a5206201bf5bbffb7e4f6a6718907f23b2a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 9 Nov 2015 09:18:55 +0000 Subject: Modification for Porquerolles Workshop Bar_code_persistence and alpha_complex_persistence git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@893 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 63d2d21d5ff7c9a94a67eafc326bf8a561bf8166 --- src/Alpha_complex/example/CMakeLists.txt | 14 ++++ src/GudhUI/CMakeLists.txt | 40 +++++++++++ src/GudhUI/alpha_complex_persistence.cpp | 78 ++++++++++++++++++++ src/GudhUI/model/Model.h | 2 +- src/GudhUI/utils/Bar_code_persistence.h | 84 ++++++++++++++++++++++ src/GudhUI/view/FirstCoordProjector.h | 5 +- src/Persistent_cohomology/example/CMakeLists.txt | 44 ++++++++++++ .../example/alpha_complex_persistence.cpp | 55 ++++++++++++++ .../example/alpha_shapes_persistence.cpp | 14 ++-- .../include/gudhi/Persistent_cohomology.h | 8 +++ src/Simplex_tree/include/gudhi/Simplex_tree.h | 2 +- .../include/gudhi/Delaunay_triangulation_off_io.h | 2 +- src/common/include/gudhi/Off_reader.h | 2 +- 13 files changed, 338 insertions(+), 12 deletions(-) create mode 100644 src/GudhUI/alpha_complex_persistence.cpp create mode 100644 src/GudhUI/utils/Bar_code_persistence.h create mode 100644 src/Persistent_cohomology/example/alpha_complex_persistence.cpp diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 04fc34af..10b87f04 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -8,6 +8,20 @@ if(CGAL_FOUND) message(STATUS "CGAL version: ${CGAL_VERSION}.") include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index 71f4fd1a..5c2afdd0 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -78,6 +78,46 @@ if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND ) target_link_libraries( GudhUI ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} ) target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) +############################################################################### + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround + + find_package(Eigen3 3.1.0) + 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}) + + 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 () +############################################################################### + else() message(STATUS "NOTICE: GudhUI requires CGAL, the QGLViewer, OpenGL and Qt4, and will not be compiled.") endif() diff --git a/src/GudhUI/alpha_complex_persistence.cpp b/src/GudhUI/alpha_complex_persistence.cpp new file mode 100644 index 00000000..4f85459a --- /dev/null +++ b/src/GudhUI/alpha_complex_persistence.cpp @@ -0,0 +1,78 @@ +#include +#include + + +#include + +// to construct a Delaunay_triangulation from a OFF file +#include +#include +#include + +#include "utils/Bar_code_persistence.h" + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " filename.off " << // alpha_square_max_value[double] " << + "coeff_field_characteristic[integer > 0] min_persistence[double >= -1.0]" << std::endl; + std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0 2 0.02" << 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]); + } + + QApplication qtapp(argc, argv); + + std::string off_file_name(argv[1]); + // double alpha_square_max_value = atof(argv[2]); + double alpha_square_max_value = 1e20; + int coeff_field_characteristic = atoi(argv[2]); // argv[3] + double min_persistence = atof(argv[3]); // argv[4] + + // ---------------------------------------------------------------------------- + // 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, 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::alphacomplex::Alpha_complex, + Gudhi::persistent_cohomology::Field_Zp > pcoh(alpha_complex_from_file); + + std::cout << "coeff_field_characteristic " << coeff_field_characteristic << + " - min_persistence " << min_persistence << std::endl; + + // initializes the coefficient field for homology + pcoh.init_coefficients(coeff_field_characteristic); + + pcoh.compute_persistent_cohomology(min_persistence); + + pcoh.output_diagram(); + + std::vector> persistence_vector; + pcoh.get_persistence(persistence_vector); + + Bar_code_persistence bc_persistence; + + for (auto persistence : persistence_vector) { + bc_persistence.insert(persistence.first, persistence.second); + } + + bc_persistence.show(); + + return qtapp.exec(); +} diff --git a/src/GudhUI/model/Model.h b/src/GudhUI/model/Model.h index d78cbad9..4f8d48ee 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 new file mode 100644 index 00000000..a1a46ea8 --- /dev/null +++ b/src/GudhUI/utils/Bar_code_persistence.h @@ -0,0 +1,84 @@ +#include // isfinite + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include // NaN, infinity +#include // for pair + +class Bar_code_persistence { + private: + typedef std::vector> Persistence; + Persistence persistence_vector; + double min_birth; + double max_death; + + public: + + Bar_code_persistence() + : min_birth(std::numeric_limits::quiet_NaN()), + max_death(std::numeric_limits::quiet_NaN()) { } + + void insert(double birth, double death) { + persistence_vector.push_back(std::make_pair(birth, death)); + if (std::isfinite(birth)) { + if ((birth < min_birth) || (std::isnan(min_birth))) + min_birth = birth; + if ((birth > max_death) || (std::isnan(max_death))) + max_death = birth; + } + if (std::isfinite(death)) + if ((death > max_death) || (std::isnan(max_death))) + max_death = death; + } + + void show() { + // Create a view, put a scene in it + QGraphicsView * view = new QGraphicsView(); + 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; + + 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; + if (std::isfinite(persistence.first)) + birth = ((persistence.first - min_birth) * ratio) + 50.0; + else + birth = 0.0; + + if (std::isfinite(persistence.second)) + death = ((persistence.second - min_birth) * ratio) + 50.0; + else + death = 700.0; + + scene->addLine(birth, height, death, height, QPen(Qt::blue, 2)); + pers_num++; + } + height += 10.0; + // scale line + scene->addLine(0, height, 700.0, height, QPen(Qt::black, 1)); + int modulo = 0; + for (double scale = 50.0; scale < 700.0; scale += 50.0) { + modulo++; + // scale small dash + scene->addLine(scale, height - 3.0, scale, height + 3.0, QPen(Qt::black, 1)); + // scale text + QString scale_value = QString::number(((scale - 50.0) / ratio) + min_birth); + QGraphicsTextItem* dimText = scene->addText(scale_value, QFont("Helvetica", 8)); + dimText->setPos(scale - (3.0 * scale_value.size()), height + 9.0 * (modulo % 2)); + } + // Show the view + view->show(); + } +}; diff --git a/src/GudhUI/view/FirstCoordProjector.h b/src/GudhUI/view/FirstCoordProjector.h index 529d2d42..3ceda3f5 100644 --- a/src/GudhUI/view/FirstCoordProjector.h +++ b/src/GudhUI/view/FirstCoordProjector.h @@ -32,8 +32,11 @@ class FirstCoordProjector3D : public Projector3D { typedef Projector3D::Point_3 Point_3; Point_3 operator()(const Point& p) const { - assert(p.dimension() >= 3); + if (p.dimension() >= 3) 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/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index ea69352e..74c2e778 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -39,6 +39,50 @@ if(GMPXX_FOUND AND GMP_FOUND) 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) #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) + + + + + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround + + find_package(Eigen3 3.1.0) + 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}) + + 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() endif() diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp new file mode 100644 index 00000000..fbadf673 --- /dev/null +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -0,0 +1,55 @@ +#include +#include + +// to construct a Delaunay_triangulation from a OFF file +#include +#include +#include + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value[double] " << + "coeff_field_characteristic[integer > 0] min_persistence[double >= -1.0]" << std::endl; + std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0 2 0.02" << std::endl; + exit(-1); // ----- >> +} + +int main(int argc, char **argv) { + if (argc != 5) { + 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]); + int coeff_field_characteristic = atoi(argv[3]); + double min_persistence = atof(argv[4]); + + // ---------------------------------------------------------------------------- + // 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, 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::alphacomplex::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); + + pcoh.output_diagram(); + + return 0; +} diff --git a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp b/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp index 6d5eebcf..235ea141 100644 --- a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp @@ -124,6 +124,12 @@ void usage(char * const progName) { } int main(int argc, char * const argv[]) { + // program args management + if (argc != 4) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; + usage(argv[0]); + } + int coeff_field_characteristic = 0; int returnedScanValue = sscanf(argv[2], "%d", &coeff_field_characteristic); if ((returnedScanValue == EOF) || (coeff_field_characteristic <= 0)) { @@ -138,12 +144,6 @@ int main(int argc, char * const argv[]) { usage(argv[0]); } - // program args management - if (argc != 4) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; - usage(argv[0]); - } - // Read points from file std::string filegraph = argv[1]; std::list lp; @@ -239,7 +239,7 @@ int main(int argc, char * const argv[]) { } } // Construction of the simplex_tree - Filtration_value filtr = std::sqrt(*the_alpha_value_iterator); + Filtration_value filtr = /*std::sqrt*/(*the_alpha_value_iterator); #ifdef DEBUG_TRACES std::cout << "filtration = " << filtr << std::endl; #endif // DEBUG_TRACES diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index d096792f..f6773bac 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -713,6 +713,14 @@ class Persistent_cohomology { } } + void get_persistence(std::vector>& persistence) { + cmp_intervals_by_length cmp(cpx_); + std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp); + for (auto pair : persistent_pairs_) { + persistence.push_back(std::make_pair(cpx_->filtration(get<0>(pair)), cpx_->filtration(get<1>(pair)))); + } + } + void write_output_diagram(std::string diagram_name) { std::ofstream diagram_out(diagram_name.c_str()); cmp_intervals_by_length cmp(cpx_); diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index c7a0b5d5..1ca43ff9 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1096,7 +1096,7 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } - + private: Vertex_handle null_vertex_; /** \brief Upper bound on the filtration values of the simplices.*/ diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 0c5474c9..47066a94 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -278,7 +278,7 @@ class Delaunay_triangulation_off_writer { 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 << points_to_vh[(*vit)->point()] - 1 << " "; } stream << std::endl; } diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index bba5a63a..e45a7600 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) return false; + //if (face.size() != (off_info_.dim + 1)) return false; visitor.maximal_face(face); } return true; -- 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(-) 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(-) 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 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(-) 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 39ffc7af64543f0b2ce17487771afbd010a97349 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 27 Nov 2015 14:16:44 +0000 Subject: Adding changes to the cubcial complex class according to Marc and Vincent's comments. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@930 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: cb9134a5c18fae3e2e63bbaf8329dd168d08d3b3 --- .../example/Bitmap_cubical_complex.cpp | 147 +- src/Bitmap_cubical_complex/example/CMakeLists.txt | 2 +- .../example/Random_bitmap_cubical_complex.cpp | 174 +-- .../include/gudhi/Bitmap_cubical_complex.h | 1443 ++++++++++---------- .../include/gudhi/Bitmap_cubical_complex_base.h | 1352 ++++++++++-------- src/Bitmap_cubical_complex/include/gudhi/counter.h | 316 +++-- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 1261 ++++++++--------- src/CMakeLists.txt | 8 +- 8 files changed, 2467 insertions(+), 2236 deletions(-) diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index 37c16618..31da3609 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -1,71 +1,76 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-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 . - */ - -// for persistence algorithm -#include -#include -#include - -#include - -// standard stuff -#include -#include - -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; -using namespace std; - -int main(int argc, char** argv) { - cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes " - "provided in text files in Perseus style (the only numbed in the first line is a dimension D of a cubical " - "complex. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N " - "denote product of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of " - "top dimensional cells. We assume that the cells are in the lexicographical order. See CubicalOneSphere.txt or " - "CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if (argc != 2) { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style cubical complex at the " - "input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex b(argv[1]); - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients(p); // initializes the coefficient field for homology - pcoh.compute_persistent_cohomology(min_persistence); - - - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*) ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 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): Pawel Dlotko + * + * 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 . + */ + + +//for persistence algorithm +#include +#include +#include + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include + +using namespace std; + +int main( int argc , char** argv ) +{ + cout << "This program computes persistent homology, by using bitmap_cubical_complex class,\ + of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are\ + numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are\ + filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a\ + Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex b( argv[1] ); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index 05ef1319..dd252a79 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.6) -project(GUDHISimplexTreeFromFile) +project(GUDHIBitmap) add_executable ( Bitmap_cubical_complex Bitmap_cubical_complex.cpp ) target_link_libraries(Bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index ac7557ce..60cfc113 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -1,81 +1,93 @@ -/* 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): Pawel Dlotko - * - * 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 . - */ - - -// for persistence algorithm -#include -#include -#include - -#include - -// standard stuff -#include -#include -#include -#include -#include - -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; -using namespace std; - -int main(int argc, char** argv) { - srand(time(0)); - - cout << "This program computes persistent homology, by using Bitmap_cubical_complex class, of cubical complexes. " - "The first parameter of the program is the dimension D of the cubical complex. The next D parameters are number " - "of top dimensional cubes in each dimension of the cubical complex. The program will create random cubical " - "complex of that sizes and compute persistent homology of it." << endl; - - int p = 2; - double min_persistence = 0; - - size_t dimensionOfBitmap = (size_t) atoi(argv[1]); - std::vector< unsigned > sizes; - size_t multipliers = 1; - for (size_t dim = 0; dim != dimensionOfBitmap; ++dim) { - unsigned sizeInThisDimension = (unsigned) atoi(argv[2 + dim]); - sizes.push_back(sizeInThisDimension); - multipliers *= sizeInThisDimension; - } - - std::vector< double > data; - for (size_t i = 0; i != multipliers; ++i) { - data.push_back(rand() / (double) RAND_MAX); - } - - Bitmap_cubical_complex b(sizes, data); - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients(p); // initializes the coefficient field for homology - pcoh.compute_persistent_cohomology(min_persistence); - - stringstream ss; - ss << "randomComplex_persistence"; - std::ofstream out((char*) ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 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): Pawel Dlotko + * + * 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 . + */ + + +//for persistence algorithm +#include +#include +#include + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + +int main( int argc , char** argv ) +{ + srand( time(0) ); + + cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes. \ +The first parameter of the program is the dimension D of the bitmap. \ +The next D parameters are number of top dimensional cubes in each dimension of the bitmap.\ +The program will create random cubical complex of that sizes and compute persistent homology of it." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc < 3 ) + { + cerr << "Wrong number of parameters, the program will now terminate\n"; + return 1; + } + + size_t dimensionOfBitmap = (size_t)atoi( argv[1] ); + std::vector< unsigned > sizes; + size_t multipliers = 1; + for ( size_t dim = 0 ; dim != dimensionOfBitmap ; ++dim ) + { + unsigned sizeInThisDimension = (unsigned)atoi( argv[2+dim] ); + sizes.push_back( sizeInThisDimension ); + multipliers *= sizeInThisDimension; + } + + std::vector< double > data; + for ( size_t i = 0 ; i != multipliers ; ++i ) + { + data.push_back( rand()/(double)RAND_MAX ); + } + + + + Bitmap_cubical_complex b( sizes , data ); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << "randomComplex_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 2f8cb0a3..f2c753d9 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -1,724 +1,719 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-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 BITMAP_CUBICAL_COMPLEX_H_ -#define BITMAP_CUBICAL_COMPLEX_H_ - -#include - -#include -#include // for pair -#include // for sort -#include // for vector - -// global variable, was used just for debugging. -bool globalDbg = false; - -template -class Bitmap_cubical_complex : public Bitmap_cubical_complex_base { - public: - //******************************************************************************************************************// - // Typedefs and typenames - //******************************************************************************************************************// - friend class Simplex_handle; - typedef size_t Simplex_key; - typedef T Filtration_value; - - - //******************************************************************************************************************// - // Simplex handle class - //******************************************************************************************************************// - - /** - * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. Elements of this - * class are: the pointer to the bitmap B in which the considered cell is together with a position of this cell in B. - * Given this data, one can get all the information about the considered cell. - **/ - class Simplex_handle { - public: - Simplex_handle() { - if (globalDbg) { - std::cerr << "Simplex_handle()\n"; - } - this->b = 0; - this->position = 0; - } - - Simplex_handle(Bitmap_cubical_complex* b) { - if (globalDbg) { - std::cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; - } - this->b = b; - this->position = 0; - } - - Simplex_handle(const Simplex_handle& org) : b(org.b) { - if (globalDbg) { - std::cerr << "Simplex_handle( const Simplex_handle& org )\n"; - } - this->position = org.position; - } - - Simplex_handle& operator=(const Simplex_handle& rhs) { - if (globalDbg) { - std::cerr << "Simplex_handle operator = \n"; - } - this->position = rhs.position; - this->b = rhs.b; - return *this; - } - - Simplex_handle(Bitmap_cubical_complex* b, Simplex_key position) { - if (globalDbg) { - std::cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; - std::cerr << "Position : " << position << std::endl; - } - this->b = b; - this->position = position; - } - friend class Bitmap_cubical_complex; - private: - Bitmap_cubical_complex* b; - Simplex_key position; - // Assumption -- this field always keep the REAL position of simplex in the bitmap, no matter what keys have been. - // to deal with the keys, the class Bitmap_cubical_complex have extra vectors: keyAssociatedToSimplex and - // simplexAssociatedToKey that allow to move between actual cell and the key assigned to it. - }; - - - //******************************************************************************************************************// - // Constructors - //******************************************************************************************************************// - // Over here we need to definie various input types. I am proposing the following ones: - // Perseus style - // TODO(Pawel Dlotko): H5 files? - // TODO(Pawel Dlotko): binary files with little endiangs / big endians? - // TODO(Pawel Dlotko): constructor from a vector of elements of a type T. - - /** - * Constructor form a Perseus-style file. - **/ - Bitmap_cubical_complex(char* perseusStyleFile) : Bitmap_cubical_complex_base(perseusStyleFile) { - if (globalDbg) { - std::cerr << "Bitmap_cubical_complex( char* perseusStyleFile )\n"; - } - std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); - std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); - - for (size_t i = 0; i != this->totalNumberOfCells; ++i) { - keyAssociatedToSimplex[i] = simplexAssociatedToKey[i] = i; - } - this->keyAssociatedToSimplex = keyAssociatedToSimplex; - this->simplexAssociatedToKey = simplexAssociatedToKey; - // we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change - // some elements of the bitmap, then this procedure need to be called again. - this->initializeElementsOrderedAccordingToFiltration(); - } - - /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells in the - * following directions and vector of element of a type T with filtration on top dimensional cells. - **/ - Bitmap_cubical_complex(std::vector dimensions, std::vector topDimensionalCells) - : Bitmap_cubical_complex_base(dimensions, topDimensionalCells) { - std::vector< size_t > keyAssociatedToSimplex(this->totalNumberOfCells + 1); - std::vector< size_t > simplexAssociatedToKey(this->totalNumberOfCells + 1); - - for (size_t i = 0; i != this->totalNumberOfCells; ++i) { - keyAssociatedToSimplex[i] = simplexAssociatedToKey[i] = i; - } - this->keyAssociatedToSimplex = keyAssociatedToSimplex; - this->simplexAssociatedToKey = simplexAssociatedToKey; - // we initialize this only once, in each constructor, when the bitmap is constructed. If the user decide to change - // some elements of the bitmap, then this procedure need to be called again. - this->initializeElementsOrderedAccordingToFiltration(); - } - - //******************************************************************************************************************// - // Other 'easy' functions - //******************************************************************************************************************// - - /** - * Returns number of all cubes in the complex. - **/ - size_t num_simplices()const { - return this->totalNumberOfCells; - } - - /** - * Returns a Simplex_handle to a cube that do not exist in this complex. - **/ - Simplex_handle null_simplex() { - return Simplex_handle(this, this->data.size()); - } - - /** - * Returns dimension of the complex. - **/ - size_t dimension() { - return this->sizes.size(); - } - - /** - * Return dimension of a cell pointed by the Simplex_handle. - **/ - size_t dimension(const Simplex_handle& sh) { - if (globalDbg) { - std::cerr << "int dimension(const Simplex_handle& sh)\n"; - } - if (sh.position != this->data.size()) return sh.b->get_dimension_of_a_cell(sh.position); - return std::numeric_limits::max(); - } - - /** - * Return the filtration of a cell pointed by the Simplex_handle. - **/ - T filtration(const Simplex_handle& sh) { - if (globalDbg) { - std::cerr << "T filtration(const Simplex_handle& sh)\n"; - } - // Returns the filtration value of a simplex. - if (sh.position != this->data.size()) return sh.b->data[ sh.position ]; - return INT_MAX; - } - - /** - * Return a key which is not a key of any cube in the considered data structure. - **/ - Simplex_key null_key() { - if (globalDbg) { - std::cerr << "Simplex_key null_key()\n"; - } - return this->data.size(); - } - - /** - * Return the key of a cube pointed by the Simplex_handle. - **/ - Simplex_key key(const Simplex_handle& sh) { - if (globalDbg) { - std::cerr << "Simplex_key key(const Simplex_handle& sh)\n"; - } - return sh.b->keyAssociatedToSimplex[ sh.position ]; - } - - /** - * Return the Simplex_handle given the key of the cube. - **/ - Simplex_handle simplex(Simplex_key key) { - if (globalDbg) { - std::cerr << "Simplex_handle simplex(Simplex_key key)\n"; - } - return Simplex_handle(this, this->simplexAssociatedToKey[ key ]); - } - - /** - * Assign key to a cube pointed by the Simplex_handle - **/ - void assign_key(Simplex_handle& sh, Simplex_key key) { - if (globalDbg) { - std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; - } - this->keyAssociatedToSimplex[sh.position] = key; - this->simplexAssociatedToKey[key] = sh.position; - } - - /** - * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. - **/ - void initializeElementsOrderedAccordingToFiltration(); - - - - //******************************************************************************************************************// - // Iterators - //******************************************************************************************************************// - - /** - * Boundary_simplex_iterator class allows iteration on boundary of each cube. - **/ - class Boundary_simplex_range; - - class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - // Iterator on the simplices belonging to the boundary of a simplex. - // value_type must be 'Simplex_handle'. - public: - Boundary_simplex_iterator(Simplex_handle& sh) : sh(sh) { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n"; - } - this->position = 0; - this->boundaryElements = this->sh.b->get_boundary_of_a_cell(this->sh.position); - } - - Boundary_simplex_iterator operator++() { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator operator++()\n"; - } - ++this->position; - return *this; - } - - Boundary_simplex_iterator operator++(int) { - Boundary_simplex_iterator result = *this; - ++(*this); - return result; - } - - Boundary_simplex_iterator operator=(const Boundary_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator operator =\n"; - } - this->sh = rhs.sh; - this->boundaryElements.clear(); - this->boundaryElementsinsert(this->boundaryElements.end(), - rhs.boundaryElements.begin(), rhs.boundaryElements.end()); - } - - bool operator==(const Boundary_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator ==\n"; - } - if (this->position == rhs.position) { - if (this->boundaryElements.size() != rhs.boundaryElements.size())return false; - for (size_t i = 0; i != this->boundaryElements.size(); ++i) { - if (this->boundaryElements[i] != rhs.boundaryElements[i])return false; - } - return true; - } - return false; - } - - bool operator!=(const Boundary_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator != \n"; - } - return !(*this == rhs); - } - - Simplex_handle operator*() { - if (globalDbg) { - std::cerr << "Simplex_handle operator*\n"; - } - return Simplex_handle(this->sh.b, this->boundaryElements[this->position]); - } - - friend class Boundary_simplex_range; - private: - Simplex_handle sh; - std::vector< size_t > boundaryElements; - size_t position; - }; - - /** - * Boundary_simplex_range class provides ranges for boundary iterators. - **/ - class Boundary_simplex_range { - // Range giving access to the simplices in the boundary of a simplex. - // .begin() and .end() return type Boundary_simplex_iterator. - public: - Boundary_simplex_range(const Simplex_handle& sh) : sh(sh) { } - - Boundary_simplex_iterator begin() { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator begin\n"; - } - Boundary_simplex_iterator it(this->sh); - return it; - } - - Boundary_simplex_iterator end() { - if (globalDbg) { - std::cerr << "Boundary_simplex_iterator end()\n"; - } - Boundary_simplex_iterator it(this->sh); - it.position = it.boundaryElements.size(); - return it; - } - - private: - Simplex_handle sh; - }; - - - /** - * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. Secondary criteria for filtration are: - * (1) Dimension of a cube (lower dimensional comes first). - * (2) Position in the data structure (the ones that are earlies in the data structure comes first). - **/ - class Filtration_simplex_range; - - class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - // Iterator over all simplices of the complex in the order of the indexing scheme. - // 'value_type' must be 'Simplex_handle'. - public: - Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { } - - Filtration_simplex_iterator() : b(NULL) { } - - Filtration_simplex_iterator operator++() { - if (globalDbg) { - std::cerr << "Filtration_simplex_iterator operator++\n"; - } - ++this->position; - return (*this); - } - - Filtration_simplex_iterator operator++(int) { - Filtration_simplex_iterator result = *this; - ++(*this); - return result; - } - - Filtration_simplex_iterator operator=(const Filtration_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "Filtration_simplex_iterator operator =\n"; - } - this->b = rhs.b; - this->position = rhs.position; - } - - bool operator==(const Filtration_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; - } - if (this->position == rhs.position) { - return true; - } - return false; - } - - bool operator!=(const Filtration_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; - } - return !(*this == rhs); - } - - Simplex_handle operator*() { - if (globalDbg) { - std::cerr << "Simplex_handle operator*()\n"; - } - return Simplex_handle(this->b, this->b->elementsOrderedAccordingToFiltration[ this->position ]); - } - - friend class Filtration_simplex_range; - private: - Bitmap_cubical_complex* b; - size_t position; - }; - - /** - * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. - **/ - class Filtration_simplex_range { - // Range over the simplices of the complex in the order of the filtration. - // .begin() and .end() return type Filtration_simplex_iterator. - public: - Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { } - - Filtration_simplex_iterator begin() { - if (globalDbg) { - std::cerr << "Filtration_simplex_iterator begin() \n"; - } - return Filtration_simplex_iterator(this->b); - } - - Filtration_simplex_iterator end() { - if (globalDbg) { - std::cerr << "Filtration_simplex_iterator end()\n"; - } - Filtration_simplex_iterator it(this->b); - it.position = this->b->elementsOrderedAccordingToFiltration.size(); - return it; - } - private: - Bitmap_cubical_complex* b; - }; - - - - //******************************************************************************************************************// - // Methods to access iterators from the container: - - /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) { - if (globalDbg) { - std::cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n"; - } - // Returns a range giving access to all simplices of the boundary of a simplex, i.e. the set of - // codimension 1 subsimplices of the Simplex. - return Boundary_simplex_range(sh); - } - - /** - * filtration_simplex_range creates an object of a Filtration_simplex_range class that provides ranges for the - * Filtration_simplex_iterator. - **/ - Filtration_simplex_range filtration_simplex_range() { - if (globalDbg) { - std::cerr << "Filtration_simplex_range filtration_simplex_range()\n"; - } - // Returns a range over the simplices of the complex in the order of the filtration - return Filtration_simplex_range(this); - } - //******************************************************************************************************************// - - - - //******************************************************************************************************************// - // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are - // there. - // TODO(Pawel Dlotko): The file IndexingTag.h in the Gudhi library contains an empty structure, so I understand that - // this is something that was planned (for simplicial maps?) but was never finished. The only idea I have here is - // to use the same empty structure from IndexingTag.h file, but only if the compiler needs it. If the compiler - // do not need it, then I would rather not add here elements which I do not understand. - // typedef Indexing_tag - - /** - * Function needed for compatibility with Gudhi. Not useful for other purposes. - **/ - std::pair endpoints(Simplex_handle sh) { - std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh.position); - if (globalDbg) { - std::cerr << "std::pair endpoints( Simplex_handle sh )\n"; - std::cerr << "bdry.size() : " << bdry.size() << std::endl; - } - // this method returns two first elements from the boundary of sh. - if (bdry.size() < 2) - throw("Error in endpoints in Bitmap_cubical_complex class. " - "The cell for which this method was called have less than two elements in the boundary."); - return std::make_pair(Simplex_handle(this, bdry[0]), Simplex_handle(this, bdry[1])); - } - - - /** - * Class needed for compatibility with Gudhi. Not useful for other purposes. - **/ - class Skeleton_simplex_range; - - class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { - // Iterator over all simplices of the complex in the order of the indexing scheme. - // 'value_type' must be 'Simplex_handle'. - public: - Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; - } - // find the position of the first simplex of a dimension d - this->position = 0; - while ((this->position != b->data.size()) && - (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { - ++this->position; - } - } - - Skeleton_simplex_iterator() : b(NULL), dimension(0) { } - - Skeleton_simplex_iterator operator++() { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator operator++()\n"; - } - // increment the position as long as you did not get to the next element of the dimension dimension. - ++this->position; - while ((this->position != this->b->data.size()) && - (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) { - ++this->position; - } - return (*this); - } - - Skeleton_simplex_iterator operator++(int) { - Skeleton_simplex_iterator result = *this; - ++(*this); - return result; - } - - Skeleton_simplex_iterator operator=(const Skeleton_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator operator =\n"; - } - this->b = rhs.b; - this->position = rhs.position; - } - - bool operator==(const Skeleton_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator ==\n"; - } - if (this->position == rhs.position) { - return true; - } - return false; - } - - bool operator!=(const Skeleton_simplex_iterator& rhs) { - if (globalDbg) { - std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; - } - return !(*this == rhs); - } - - Simplex_handle operator*() { - if (globalDbg) { - std::cerr << "Simplex_handle operator*() \n"; - } - return Simplex_handle(this->b, this->position); - } - - friend class Skeleton_simplex_range; - private: - Bitmap_cubical_complex* b; - size_t position; - int dimension; - }; - - /** - * Class needed for compatibility with Gudhi. Not useful for other purposes. - **/ - class Skeleton_simplex_range { - // Range over the simplices of the complex in the order of the filtration. - // .begin() and .end() return type Filtration_simplex_iterator. - public: - Skeleton_simplex_range(Bitmap_cubical_complex* b, int dimension) : b(b), dimension(dimension) { } - - Skeleton_simplex_iterator begin() { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator begin()\n"; - } - return Skeleton_simplex_iterator(this->b, this->dimension); - } - - Skeleton_simplex_iterator end() { - if (globalDbg) { - std::cerr << "Skeleton_simplex_iterator end()\n"; - } - Skeleton_simplex_iterator it(this->b, this->dimension); - it.position = this->b->data.size(); - return it; - } - - private: - Bitmap_cubical_complex* b; - int dimension; - }; - - /** - * Function needed for compatibility with Gudhi. Not useful for other purposes. - **/ - Skeleton_simplex_range skeleton_simplex_range(int dimension) { - if (globalDbg) { - std::cerr << "Skeleton_simplex_range skeleton_simplex_range( int dimension )\n"; - } - return Skeleton_simplex_range(this, dimension); - } - - - - //******************************************************************************************************************// - // functions used for debugging: - - /** - * Function used for debugging purposes. - **/ - void printKeyAssociatedToSimplex() { - for (size_t i = 0; i != this->data.size(); ++i) { - std::cerr << i << " -> " << this->simplexAssociatedToKey[i] << std::endl; - } - } - - /** - * Function used for debugging purposes. - **/ - size_t printRealPosition(const Simplex_handle& sh) { - return sh.position; - } - - private: - std::vector< size_t > keyAssociatedToSimplex; - std::vector< size_t > simplexAssociatedToKey; - // needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. - std::vector< size_t > elementsOrderedAccordingToFiltration; -}; - -template -bool compareElementsForElementsOrderedAccordingToFiltration(const std::pair< size_t, - std::pair< T, char > >& f, - const std::pair< size_t, - std::pair< T, char > >& s) { - if (globalDbg) { - std::cerr << "ompareElementsForElementsOrderedAccordingToFiltration\n"; - } - if (f.second.first < s.second.first) { - return true; - } else { - if (f.second.first > s.second.first) { - return false; - } else { - // in this case f.second.first == s.second.first, and we use dimension to compare: - if (f.second.second < s.second.second) { - return true; - } else { - if (f.second.second > s.second.second) { - return false; - } else { - // in this case, both the filtration value and the dimensions for those cells are the same. - // Since it may be nice to have a stable sorting procedure, in this case, we compare positions in the bitmap: - return ( f.first < s.first); - } - } - } - } -} - -template -void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() { - if (globalDbg) { - std::cerr << "void Bitmap_cubical_complex::initializeElementsOrderedAccordingToFiltration() \n"; - } - // ( position , (filtration , dimension) ) - std::vector< std::pair< size_t, std::pair< T, char > > > dataOfElementsFromBitmap(this->data.size()); - for (size_t i = 0; i != this->data.size(); ++i) { - // TODO(Pawel Dlotko): This can be optimized by having a counter here. We do not need to re-compute the dimension - // for every cell from scratch - dataOfElementsFromBitmap[i] = std::make_pair(i, std::make_pair(this->data[i], this->get_dimension_of_a_cell(i))); - } - std::sort(dataOfElementsFromBitmap.begin(), dataOfElementsFromBitmap.end(), - compareElementsForElementsOrderedAccordingToFiltration); - - // Elements of bitmap ordered according to filtration then according to dimension then according to position in bitmap - std::vector< size_t > elements_of_bitmap_ordered(this->data.size()); - for (size_t i = 0; i != dataOfElementsFromBitmap.size(); ++i) { - elements_of_bitmap_ordered[i] = dataOfElementsFromBitmap[i].first; - } - this->elementsOrderedAccordingToFiltration = elements_of_bitmap_ordered; -} - - -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// - -#endif // BITMAP_CUBICAL_COMPLEX_H_ + /* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 . + */ + + +#pragma once +#include +#include "Bitmap_cubical_complex_base.h" + + + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +//global variable, was used just for debugging. +const bool globalDbg = false; + +template +class Bitmap_cubical_complex : public Bitmap_cubical_complex_base +{ +public: +//*********************************************// +//Typedefs and typenames +//*********************************************// + friend class Simplex_handle; + typedef size_t Simplex_key; + typedef T Filtration_value; + + +//*********************************************// +//Simplex handle class +//*********************************************// + /** + * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. + * Elements of this class are: the pointer to the bitmap B in which the considered cell is + * together with a position of this cell in B. Given this data, + * one can get all the information about the considered cell. + **/ + class Simplex_handle + { + public: + Simplex_handle() + { + if ( globalDbg ){cerr << "Simplex_handle()\n";} + this->b = 0; + this->position = 0; + } + + Simplex_handle(Bitmap_cubical_complex* b) + { + if ( globalDbg ) + { + cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; + } + this->b = b; + this->position = 0; + } + + //Simplex_handle( const Simplex_handle& org ):b(org.b) + //{ + // if ( globalDbg ){cerr << "Simplex_handle( const Simplex_handle& org )\n";} + // this->position = org.position; + //} + + Simplex_handle operator = ( const Simplex_handle& rhs ) + { + if ( globalDbg ){cerr << "Simplex_handle operator = \n";} + this->position = rhs.position; + this->b = rhs.b; + return *this; + } + + Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position) + { + if ( globalDbg ) + { + cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; + cerr << "Position : " << position << endl; + } + this->b = b; + this->position = position; + } + friend class Bitmap_cubical_complex; + private: + Bitmap_cubical_complex* b; + Simplex_key position; + //Assumption -- field above always keep the REAL position of simplex in the bitmap, + //no matter what keys have been. + //to deal with the keys, the class Bitmap_cubical_complex have extra vectors: key_associated_to_simplex and + //simplex_associated_to_key that allow to move between actual cell and the key assigned to it. + }; + + +//*********************************************// +//Constructors +//*********************************************// + //Over here we need to definie various input types. I am proposing the following ones: + //Perseus style + //H5 files? TODO + //binary files with little endiangs / big endians? TODO + //constructor from a vector of elements of a type T. TODO + + /** + * Constructor form a Perseus-style file. + **/ + Bitmap_cubical_complex( const char* perseus_style_file ): + Bitmap_cubical_complex_base(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1), + simplex_associated_to_key(this->total_number_of_cells+1) + { + if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} + for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) + { + this->key_associated_to_simplex[i] = this->simplex_associated_to_key[i] = i; + } + //we initialize this only once, in each constructor, when the bitmap is constructed. + //If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initialize_elements_ordered_according_to_filtration(); + } + + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * in the following directions and vector of element of a type T + * with filtration on top dimensional cells. + **/ + Bitmap_cubical_complex( std::vector& dimensions , std::vector& top_dimensional_cells ): + Bitmap_cubical_complex_base(dimensions,top_dimensional_cells), + key_associated_to_simplex(this->total_number_of_cells+1), + simplex_associated_to_key(this->total_number_of_cells+1) + { + for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) + { + this->key_associated_to_simplex[i] = this->simplex_associated_to_key[i] = i; + } + //we initialize this only once, in each constructor, when the bitmap is constructed. + //If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initialize_elements_ordered_according_to_filtration(); + } + +//*********************************************// +//Other 'easy' functions +//*********************************************// + /** + * Returns number of all cubes in the complex. + **/ + size_t num_simplices()const + { + return this->total_number_of_cells; + } + + /** + * Returns a Simplex_handle to a cube that do not exist in this complex. + **/ + Simplex_handle null_simplex() + { + return Simplex_handle(this,this->data.size()); + } + + /** + * Returns dimension of the complex. + **/ + size_t dimension() + { + return this->sizes.size(); + } + + /** + * Return dimension of a cell pointed by the Simplex_handle. + **/ + unsigned dimension(const Simplex_handle& sh) + { + if ( globalDbg ){cerr << "unsigned dimension(const Simplex_handle& sh)\n";} + if ( sh.position != this->data.size() ) return sh.b->get_dimension_of_a_cell( sh.position ); + return -1; + } + + /** + * Return the filtration of a cell pointed by the Simplex_handle. + **/ + T filtration(const Simplex_handle& sh) + { + if ( globalDbg ){cerr << "T filtration(const Simplex_handle& sh)\n";} + //Returns the filtration value of a simplex. + if ( sh.position != this->data.size() ) return sh.b->data[ sh.position ]; + return std::numeric_limits::max(); + } + + /** + * Return a key which is not a key of any cube in the considered data structure. + **/ + Simplex_key null_key() + { + if ( globalDbg ){cerr << "Simplex_key null_key()\n";} + return this->data.size(); + } + + /** + * Return the key of a cube pointed by the Simplex_handle. + **/ + Simplex_key key(const Simplex_handle& sh) + { + if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} + return sh.b->key_associated_to_simplex[ sh.position ]; + } + + /** + * Return the Simplex_handle given the key of the cube. + **/ + Simplex_handle simplex(Simplex_key key) + { + if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} + return Simplex_handle( this , this->simplex_associated_to_key[ key ] ); + } + + /** + * Assign key to a cube pointed by the Simplex_handle + **/ + void assign_key(Simplex_handle& sh, Simplex_key key) + { + if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} + this->key_associated_to_simplex[sh.position] = key; + this->simplex_associated_to_key[key] = sh.position; + } + + /** + * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. + **/ + void initialize_elements_ordered_according_to_filtration(); + + + +//*********************************************// +//Iterators +//*********************************************// + + /** + * Boundary_simplex_iterator class allows iteration on boundary of each cube. + **/ + class Boundary_simplex_range; + class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > + { + //Iterator on the simplices belonging to the boundary of a simplex. + //value_type must be 'Simplex_handle'. + public: + Boundary_simplex_iterator( Simplex_handle& sh ):sh(sh) + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n";} + this->position = 0; + this->boundary_elements = this->sh.b->get_boundary_of_a_cell( this->sh.position ); + } + Boundary_simplex_iterator operator++() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator operator++()\n";} + ++this->position; + return *this; + } + Boundary_simplex_iterator operator++(int) + { + Boundary_simplex_iterator result = *this; + ++(*this); + return result; + } + Boundary_simplex_iterator operator =( const Boundary_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator operator =\n";} + this->sh = rhs.sh; + this->boundary_elements.clear(); + this->boundary_elementsinsert + (this->boundary_elements.end(), rhs.boundary_elements.begin(), rhs.boundary_elements.end()); + } + bool operator == ( const Boundary_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator ==\n";} + if ( this->position == rhs.position ) + { + if ( this->boundary_elements.size() != rhs.boundary_elements.size() )return false; + for ( size_t i = 0 ; i != this->boundary_elements.size() ; ++i ) + { + if ( this->boundary_elements[i] != rhs.boundary_elements[i] )return false; + } + return true; + } + return false; + } + + bool operator != ( const Boundary_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator != \n";} + return !(*this == rhs); + } + Simplex_handle operator*() + { + if ( globalDbg ){cerr << "Simplex_handle operator*\n";} + return Simplex_handle( this->sh.b , this->boundary_elements[this->position] ); + } + + friend class Boundary_simplex_range; + private: + Simplex_handle sh; + std::vector< size_t > boundary_elements; + size_t position; + }; + + + /** + * Boundary_simplex_range class provides ranges for boundary iterators. + **/ + class Boundary_simplex_range + { + //Range giving access to the simplices in the boundary of a simplex. + //.begin() and .end() return type Boundary_simplex_iterator. + public: + Boundary_simplex_range(const Simplex_handle& sh):sh(sh){}; + Boundary_simplex_iterator begin() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator begin\n";} + Boundary_simplex_iterator it( this->sh ); + return it; + } + Boundary_simplex_iterator end() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator end()\n";} + Boundary_simplex_iterator it( this->sh ); + it.position = it.boundary_elements.size(); + return it; + } + private: + Simplex_handle sh; + }; + + + /** + * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. + * Secondary criteria for filtration are: + * (1) Dimension of a cube (lower dimensional comes first). + * (2) Position in the data structure (the ones that are earlies in the data structure comes first). + **/ + class Filtration_simplex_range; + class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > + { + //Iterator over all simplices of the complex in the order of the indexing scheme. + //'value_type' must be 'Simplex_handle'. + public: + Filtration_simplex_iterator( Bitmap_cubical_complex* b ):b(b),position(0){}; + Filtration_simplex_iterator():b(NULL){}; + + Filtration_simplex_iterator operator++() + { + if ( globalDbg ){cerr << "Filtration_simplex_iterator operator++\n";} + ++this->position; + return (*this); + } + Filtration_simplex_iterator operator++(int) + { + Filtration_simplex_iterator result = *this; + ++(*this); + return result; + } + Filtration_simplex_iterator operator =( const Filtration_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "Filtration_simplex_iterator operator =\n";} + this->b = rhs.b; + this->position = rhs.position; + } + bool operator == ( const Filtration_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";} + if ( this->position == rhs.position ) + { + return true; + } + return false; + } + + bool operator != ( const Filtration_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";} + return !(*this == rhs); + } + Simplex_handle operator*() + { + if ( globalDbg ){cerr << "Simplex_handle operator*()\n";} + return Simplex_handle( this->b , this->b->elements_ordered_according_to_filtration[ this->position ] ); + } + + friend class Filtration_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + }; + + + /** + * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. + **/ + class Filtration_simplex_range + { + //Range over the simplices of the complex in the order of the filtration. + //.begin() and .end() return type Filtration_simplex_iterator. + public: + Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; + Filtration_simplex_iterator begin() + { + if ( globalDbg ){cerr << "Filtration_simplex_iterator begin() \n";} + return Filtration_simplex_iterator( this->b ); + } + Filtration_simplex_iterator end() + { + if ( globalDbg ){cerr << "Filtration_simplex_iterator end()\n";} + Filtration_simplex_iterator it( this->b ); + it.position = this->b->elements_ordered_according_to_filtration.size(); + return it; + } + private: + Bitmap_cubical_complex* b; + }; + + + +//*********************************************// +//Methods to access iterators from the container: + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) + { + if ( globalDbg ){cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n";} + //Returns a range giving access to all simplices of the boundary of a simplex, + //i.e. the set of codimension 1 subsimplices of the Simplex. + return Boundary_simplex_range(sh); + } + + /** + * filtration_simplex_range creates an object of a Filtration_simplex_range class + * that provides ranges for the Filtration_simplex_iterator. + **/ + Filtration_simplex_range filtration_simplex_range() + { + if ( globalDbg ){cerr << "Filtration_simplex_range filtration_simplex_range()\n";} + //Returns a range over the simplices of the complex in the order of the filtration + return Filtration_simplex_range(this); + } +//*********************************************// + + + +//*********************************************// +//Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. + //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so + //I understand that this is something that was planned (for simplicial maps?) + //but was never finished. The only idea I have here is to use the same empty structure from + //IndexingTag.h file, but only if the compiler needs it. If the compiler + //do not need it, then I would rather not add here elements which I do not understand. + //typedef Indexing_tag + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + std::pair endpoints( Simplex_handle sh ) + { + std::vector< size_t > bdry = this->get_boundary_of_a_cell( sh.position ); + if ( globalDbg ) + { + cerr << "std::pair endpoints( Simplex_handle sh )\n"; + cerr << "bdry.size() : " << bdry.size() << endl; + } + //this method returns two first elements from the boundary of sh. + if ( bdry.size() < 2 ) + throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); + return std::make_pair( Simplex_handle(this,bdry[0]) , Simplex_handle(this,bdry[1]) ); + } + + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range; + class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > + { + //Iterator over all simplices of the complex in the order of the indexing scheme. + //'value_type' must be 'Simplex_handle'. + public: + Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d ):b(b),dimension(d) + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n";} + //find the position of the first simplex of a dimension d + this->position = 0; + while ( + (this->position != b->data.size()) && + ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) + ) + { + ++this->position; + } + }; + Skeleton_simplex_iterator ():b(NULL),dimension(0){}; + + Skeleton_simplex_iterator operator++() + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator++()\n";} + //increment the position as long as you did not get to the next element of the dimension dimension. + ++this->position; + while ( + (this->position != this->b->data.size()) && + ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) + ) + { + ++this->position; + } + return (*this); + } + Skeleton_simplex_iterator operator++(int) + { + Skeleton_simplex_iterator result = *this; + ++(*this); + return result; + } + Skeleton_simplex_iterator operator =( const Skeleton_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator =\n";} + this->b = rhs.b; + this->position = rhs.position; + } + bool operator == ( const Skeleton_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator ==\n";} + if ( this->position == rhs.position ) + { + return true; + } + return false; + } + + bool operator != ( const Skeleton_simplex_iterator& rhs ) + { + if ( globalDbg ){cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";} + return !(*this == rhs); + } + Simplex_handle operator*() + { + if ( globalDbg ){cerr << "Simplex_handle operator*() \n";} + return Simplex_handle( this->b , this->position ); + } + + friend class Skeleton_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + unsigned dimension; + }; + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range + { + //Range over the simplices of the complex in the order of the filtration. + //.begin() and .end() return type Filtration_simplex_iterator. + public: + Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; + Skeleton_simplex_iterator begin() + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator begin()\n";} + return Skeleton_simplex_iterator( this->b , this->dimension ); + } + Skeleton_simplex_iterator end() + { + if ( globalDbg ){cerr << "Skeleton_simplex_iterator end()\n";} + Skeleton_simplex_iterator it( this->b , this->dimension ); + it.position = this->b->data.size(); + return it; + } + private: + Bitmap_cubical_complex* b; + unsigned dimension; + }; + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + Skeleton_simplex_range skeleton_simplex_range( unsigned dimension ) + { + if ( globalDbg ){cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n";} + return Skeleton_simplex_range( this , dimension ); + } + + + +//*********************************************// +//functions used for debugging: + /** + * Function used for debugging purposes. + **/ + //void printkey_associated_to_simplex() + //{ + // for ( size_t i = 0 ; i != this->data.size() ; ++i ) + // { + // cerr << i << " -> " << this->simplex_associated_to_key[i] << endl; + // } + //} + + /** + * Function used for debugging purposes. + **/ + size_t printRealPosition( const Simplex_handle& sh ) + { + return sh.position; + } + +private: + std::vector< size_t > key_associated_to_simplex; + std::vector< size_t > simplex_associated_to_key; + std::vector< size_t > elements_ordered_according_to_filtration; + //filed above is needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. +};//Bitmap_cubical_complex + +template +bool compare_elements_for_elements_ordered_according_to_filtration +( const std::pair< size_t , std::pair< T , char > >& f , const std::pair< size_t , std::pair< T , char > >& s ) +{ + if ( globalDbg ){cerr << "compare_elements_for_elements_ordered_according_to_filtration\n";} + if ( f.second.first < s.second.first ) + { + return true; + } + else + { + if ( f.second.first > s.second.first ) + { + return false; + } + else + { + //in this case f.second.first == s.second.first, and we use dimension to compare: + if ( f.second.second < s.second.second ) + { + return true; + } + else + { + if ( f.second.second > s.second.second ) + { + return false; + } + else + { + //in this case, both the filtration value and the dimensions for those cells are the same. + //Since it may be nice to have a stable sorting procedure, in this case, + //we compare positions in the bitmap: + return ( f.first < s.first ); + } + } + } + } +} + +template +void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() +{ + if ( globalDbg ) + { + cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; + } + //( position , (filtration , dimension) ) + std::vector< std::pair< size_t , std::pair< T , char > > > data_of_elements_from_bitmap( this->data.size() ); + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + //TODO -- this can be optimized by having a counter here. + //We do not need to re-compute the dimension for every cell from scratch + data_of_elements_from_bitmap[i] = + std::make_pair( i , std::make_pair( this->data[i] , this->get_dimension_of_a_cell(i) ) ); + } + std::sort( data_of_elements_from_bitmap.begin() , + data_of_elements_from_bitmap.end() , + compare_elements_for_elements_ordered_according_to_filtration ); + + std::vector< size_t > + elements_ordered_according_to_filtration_then_to_dimension_then_to_position + ( this->data.size() ); + for ( size_t i = 0 ; i != data_of_elements_from_bitmap.size() ; ++i ) + { + elements_ordered_according_to_filtration_then_to_dimension_then_to_position[i] + = data_of_elements_from_bitmap[i].first; + } + this->elements_ordered_according_to_filtration = + elements_ordered_according_to_filtration_then_to_dimension_then_to_position; +} + + +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// + + +} +} \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index d9c91832..2c2bd481 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -1,593 +1,759 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-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 BITMAP_CUBICAL_COMPLEX_BASE_H_ -#define BITMAP_CUBICAL_COMPLEX_BASE_H_ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * This is a class implementing a basic bitmap data structure to store cubical complexes. It implements only the most basic subroutines. - * The idea of the bitmap is the following. Our aim is to have a memory efficient data structure to store d-dimensional cubical complex C being a cubical decomposition - * of a rectangular region of a space. This is achieved by storing C as a vector of bits (this is where the name 'bitmap' came from). Each cell is represented by a single - * bit (in case of black and white bitmaps, or by a single element of a type T (here T is a filtration type of a bitmap, typically a double). All the informations needed for homology and - * persistent homology computations (like dimension of a cell, boundary and coboundary elements of a cell, are then obtained from the position of the element in C. - */ -template -class Bitmap_cubical_complex_base { - public: - /** - * There are a few constructors of a Bitmap_cubical_complex_base class. First one, that takes vector, creates an empty bitmap of a dimension equal to the number of elements in the - * input vector and size in the i-th dimension equal the number in the position i-of the input vector. - */ - Bitmap_cubical_complex_base(std::vector sizes_); - /** - * The second constructor takes as a input a Perseus style file. For more details, please consult the documentations of Perseus software as well as examples attached to this - * implementation. - **/ - Bitmap_cubical_complex_base(char* perseusStyleFile_); - /** - * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) together with vector of filtration values of top dimensional cells. - **/ - Bitmap_cubical_complex_base(std::vector dimensions_, std::vector topDimensionalCells_); - - /** - * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell and get_cell_data are the basic functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a non-negative integer, indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to the positions of (co)boundary element of the input cell. - */ - inline std::vector< size_t > get_boundary_of_a_cell(size_t cell_); - /** - * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell and get_cell_data are the basic functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a non-negative integer, indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to the positions of (co)boundary element of the input cell. - **/ - inline std::vector< size_t > get_coboundary_of_a_cell(size_t cell_); - /** - * In the case of get_dimension_of_a_cell function, the output is a non-negative integer indicating the dimension of a cell. - **/ - inline unsigned get_dimension_of_a_cell(size_t cell_); - /** - * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. - **/ - inline T& get_cell_data(size_t cell_); - - - /** - * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. Then, there are a few ways one can pick the filtration of lower dimensional - * cells. The most typical one is by so called lower star filtration. This function is always called by any constructor which takes the top dimensional cells. If you use such a constructor, - * then there is no need to call this function. Call it only if you are putting the filtration of the cells by your own (for instance by using topDimensionalCellsIterator). - **/ - void impose_lower_star_filtration(); // assume that top dimensional cells are already set. - - /** - * Returns dimension of a complex. - **/ - inline unsigned dimension() { - return sizes.size(); - } - - /** - * Returns number of all cubes in the data structure. - **/ - inline unsigned size_of_bitmap() { - return this->data.size(); - } - - /** - * Writing to stream operator. - **/ - template - friend std::ostream& operator<<(std::ostream & os_, const Bitmap_cubical_complex_base& b_); - - // ITERATORS - - /** - * Iterator through all cells in the complex (in order they appear in the structure -- i.e. in lexicographical order). - **/ - typedef typename std::vector< T >::iterator all_cells_iterator; - - all_cells_iterator all_cells_begin()const { - return this->data.begin(); - } - - all_cells_iterator all_cells_end()const { - return this->data.end(); - } - - - typedef typename std::vector< T >::const_iterator all_cells_const_iterator; - - all_cells_const_iterator all_cells_const_begin()const { - return this->data.begin(); - } - - all_cells_const_iterator all_cells_const_end()const { - return this->data.end(); - } - - /** - * Iterator through top dimensional cells of the complex. The cells appear in order they are stored in the structure (i.e. in lexicographical order) - **/ - class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > { - public: - Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b_) : b(b_) { - for (size_t i = 0; i != b_.dimension(); ++i) { - this->counter.push_back(0); - } - } - - Top_dimensional_cells_iterator operator++() { - // first find first element of the counter that can be increased: - size_t dim = 0; - while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; - - if (dim != this->b.dimension()) { - ++this->counter[dim]; - for (size_t i = 0; i != dim; ++i) { - this->counter[i] = 0; - } - } else { - ++this->counter[0]; - } - return *this; - } - - Top_dimensional_cells_iterator operator++(int) { - Top_dimensional_cells_iterator result = *this; - ++(*this); - return result; - } - - Top_dimensional_cells_iterator operator=(const Top_dimensional_cells_iterator& rhs_) { - this->counter = rhs_.counter; - this->b = rhs_.b; - return *this; - } - - bool operator==(const Top_dimensional_cells_iterator& rhs_) { - if (&this->b != &rhs_.b)return false; - if (this->counter.size() != rhs_.counter.size())return false; - for (size_t i = 0; i != this->counter.size(); ++i) { - if (this->counter[i] != rhs_.counter[i])return false; - } - return true; - } - - bool operator!=(const Top_dimensional_cells_iterator& rhs_) { - return !(*this == rhs_); - } - - T& operator*() { - // given the counter, compute the index in the array and return this element. - unsigned index = 0; - for (size_t i = 0; i != this->counter.size(); ++i) { - index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; - } - return this->b.data[index]; - } - - size_t computeIndexInBitmap() { - size_t index = 0; - for (size_t i = 0; i != this->counter.size(); ++i) { - index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; - } - return index; - } - - void printCounter() { - for (size_t i = 0; i != this->counter.size(); ++i) { - std::cout << this->counter[i] << " "; - } - } - friend class Bitmap_cubical_complex_base; - protected: - std::vector< unsigned > counter; - Bitmap_cubical_complex_base& b; - }; - - Top_dimensional_cells_iterator top_dimensional_cells_begin() { - Top_dimensional_cells_iterator a(*this); - return a; - } - - Top_dimensional_cells_iterator top_dimensional_cells_end() { - Top_dimensional_cells_iterator a(*this); - for (size_t i = 0; i != this->dimension(); ++i) { - a.counter[i] = this->sizes[i] - 1; - } - a.counter[0]++; - return a; - } - - - //****************************************************************************************************************// - //****************************************************************************************************************// - //****************************************************************************************************************// - //****************************************************************************************************************// - - - //****************************************************************************************************************// - //****************************************************************************************************************// - //****************************************************************************************************************// - //****************************************************************************************************************// - - protected: - std::vector sizes; - std::vector multipliers; - std::vector data; - size_t totalNumberOfCells; - - void set_up_containers(std::vector sizes_) { - unsigned multiplier = 1; - for (size_t i = 0; i != sizes_.size(); ++i) { - this->sizes.push_back(sizes_[i]); - this->multipliers.push_back(multiplier); - // multiplier *= 2*(sizes[i]+1)+1; - multiplier *= 2 * sizes_[i] + 1; - } - // std::reverse( this->sizes.begin() , this->sizes.end() ); - std::vector data(multiplier); - std::fill(data.begin(), data.end(), INT_MAX); - this->totalNumberOfCells = multiplier; - this->data = data; - } - - size_t compute_position_in_bitmap(std::vector< int > counter_) { - size_t position = 0; - for (size_t i = 0; i != this->multipliers.size(); ++i) { - position += this->multipliers[i] * counter_[i]; - } - return position; - } - - std::vector compute_counter_for_given_cell(size_t cell_) { - std::vector counter; - for (size_t dim = this->sizes.size(); dim != 0; --dim) { - counter.push_back(cell_ / this->multipliers[dim - 1]); - cell_ = cell_ % this->multipliers[dim - 1]; - } - std::reverse(counter.begin(), counter.end()); - return counter; - } - - std::vector< size_t > generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_); -}; - -template -std::ostream& operator<<(std::ostream & out_, const Bitmap_cubical_complex_base& b_) { - // for ( typename bitmap::all_cells_const_iterator it = b.all_cells_const_begin() ; - // it != b.all_cells_const_end() ; ++it ) - for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b_.all_cells_const_begin(); - it != b_.all_cells_const_end(); ++it) { - out_ << *it << " "; - } - return out_; -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizes_) { - this->set_up_containers(sizes_); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(std::vector sizesInFollowingDirections_, - std::vector topDimensionalCells_) { - this->set_up_containers(sizesInFollowingDirections_); - - size_t numberOfTopDimensionalElements = 1; - for (size_t i = 0; i != sizesInFollowingDirections_.size(); ++i) { - numberOfTopDimensionalElements *= sizesInFollowingDirections_[i]; - } - if (numberOfTopDimensionalElements != topDimensionalCells_.size()) { - std::cerr << "Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , " - "std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from " - "sizesInFollowingDirections vector is different than the size of topDimensionalCells vector." << std::endl; - throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizesInFollowingDirections_ , " - "std::vector topDimensionalCells_ ). Number of top dimensional elements that follow from " - "sizesInFollowingDirections vector is different than the size of topDimensionalCells vector."); - } - - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - size_t index = 0; - for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { - (*it) = topDimensionalCells_[index]; - ++index; - } - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(char* perseusStyleFile_) { - bool dbg = false; - std::ifstream inFiltration, inIds; - inFiltration.open(perseusStyleFile_); - unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - if (dbg) { - std::cerr << "dimensionOfData : " << dimensionOfData << std::endl; - } - - std::vector sizes; - for (size_t i = 0; i != dimensionOfData; ++i) { - int sizeInThisDimension; - inFiltration >> sizeInThisDimension; - sizeInThisDimension = abs(sizeInThisDimension); - sizes.push_back(sizeInThisDimension); - if (dbg) { - std::cerr << "sizeInThisDimension : " << sizeInThisDimension << std::endl; - } - } - this->set_up_containers(sizes); - - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_begin(); - - // TODO(Pawel Dlotko): Over here we also need to read id's of cell and put them to bitmapElement structure! - while (!inFiltration.eof()) { - double filtrationLevel; - inFiltration >> filtrationLevel; - if (dbg) { - std::cerr << "Cell of an index : " << it.computeIndexInBitmap() << " and dimension: " << - this->get_dimension_of_a_cell(it.computeIndexInBitmap()) << " get the value : " << - filtrationLevel << std::endl; - } - *it = filtrationLevel; - ++it; - } - inFiltration.close(); - this->impose_lower_star_filtration(); -} - -template -std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell_) { - bool bdg = false; - // First of all, we need to take the list of coordinates in which the cell has nonzero length. - // We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensionsInWhichCellHasNonzeroLength; - unsigned dimension = 0; - size_t cell1 = cell_; - for (size_t i = this->multipliers.size(); i != 0; --i) { - unsigned position = cell1 / multipliers[i - 1]; - if (position % 2 == 1) { - dimensionsInWhichCellHasNonzeroLength.push_back(i - 1); - dimension++; - } - cell1 = cell1 % multipliers[i - 1]; - } - - if (bdg) { - std::cerr << "dimensionsInWhichCellHasNonzeroLength : \n"; - for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { - std::cerr << dimensionsInWhichCellHasNonzeroLength[i] << std::endl; - } - getchar(); - } - - std::vector< size_t > boundaryElements; - if (dimensionsInWhichCellHasNonzeroLength.size() == 0)return boundaryElements; - for (size_t i = 0; i != dimensionsInWhichCellHasNonzeroLength.size(); ++i) { - boundaryElements.push_back(cell_ - multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); - boundaryElements.push_back(cell_ + multipliers[ dimensionsInWhichCellHasNonzeroLength[i] ]); - - if (bdg) std::cerr << "multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; - if (bdg) std::cerr << "cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << - cell_ - multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; - if (bdg) std::cerr << "cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] : " << - cell_ + multipliers[dimensionsInWhichCellHasNonzeroLength[i]] << std::endl; - } - return boundaryElements; -} - -template -std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(size_t cell_) { - bool bdg = false; - // First of all, we need to take the list of coordinates in which the cell has nonzero length. - // We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensionsInWhichCellHasZeroLength; - unsigned dimension = 0; - size_t cell1 = cell_; - for (size_t i = this->multipliers.size(); i != 0; --i) { - unsigned position = cell1 / multipliers[i - 1]; - if (position % 2 == 0) { - dimensionsInWhichCellHasZeroLength.push_back(i - 1); - dimension++; - } - cell1 = cell1 % multipliers[i - 1]; - } - - std::vector counter = this->compute_counter_for_given_cell(cell_); - // reverse(counter.begin() , counter.end()); - - if (bdg) { - std::cerr << "dimensionsInWhichCellHasZeroLength : \n"; - for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { - std::cerr << dimensionsInWhichCellHasZeroLength[i] << std::endl; - } - std::cerr << "\n counter : " << std::endl; - for (size_t i = 0; i != counter.size(); ++i) { - std::cerr << counter[i] << std::endl; - } - getchar(); - } - - std::vector< size_t > coboundaryElements; - if (dimensionsInWhichCellHasZeroLength.size() == 0)return coboundaryElements; - for (size_t i = 0; i != dimensionsInWhichCellHasZeroLength.size(); ++i) { - if (bdg) { - std::cerr << "Dimension : " << i << std::endl; - if (counter[dimensionsInWhichCellHasZeroLength[i]] == 0) { - std::cerr << "In dimension : " << i << - " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; - } - if (counter[dimensionsInWhichCellHasZeroLength[i]] == 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]]) { - std::cerr << "In dimension : " << i << - " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; - } - } - - - if ((cell_ > multipliers[dimensionsInWhichCellHasZeroLength[i]]) && - (counter[dimensionsInWhichCellHasZeroLength[i]] != 0)) { - // if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 0 ) - if (bdg)std::cerr << "Subtracting : " << cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]] << std::endl; - coboundaryElements.push_back(cell_ - multipliers[dimensionsInWhichCellHasZeroLength[i]]); - } - if ((cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] < this->data.size()) && - (counter[dimensionsInWhichCellHasZeroLength[i]] != 2 * this->sizes[dimensionsInWhichCellHasZeroLength[i]])) { - // if ( counter[dimensionsInWhichCellHasZeroLength[i]] != 2*this->sizes[dimensionsInWhichCellHasZeroLength[i]] ) - coboundaryElements.push_back(cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]]); - if (bdg)std::cerr << "Adding : " << cell_ + multipliers[dimensionsInWhichCellHasZeroLength[i]] << std::endl; - } - } - return coboundaryElements; -} - -template -unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell(size_t cell_) { - bool dbg = false; - if (dbg)std::cerr << "\n\n\n Computing position o a cell of an index : " << cell_ << std::endl; - unsigned dimension = 0; - for (size_t i = this->multipliers.size(); i != 0; --i) { - unsigned position = cell_ / multipliers[i - 1]; - - if (dbg)std::cerr << "i-1 :" << i - 1 << std::endl; - if (dbg)std::cerr << "cell_ : " << cell_ << std::endl; - if (dbg)std::cerr << "position : " << position << std::endl; - if (dbg)std::cerr << "multipliers[" << i - 1 << "] = " << multipliers[i - 1] << std::endl; - if (dbg)getchar(); - - if (position % 2 == 1) { - if (dbg)std::cerr << "Nonzero length in this direction \n"; - dimension++; - } - cell_ = cell_ % multipliers[i - 1]; - } - return dimension; -} - -template -T& Bitmap_cubical_complex_base::get_cell_data(size_t cell_) { - return this->data[cell_]; -} - -template -void Bitmap_cubical_complex_base::impose_lower_star_filtration() { - bool dbg = false; - - // this vector will be used to check which elements have already been taken care of in imposing lower star filtration: - std::vector isThisCellConsidered(this->data.size(), false); - - std::vector indicesToConsider; - // we assume here that we already have a filtration on the top dimensional cells - // and we have to extend it to lower ones. - typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - for (it = this->top_dimensional_cells_begin(); it != this->top_dimensional_cells_end(); ++it) { - indicesToConsider.push_back(it.computeIndexInBitmap()); - } - - while (indicesToConsider.size()) { - if (dbg) { - std::cerr << "indicesToConsider in this iteration \n"; - for (size_t i = 0; i != indicesToConsider.size(); ++i) { - std::cout << indicesToConsider[i] << " "; - } - getchar(); - } - std::vector newIndicesToConsider; - for (size_t i = 0; i != indicesToConsider.size(); ++i) { - std::vector bd = this->get_boundary_of_a_cell(indicesToConsider[i]); - for (size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) { - if (this->data[ bd[boundaryIt] ] > this->data[ indicesToConsider[i] ]) { - this->data[ bd[boundaryIt] ] = this->data[ indicesToConsider[i] ]; - } - if (isThisCellConsidered[ bd[boundaryIt] ] == false) { - newIndicesToConsider.push_back(bd[boundaryIt]); - isThisCellConsidered[ bd[boundaryIt] ] = true; - } - } - } - indicesToConsider.swap(newIndicesToConsider); - } -} - -template -std::vector< size_t > -Bitmap_cubical_complex_base::generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions(std::vector< bool > directionsForPeriodicBCond_) { - bool dbg = false; - if (this->sizes.size() != directionsForPeriodicBCond_.size()) - throw ("directionsForPeriodicBCond_ vector size is different from the size of the bitmap. " - "The program will now terminate \n"); - - std::vector sizes(this->sizes.size()); - for (size_t i = 0; i != this->sizes.size(); ++i)sizes[i] = 2 * this->sizes[i]; - - counter c(sizes); - - std::vector< size_t > result; - - for (size_t i = 0; i != this->data.size(); ++i) { - size_t position; - if (!c.isFinal()) { - position = i; - // result.push_back( i ); - } else { - std::vector< bool > finals = c.directionsOfFinals(); - bool jumpInPosition = false; - for (size_t dir = 0; dir != finals.size(); ++dir) { - if (finals[dir] == false)continue; - if (directionsForPeriodicBCond_[dir]) { - jumpInPosition = true; - } - } - if (jumpInPosition == true) { - // in this case this guy is final, so we need to find 'the opposite one' - position = compute_position_in_bitmap(c.findOpposite(directionsForPeriodicBCond_)); - } else { - position = i; - } - } - result.push_back(position); - if (dbg) { - std::cerr << " position : " << position << std::endl; - std::cerr << c << std::endl; - getchar(); - } - - c.increment(); - } - - return result; -} - -#endif // BITMAP_CUBICAL_COMPLEX_BASE_H_ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include "counter.h" + + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + + + +/** + * This is a class implementing a basic bitmap data structure to store cubical complexes. + * It implements only the most basic subroutines. + * The idea of the bitmap is the following. Our aim is to have a memory efficient + * data structure to store d-dimensional cubical complex + * C being a cubical decomposition + * of a rectangular region of a space. This is achieved by storing C as a + * vector of bits (this is where the name 'bitmap' came from). + * Each cell is represented by a single + * bit (in case of black and white bitmaps, or by a single element of a type T + * (here T is a filtration type of a bitmap, typically a double). + * All the informations needed for homology and + * persistent homology computations (like dimension of a cell, boundary and + * coboundary elements of a cell, are then obtained from the + * position of the element in C. + * The default filtration used in this implementation is the lower star filtration. + */ +template +class Bitmap_cubical_complex_base +{ +public: + /** + * There are a few constructors of a Bitmap_cubical_complex_base class. + * First one, that takes vector, creates an empty bitmap of a dimension equal + * the number of elements in the + * input vector and size in the i-th dimension equal the number in the position i-of the input vector. + */ + Bitmap_cubical_complex_base( std::vector& sizes ); + /** + * The second constructor takes as a input a Perseus style file. For more details, + * please consult the documentations of + * Perseus software as well as examples attached to this + * implementation. + **/ + Bitmap_cubical_complex_base( const char* perseus_style_file ); + /** + * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) + * together with vector of filtration values of top dimensional cells. + **/ + Bitmap_cubical_complex_base( std::vector& dimensions , const std::vector& top_dimensional_cells ); + + /** + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell + * and get_cell_data are the basic + * functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a + * non-negative integer, indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to + * the positions of (co)boundary element of the input cell. + */ + inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + /** + * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, + * get_dimension_of_a_cell and get_cell_data are the basic + * functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. + * The input parameter of all of those function is a non-negative integer, + * indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if + * non-negative integers pointing to the + * positions of (co)boundary element of the input cell. + **/ + inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + /** + * In the case of get_dimension_of_a_cell function, the output is a non-negative integer + * indicating the dimension of a cell. + **/ + inline unsigned get_dimension_of_a_cell( size_t cell )const; + /** + * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. + **/ + inline T& get_cell_data( size_t cell ); + + + /** + * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. + * Then, there are a few ways one can pick the filtration of lower dimensional + * cells. The most typical one is by so called lower star filtration. This function is always called by any + * constructor which takes the top dimensional cells. If you use such a constructor, + * then there is no need to call this function. Call it only if you are putting the filtration + * of the cells by your own (for instance by using Top_dimensional_cells_iterator). + **/ + void impose_lower_star_filtration();//assume that top dimensional cells are already set. + + /** + * Returns dimension of a complex. + **/ + inline unsigned dimension()const{ return sizes.size(); } + + /** + * Returns number of all cubes in the data structure. + **/ + inline unsigned size_of_bitmap()const + { + return this->data.size(); + } + + /** + * Writing to stream operator. + **/ + template + friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + + //ITERATORS + + /** + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). + **/ + typedef typename std::vector< T >::iterator all_cells_iterator; + all_cells_iterator all_cells_begin()const + { + return this->data.begin(); + } + all_cells_iterator all_cells_end()const + { + return this->data.end(); + } + + + typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + all_cells_const_iterator all_cells_const_begin()const + { + return this->data.begin(); + } + all_cells_const_iterator all_cells_const_end()const + { + return this->data.end(); + } + + /** + * Iterator through top dimensional cells of the complex. The cells appear in order they are stored + * in the structure (i.e. in lexicographical order) + **/ + class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > + { + public: + Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) + { + for ( size_t i = 0 ; i != b.dimension() ; ++i ) + { + this->counter.push_back(0); + } + } + Top_dimensional_cells_iterator operator++() + { + //first find first element of the counter that can be increased: + size_t dim = 0; + while ( ( dim != this->b.dimension() ) && ( this->counter[dim] == this->b.sizes[dim]-1 ) )++dim; + + if ( dim != this->b.dimension() ) + { + ++this->counter[dim]; + for ( size_t i = 0 ; i != dim ; ++i ) + { + this->counter[i] = 0; + } + } + else + { + ++this->counter[0]; + } + return *this; + } + Top_dimensional_cells_iterator operator++(int) + { + Top_dimensional_cells_iterator result = *this; + ++(*this); + return result; + } + Top_dimensional_cells_iterator operator =( const Top_dimensional_cells_iterator& rhs ) + { + this->counter = rhs.counter; + this->b = rhs.b; + return *this; + } + bool operator == ( const Top_dimensional_cells_iterator& rhs )const + { + if ( &this->b != &rhs.b )return false; + if ( this->counter.size() != rhs.counter.size() )return false; + for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + { + if ( this->counter[i] != rhs.counter[i] )return false; + } + return true; + } + bool operator != ( const Top_dimensional_cells_iterator& rhs )const + { + return !(*this == rhs); + } + + T& operator*() + { + //given the counter, compute the index in the array and return this element. + unsigned index = 0; + for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + { + index += (2*this->counter[i]+1)*this->b.multipliers[i]; + } + return this->b.data[index]; + } + + size_t compute_index_in_bitmap()const + { + size_t index = 0; + for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + { + index += (2*this->counter[i]+1)*this->b.multipliers[i]; + } + return index; + } + + void print_counter()const + { + for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + { + cout << this->counter[i] << " "; + } + } + friend class Bitmap_cubical_complex_base; + protected: + std::vector< unsigned > counter; + Bitmap_cubical_complex_base& b; + }; + Top_dimensional_cells_iterator top_dimensional_cells_begin() + { + Top_dimensional_cells_iterator a(*this); + return a; + } + Top_dimensional_cells_iterator top_dimensional_cells_end() + { + Top_dimensional_cells_iterator a(*this); + for ( size_t i = 0 ; i != this->dimension() ; ++i ) + { + a.counter[i] = this->sizes[i]-1; + } + a.counter[0]++; + return a; + } + + +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// + + +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// +//****************************************************************************************************************// + +protected: + std::vector sizes; + std::vector multipliers; + std::vector data; + size_t total_number_of_cells; + void set_up_containers( std::vector& sizes ) + { + unsigned multiplier = 1; + for ( size_t i = 0 ; i != sizes.size() ; ++i ) + { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + //multiplier *= 2*(sizes[i]+1)+1; + multiplier *= 2*sizes[i]+1; + } + //std::reverse( this->sizes.begin() , this->sizes.end() ); + std::vector data(multiplier); + std::fill( data.begin() , data.end() , std::numeric_limits::max() ); + this->total_number_of_cells = multiplier; + this->data = data; + } + + size_t compute_position_in_bitmap( std::vector< unsigned >& counter ) + { + size_t position = 0; + for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) + { + position += this->multipliers[i]*counter[i]; + } + return position; + } + + std::vector compute_counter_for_given_cell( size_t cell )const + { + std::vector counter; + for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) + { + counter.push_back(cell/this->multipliers[dim-1]); + cell = cell%this->multipliers[dim-1]; + } + std::reverse( counter.begin() , counter.end() ); + return counter; + } + + std::vector< size_t > + generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions + ( std::vector< bool >& directions_for_periodic_b_cond ); +}; + + + + +template +ostream& operator << ( ostream & out , const Bitmap_cubical_complex_base& b ) +{ + for ( typename Bitmap_cubical_complex_base::all_cells_const_iterator + it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) + { + out << *it << " "; + } + return out; +} + + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base +( std::vector& sizes ) +{ + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base +( std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) +{ + this->set_up_containers( sizes_in_following_directions ); + + size_t number_of_top_dimensional_elements = 1; + for ( size_t i = 0 ; i != sizes_in_following_directions.size() ; ++i ) + { + number_of_top_dimensional_elements *= sizes_in_following_directions[i]; + } + if ( number_of_top_dimensional_elements != top_dimensional_cells.size() ) + { + cerr << + "Error in constructor\ + Bitmap_cubical_complex_base\ + ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ + Number of top dimensional elements that follow from sizes_in_following_directions vector is different\ + than the size of top_dimensional_cells vector." << endl; + throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ + std::vector top_dimensional_cells )\ + . Number of top dimensional elements that follow from sizes_in_following_directions vector is different than the\ + size of top_dimensional_cells vector."); + } + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + size_t index = 0; + for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + (*it) = top_dimensional_cells[index]; + ++index; + } + this->impose_lower_star_filtration(); +} + + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file ) +{ + bool dbg = false; + ifstream inFiltration, inIds; + inFiltration.open( perseus_style_file ); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;} + + std::vector sizes; + for ( size_t i = 0 ; i != dimensionOfData ; ++i ) + { + unsigned size_in_this_dimension; + inFiltration >> size_in_this_dimension; + size_in_this_dimension = abs(size_in_this_dimension); + sizes.push_back( size_in_this_dimension ); + if (dbg){cerr << "size_in_this_dimension : " << size_in_this_dimension << endl;} + } + this->set_up_containers( sizes ); + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_begin(); + + //TODO -- over here we also need to read id's of cell and put them to bitmapElement structure! + while ( !inFiltration.eof() ) + { + double filtrationLevel; + inFiltration >> filtrationLevel; + if ( dbg ) + { + cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << endl; + } + *it = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); +} + + +template +std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const +{ + bool bdg = false; + //first of all, we need to take the list of coordinates in which the cell has nonzero length. + //We do it by using modified version to compute dimension of a cell: + std::vector< unsigned > dimensions_in_which_cell_has_nonzero_length; + unsigned dimension = 0; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/multipliers[i-1]; + if ( position%2 == 1 ) + { + dimensions_in_which_cell_has_nonzero_length.push_back(i-1); + dimension++; + } + cell1 = cell1%multipliers[i-1]; + } + + if (bdg) + { + cerr << "dimensions_in_which_cell_has_nonzero_length : \n"; + for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) + { + cerr << dimensions_in_which_cell_has_nonzero_length[i] << endl; + } + getchar(); + } + + std::vector< size_t > boundary_elements; + if ( dimensions_in_which_cell_has_nonzero_length.size() == 0 )return boundary_elements; + for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) + { + boundary_elements.push_back( cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + boundary_elements.push_back( cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + + if (bdg) cerr << "multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " + << multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; + if (bdg) cerr << "cell - multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " + << cell - multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; + if (bdg) cerr << "cell + multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " + << cell + multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; + } + return boundary_elements; +} + + + + +template +std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const +{ + bool bdg = false; + //first of all, we need to take the list of coordinates in which the cell has nonzero length. + //We do it by using modified version to compute dimension of a cell: + std::vector< unsigned > dimensions_in_which_cell_has_zero_length; + unsigned dimension = 0; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/multipliers[i-1]; + if ( position%2 == 0 ) + { + dimensions_in_which_cell_has_zero_length.push_back(i-1); + dimension++; + } + cell1 = cell1%multipliers[i-1]; + } + + std::vector counter = this->compute_counter_for_given_cell( cell ); + //reverse(counter.begin() , counter.end()); + + if (bdg) + { + cerr << "dimensions_in_which_cell_has_zero_length : \n"; + for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) + { + cerr << dimensions_in_which_cell_has_zero_length[i] << endl; + } + cerr << "\n counter : " << endl; + for ( size_t i = 0 ; i != counter.size() ; ++i ) + { + cerr << counter[i] << endl; + } + getchar(); + } + + std::vector< size_t > coboundary_elements; + if ( dimensions_in_which_cell_has_zero_length.size() == 0 )return coboundary_elements; + for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) + { + if ( bdg ) + { + cerr << "Dimension : " << i << endl; + if (counter[dimensions_in_which_cell_has_zero_length[i]] == 0) + { + cerr << "In dimension : " << i + << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + } + if ( counter[dimensions_in_which_cell_has_zero_length[i]] + == + 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) + { + cerr << "In dimension : " << i + << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; + } + } + + + if ( (cell > multipliers[dimensions_in_which_cell_has_zero_length[i]]) + && (counter[dimensions_in_which_cell_has_zero_length[i]] != 0) ) + //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != 0 ) + { + if ( bdg ) + { + cerr << "Subtracting : " << cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] << endl; + } + coboundary_elements.push_back( cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] ); + } + if ( + (cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && + (counter[dimensions_in_which_cell_has_zero_length[i]] + != + 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) + ) + //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != + //2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) + { + coboundary_elements.push_back( cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] ); + if ( bdg )cerr << "Adding : " << cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] << endl; + } + } + return coboundary_elements; +} + + + + + + +template +unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell( size_t cell )const +{ + bool dbg = false; + if (dbg)cerr << "\n\n\n Computing position o a cell of an index : " << cell << endl; + unsigned dimension = 0; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell/multipliers[i-1]; + + if (dbg)cerr << "i-1 :" << i-1 << endl; + if (dbg)cerr << "cell : " << cell << endl; + if (dbg)cerr << "position : " << position << endl; + if (dbg)cerr << "multipliers["< +T& Bitmap_cubical_complex_base::get_cell_data( size_t cell ) +{ + return this->data[cell]; +} + + +template +void Bitmap_cubical_complex_base::impose_lower_star_filtration() +{ + bool dbg = false; + + //this vector will be used to check which elements have already been taken care of + //in imposing lower star filtration: + std::vector is_this_cell_considered( this->data.size() , false ); + + std::vector indices_to_consider; + //we assume here that we already have a filtration on the top dimensional cells and + //we have to extend it to lower ones. + typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + indices_to_consider.push_back( it.compute_index_in_bitmap() ); + } + + while ( indices_to_consider.size() ) + { + if ( dbg ) + { + cerr << "indices_to_consider in this iteration \n"; + for ( size_t i = 0 ; i != indices_to_consider.size() ; ++i ) + { + cout << indices_to_consider[i] << " "; + } + getchar(); + } + std::vector new_indices_to_consider; + for ( size_t i = 0 ; i != indices_to_consider.size() ; ++i ) + { + std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); + for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) + { + if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) + { + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + } + if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) + { + new_indices_to_consider.push_back( bd[boundaryIt] ); + is_this_cell_considered[ bd[boundaryIt] ] = true; + } + } + } + indices_to_consider.swap(new_indices_to_consider); + } +} + + +template +bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , char >& first , + const std::pair< std::pair< T , size_t > , char >& second ) +{ + if ( first.first.first < second.first.first ) + { + return true; + } + else + { + if ( first.first.first > second.first.first ) + { + return false; + } + //in this case first.first.first == second.first.first, so we need to compare dimensions + return first.second < second.second; + } +} + + + +template +std::vector< size_t > Bitmap_cubical_complex_base:: +generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions +( std::vector< bool >& directions_for_periodic_b_cond ) +{ + bool dbg = false; + if ( this->sizes.size() != directions_for_periodic_b_cond.size() ) + throw "directions_for_periodic_b_cond vector size is different from the size of the bitmap. Program terminate \n"; + + std::vector sizes( this->sizes.size() ); + for ( size_t i = 0 ; i != this->sizes.size() ; ++i )sizes[i] = 2*this->sizes[i]; + + counter c( sizes ); + + std::vector< size_t > result; + + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + size_t position; + if ( !c.isFinal() ) + { + position = i; + //result.push_back( i ); + } + else + { + std::vector< bool > finals = c.directions_of_finals(); + bool jump_in_position = false; + for ( size_t dir = 0 ; dir != finals.size() ; ++dir ) + { + if ( finals[dir] == false )continue; + if ( directions_for_periodic_b_cond[dir] ) + { + jump_in_position = true; + } + } + if ( jump_in_position == true ) + { + //in this case this guy is final, so we need to find 'the opposite one' + position = compute_position_in_bitmap( c.find_opposite( directions_for_periodic_b_cond ) ); + } + else + { + position = i; + } + } + result.push_back( position ); + if ( dbg ) + { + cerr << " position : " << position << endl; + cerr << c << endl; + getchar(); + } + + c.increment(); + } + + return result; +} + +} + +} \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/counter.h b/src/Bitmap_cubical_complex/include/gudhi/counter.h index 9445a422..a5fda36f 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/counter.h @@ -1,139 +1,177 @@ -/* 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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-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 COUNTER_H_ -#define COUNTER_H_ - -#include -#include - -/** - * This is an implementation of a simple counter. It is needed for the implementation of a bitmapCubicalComplex. - **/ - -class counter { - public: - /** - * Constructor of a counter class. It takes only the parameter which is the end value of the counter. - * The default beginning value is a vector of the same length as the end, filled-in with zeros. - **/ - counter(std::vector< int > endd) { - for (size_t i = 0; i != endd.size(); ++i) { - this->current.push_back(0); - this->begin.push_back(0); - this->end.push_back(endd[i]); - } - } - - /** - * Constructor of a counter class. It takes as the input beginn and endd vector. It assumes that begin vector is - * lexicographically below the end vector. - **/ - counter(std::vector< int > beginn, std::vector< int > endd) { - if (beginn.size() != endd.size()) - throw("In constructor of a counter, begin and end vectors do not have the same size. Program terminate"); - for (size_t i = 0; i != endd.size(); ++i) { - this->current.push_back(0); - this->begin.push_back(0); - this->end.push_back(endd[i]); - } - } - - /** - * Function to increment the counter. If the value returned by the function is true, then the incrementation process - * was successful. - * If the value of the function is false, that means, that the counter have reached its end-value. - **/ - bool increment() { - size_t i = 0; - while ((i != this->end.size()) && (this->current[i] == this->end[i])) { - ++i; - } - - if (i == this->end.size())return false; - ++this->current[i]; - for (size_t j = 0; j != i; ++j) { - this->current[j] = this->begin[j]; - } - return true; - } - - /** - * Function to check if we are at the end of counter. - **/ - bool isFinal() { - for (size_t i = 0; i != this->current.size(); ++i) { - if (this->current[i] == this->end[i])return true; - } - return false; - } - - /** - * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. - * Its aim is to find an counter corresponding to the element the following boundary element is identified with - * when periodic boundary conditions are imposed. - **/ - std::vector< int > findOpposite(std::vector< bool > directionsForPeriodicBCond) { - std::vector< int > result; - for (size_t i = 0; i != this->current.size(); ++i) { - if ((this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true)) { - result.push_back(this->begin[i]); - } else { - result.push_back(this->current[i]); - } - } - return result; - } - - /** - * Function checking at which positions the current value of a counter is the final value of the counter. - **/ - std::vector< bool > directionsOfFinals() { - std::vector< bool > result; - for (size_t i = 0; i != this->current.size(); ++i) { - if (this->current[i] == this->end[i]) { - result.push_back(true); - } else { - result.push_back(false); - } - } - return result; - } - - /** - * Function to write counter to the stream. - **/ - friend std::ostream& operator<<(std::ostream& out, const counter& c) { - // std::cerr << "c.current.size() : " << c.current.size() << std::endl; - for (size_t i = 0; i != c.current.size(); ++i) { - out << c.current[i] << " "; - } - return out; - } - - private: - std::vector< int > begin; - std::vector< int > end; - std::vector< int > current; -}; - -#endif // COUNTER_H_ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 . + */ + +#pragma once + +#include +#include + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +/** +* This is an implementation of a counter being a vector of integers. +* The constructor of the class takes as an input two vectors W and V. +* It assumes that W < V coordinatewise. +* If the initial counter W is not specified, it is assumed to be vector of zeros. +* The class allows to iterate between W and V by using increment() function. +* The increment() function returns a bool value. +* The current counter reach the end counter V if the value returned by the increment function is FALSE. +* This class is needed for the implementation of a bitmapCubicalComplex. +**/ + +class counter +{ +public: + /** + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. + * The default beginning value is a vector of the same length as the endd, filled-in with zeros. + **/ + counter(std::vector const& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} + //counter(std::vector< int >& endd) + //{ + // for ( size_t i = 0 ; i != endd.size() ; ++i ) + // { + // this->current.push_back(0); + // this->begin.push_back(0); + // this->end.push_back( endd[i] ); + // } + //} + + + /** + * Constructor of a counter class. It takes as the input beginn and end vector. + * It assumes that begin vector is lexicographically below the end vector. + **/ + counter(std::vector< unsigned >& beginn , std::vector< unsigned >& endd) + { + if ( beginn.size() != endd.size() ) + throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + for ( size_t i = 0 ; i != endd.size() ; ++i ) + { + this->current.push_back(0); + this->begin.push_back(0); + this->end.push_back( endd[i] ); + } + } + + /** + * Function to increment the counter. If the value returned by the function is true, + * then the incrementation process was successful. + * If the value of the function is false, that means, that the counter have reached its end-value. + **/ + bool increment() + { + size_t i = 0; + while( (i != this->end.size()) && (this->current[i] == this->end[i]) ) + { + ++i; + } + + if ( i == this->end.size() )return false; + ++this->current[i]; + for ( size_t j = 0 ; j != i ; ++j ) + { + this->current[j] = this->begin[j]; + } + return true; + } + + /** + * Function to check if we are at the end of counter. + **/ + bool isFinal() + { + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( this->current[i] == this->end[i] )return true; + } + return false; + } + + /** + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. + * Its aim is to find an counter corresponding to the element the following + * boundary element is identified with when periodic boundary conditions are imposed. + **/ + std::vector< unsigned > find_opposite( std::vector< bool >& directionsForPeriodicBCond ) + { + std::vector< unsigned > result; + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( (this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true) ) + { + result.push_back( this->begin[i] ); + } + else + { + result.push_back( this->current[i] ); + } + } + return result; + } + + /** + * Function checking at which positions the current value of a counter is the final value of the counter. + **/ + std::vector< bool > directions_of_finals() + { + std::vector< bool > result; + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( this->current[i] == this->end[i] ) + { + result.push_back( true ); + } + else + { + result.push_back( false ); + } + } + return result; + } + + /** + * Function to write counter to the stream. + **/ + friend std::ostream& operator<<(std::ostream& out , const counter& c ) + { + //cerr << "c.current.size() : " << c.current.size() << endl; + for ( size_t i = 0 ; i != c.current.size() ; ++i ) + { + out << c.current[i] << " "; + } + return out; + } +private: + std::vector< unsigned > begin; + std::vector< unsigned > end; + std::vector< unsigned > current; +}; + +} +} \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 1c204bae..183b856a 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -1,623 +1,638 @@ -#include "gudhi/Bitmap_cubical_complex.h" - -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "cubical_complex" -#include - -using namespace std; - -BOOST_AUTO_TEST_CASE(check_dimension) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - BOOST_CHECK(increasing.dimension() == 2); -} - -BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { - std::vector< double > expectedFiltrationValues1; - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(100); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - - std::vector< double > expectedFiltrationValues2; - expectedFiltrationValues2.push_back(1); - expectedFiltrationValues2.push_back(2); - expectedFiltrationValues2.push_back(3); - expectedFiltrationValues2.push_back(4); - expectedFiltrationValues2.push_back(5); - expectedFiltrationValues2.push_back(6); - expectedFiltrationValues2.push_back(7); - expectedFiltrationValues2.push_back(8); - expectedFiltrationValues2.push_back(9); - - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector< double > oneDimensionalCycle; - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(100); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); - - - int i = 0; - for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { - BOOST_CHECK(*it == expectedFiltrationValues2[i]); - ++i; - } - i = 0; - for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { - BOOST_CHECK(*it == expectedFiltrationValues1[i]); - ++i; - } -} - -BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { - - std::vector boundary0; - std::vector boundary1; - boundary1.push_back(0); - boundary1.push_back(2); - std::vector boundary2; - std::vector boundary3; - boundary3.push_back(2); - boundary3.push_back(4); - std::vector boundary4; - std::vector boundary5; - boundary5.push_back(4); - boundary5.push_back(6); - std::vector boundary6; - std::vector boundary7; - boundary7.push_back(0); - boundary7.push_back(14); - std::vector boundary8; - boundary8.push_back(1); - boundary8.push_back(15); - boundary8.push_back(7); - boundary8.push_back(9); - std::vector boundary9; - boundary9.push_back(2); - boundary9.push_back(16); - std::vector boundary10; - boundary10.push_back(3); - boundary10.push_back(17); - boundary10.push_back(9); - boundary10.push_back(11); - std::vector boundary11; - boundary11.push_back(4); - boundary11.push_back(18); - std::vector boundary12; - boundary12.push_back(5); - boundary12.push_back(19); - boundary12.push_back(11); - boundary12.push_back(13); - std::vector boundary13; - boundary13.push_back(6); - boundary13.push_back(20); - std::vector boundary14; - std::vector boundary15; - boundary15.push_back(14); - boundary15.push_back(16); - std::vector boundary16; - std::vector boundary17; - boundary17.push_back(16); - boundary17.push_back(18); - std::vector boundary18; - std::vector boundary19; - boundary19.push_back(18); - boundary19.push_back(20); - std::vector boundary20; - std::vector boundary21; - boundary21.push_back(14); - boundary21.push_back(28); - std::vector boundary22; - boundary22.push_back(15); - boundary22.push_back(29); - boundary22.push_back(21); - boundary22.push_back(23); - std::vector boundary23; - boundary23.push_back(16); - boundary23.push_back(30); - std::vector boundary24; - boundary24.push_back(17); - boundary24.push_back(31); - boundary24.push_back(23); - boundary24.push_back(25); - std::vector boundary25; - boundary25.push_back(18); - boundary25.push_back(32); - std::vector boundary26; - boundary26.push_back(19); - boundary26.push_back(33); - boundary26.push_back(25); - boundary26.push_back(27); - std::vector boundary27; - boundary27.push_back(20); - boundary27.push_back(34); - std::vector boundary28; - std::vector boundary29; - boundary29.push_back(28); - boundary29.push_back(30); - std::vector boundary30; - std::vector boundary31; - boundary31.push_back(30); - boundary31.push_back(32); - std::vector boundary32; - std::vector boundary33; - boundary33.push_back(32); - boundary33.push_back(34); - std::vector boundary34; - std::vector boundary35; - boundary35.push_back(28); - boundary35.push_back(42); - std::vector boundary36; - boundary36.push_back(29); - boundary36.push_back(43); - boundary36.push_back(35); - boundary36.push_back(37); - std::vector boundary37; - boundary37.push_back(30); - boundary37.push_back(44); - std::vector boundary38; - boundary38.push_back(31); - boundary38.push_back(45); - boundary38.push_back(37); - boundary38.push_back(39); - std::vector boundary39; - boundary39.push_back(32); - boundary39.push_back(46); - std::vector boundary40; - boundary40.push_back(33); - boundary40.push_back(47); - boundary40.push_back(39); - boundary40.push_back(41); - std::vector boundary41; - boundary41.push_back(34); - boundary41.push_back(48); - std::vector boundary42; - std::vector boundary43; - boundary43.push_back(42); - boundary43.push_back(44); - std::vector boundary44; - std::vector boundary45; - boundary45.push_back(44); - boundary45.push_back(46); - std::vector boundary46; - std::vector boundary47; - boundary47.push_back(46); - boundary47.push_back(48); - std::vector boundary48; - std::vector< std::vector > boundaries; - boundaries.push_back(boundary0); - boundaries.push_back(boundary1); - boundaries.push_back(boundary2); - boundaries.push_back(boundary3); - boundaries.push_back(boundary4); - boundaries.push_back(boundary5); - boundaries.push_back(boundary6); - boundaries.push_back(boundary7); - boundaries.push_back(boundary8); - boundaries.push_back(boundary9); - boundaries.push_back(boundary10); - boundaries.push_back(boundary11); - boundaries.push_back(boundary12); - boundaries.push_back(boundary13); - boundaries.push_back(boundary14); - boundaries.push_back(boundary15); - boundaries.push_back(boundary16); - boundaries.push_back(boundary17); - boundaries.push_back(boundary18); - boundaries.push_back(boundary19); - boundaries.push_back(boundary20); - boundaries.push_back(boundary21); - boundaries.push_back(boundary22); - boundaries.push_back(boundary23); - boundaries.push_back(boundary24); - boundaries.push_back(boundary25); - boundaries.push_back(boundary26); - boundaries.push_back(boundary27); - boundaries.push_back(boundary28); - boundaries.push_back(boundary29); - boundaries.push_back(boundary30); - boundaries.push_back(boundary31); - boundaries.push_back(boundary32); - boundaries.push_back(boundary33); - boundaries.push_back(boundary34); - boundaries.push_back(boundary35); - boundaries.push_back(boundary36); - boundaries.push_back(boundary37); - boundaries.push_back(boundary38); - boundaries.push_back(boundary39); - boundaries.push_back(boundary40); - boundaries.push_back(boundary41); - boundaries.push_back(boundary42); - boundaries.push_back(boundary43); - boundaries.push_back(boundary44); - boundaries.push_back(boundary45); - boundaries.push_back(boundary46); - boundaries.push_back(boundary47); - boundaries.push_back(boundary48); - - - - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { - std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); - for (size_t j = 0; j != bd.size(); ++j) { - BOOST_CHECK(boundaries[i][j] == bd[j]); - } - } -} - -BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - - - std::vector coboundaryElements; - coboundaryElements.push_back(7); - coboundaryElements.push_back(1); - coboundaryElements.push_back(8); - coboundaryElements.push_back(9); - coboundaryElements.push_back(1); - coboundaryElements.push_back(3); - coboundaryElements.push_back(10); - coboundaryElements.push_back(11); - coboundaryElements.push_back(3); - coboundaryElements.push_back(5); - coboundaryElements.push_back(12); - coboundaryElements.push_back(13); - coboundaryElements.push_back(5); - coboundaryElements.push_back(8); - coboundaryElements.push_back(8); - coboundaryElements.push_back(10); - coboundaryElements.push_back(10); - coboundaryElements.push_back(12); - coboundaryElements.push_back(12); - coboundaryElements.push_back(7); - coboundaryElements.push_back(21); - coboundaryElements.push_back(15); - coboundaryElements.push_back(8); - coboundaryElements.push_back(22); - coboundaryElements.push_back(9); - coboundaryElements.push_back(23); - coboundaryElements.push_back(15); - coboundaryElements.push_back(17); - coboundaryElements.push_back(10); - coboundaryElements.push_back(24); - coboundaryElements.push_back(11); - coboundaryElements.push_back(25); - coboundaryElements.push_back(17); - coboundaryElements.push_back(19); - coboundaryElements.push_back(12); - coboundaryElements.push_back(26); - coboundaryElements.push_back(13); - coboundaryElements.push_back(27); - coboundaryElements.push_back(19); - coboundaryElements.push_back(22); - coboundaryElements.push_back(22); - coboundaryElements.push_back(24); - coboundaryElements.push_back(24); - coboundaryElements.push_back(26); - coboundaryElements.push_back(26); - coboundaryElements.push_back(21); - coboundaryElements.push_back(35); - coboundaryElements.push_back(29); - coboundaryElements.push_back(22); - coboundaryElements.push_back(36); - coboundaryElements.push_back(23); - coboundaryElements.push_back(37); - coboundaryElements.push_back(29); - coboundaryElements.push_back(31); - coboundaryElements.push_back(24); - coboundaryElements.push_back(38); - coboundaryElements.push_back(25); - coboundaryElements.push_back(39); - coboundaryElements.push_back(31); - coboundaryElements.push_back(33); - coboundaryElements.push_back(26); - coboundaryElements.push_back(40); - coboundaryElements.push_back(27); - coboundaryElements.push_back(41); - coboundaryElements.push_back(33); - coboundaryElements.push_back(36); - coboundaryElements.push_back(36); - coboundaryElements.push_back(38); - coboundaryElements.push_back(38); - coboundaryElements.push_back(40); - coboundaryElements.push_back(40); - coboundaryElements.push_back(35); - coboundaryElements.push_back(43); - coboundaryElements.push_back(36); - coboundaryElements.push_back(37); - coboundaryElements.push_back(43); - coboundaryElements.push_back(45); - coboundaryElements.push_back(38); - coboundaryElements.push_back(39); - coboundaryElements.push_back(45); - coboundaryElements.push_back(47); - coboundaryElements.push_back(40); - coboundaryElements.push_back(41); - coboundaryElements.push_back(47); - size_t number = 0; - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { - std::vector< size_t > bd = increasing.get_coboundary_of_a_cell(i); - for (size_t j = 0; j != bd.size(); ++j) { - BOOST_CHECK(coboundaryElements[number] == bd[j]); - ++number; - } - - } -} - -BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - - std::vector dim; - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(2); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - dim.push_back(1); - dim.push_back(0); - - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { - BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]); - } -} - -BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - - std::vector< unsigned > dim; - dim.push_back(0); - dim.push_back(0); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - dim.push_back(0); - dim.push_back(1); - dim.push_back(1); - dim.push_back(2); - - std::vector fil; - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(1); - fil.push_back(2); - fil.push_back(2); - fil.push_back(2); - fil.push_back(2); - fil.push_back(2); - fil.push_back(2); - fil.push_back(3); - fil.push_back(3); - fil.push_back(3); - fil.push_back(3); - fil.push_back(3); - fil.push_back(3); - fil.push_back(4); - fil.push_back(4); - fil.push_back(4); - fil.push_back(4); - fil.push_back(4); - fil.push_back(4); - fil.push_back(5); - fil.push_back(5); - fil.push_back(5); - fil.push_back(5); - fil.push_back(6); - fil.push_back(6); - fil.push_back(6); - fil.push_back(6); - fil.push_back(7); - fil.push_back(7); - fil.push_back(7); - fil.push_back(7); - fil.push_back(7); - fil.push_back(7); - fil.push_back(8); - fil.push_back(8); - fil.push_back(8); - fil.push_back(8); - fil.push_back(9); - fil.push_back(9); - fil.push_back(9); - fil.push_back(9); - - - Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); - size_t position = 0; - for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { - BOOST_CHECK(increasing.dimension(*it) == dim[position]); - BOOST_CHECK(increasing.filtration(*it) == fil[position]); - ++position; - } -} +#include +#include +#include +#include + +// standard stuff +#include +#include + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "cubical_complex" +#include + + +using namespace std; +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + + + +BOOST_AUTO_TEST_CASE(check_dimension) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + BOOST_CHECK(increasing.dimension() == 2); +} + +BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { + std::vector< double > expectedFiltrationValues1; + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(100); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + expectedFiltrationValues1.push_back(0); + + std::vector< double > expectedFiltrationValues2; + expectedFiltrationValues2.push_back(1); + expectedFiltrationValues2.push_back(2); + expectedFiltrationValues2.push_back(3); + expectedFiltrationValues2.push_back(4); + expectedFiltrationValues2.push_back(5); + expectedFiltrationValues2.push_back(6); + expectedFiltrationValues2.push_back(7); + expectedFiltrationValues2.push_back(8); + expectedFiltrationValues2.push_back(9); + + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector< double > oneDimensionalCycle; + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(100); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + oneDimensionalCycle.push_back(0); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); + + + int i = 0; + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator + it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { + BOOST_CHECK(*it == expectedFiltrationValues2[i]); + ++i; + } + i = 0; + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator + it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { + BOOST_CHECK(*it == expectedFiltrationValues1[i]); + ++i; + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { + + std::vector boundary0; + std::vector boundary1; + boundary1.push_back(0); + boundary1.push_back(2); + std::vector boundary2; + std::vector boundary3; + boundary3.push_back(2); + boundary3.push_back(4); + std::vector boundary4; + std::vector boundary5; + boundary5.push_back(4); + boundary5.push_back(6); + std::vector boundary6; + std::vector boundary7; + boundary7.push_back(0); + boundary7.push_back(14); + std::vector boundary8; + boundary8.push_back(1); + boundary8.push_back(15); + boundary8.push_back(7); + boundary8.push_back(9); + std::vector boundary9; + boundary9.push_back(2); + boundary9.push_back(16); + std::vector boundary10; + boundary10.push_back(3); + boundary10.push_back(17); + boundary10.push_back(9); + boundary10.push_back(11); + std::vector boundary11; + boundary11.push_back(4); + boundary11.push_back(18); + std::vector boundary12; + boundary12.push_back(5); + boundary12.push_back(19); + boundary12.push_back(11); + boundary12.push_back(13); + std::vector boundary13; + boundary13.push_back(6); + boundary13.push_back(20); + std::vector boundary14; + std::vector boundary15; + boundary15.push_back(14); + boundary15.push_back(16); + std::vector boundary16; + std::vector boundary17; + boundary17.push_back(16); + boundary17.push_back(18); + std::vector boundary18; + std::vector boundary19; + boundary19.push_back(18); + boundary19.push_back(20); + std::vector boundary20; + std::vector boundary21; + boundary21.push_back(14); + boundary21.push_back(28); + std::vector boundary22; + boundary22.push_back(15); + boundary22.push_back(29); + boundary22.push_back(21); + boundary22.push_back(23); + std::vector boundary23; + boundary23.push_back(16); + boundary23.push_back(30); + std::vector boundary24; + boundary24.push_back(17); + boundary24.push_back(31); + boundary24.push_back(23); + boundary24.push_back(25); + std::vector boundary25; + boundary25.push_back(18); + boundary25.push_back(32); + std::vector boundary26; + boundary26.push_back(19); + boundary26.push_back(33); + boundary26.push_back(25); + boundary26.push_back(27); + std::vector boundary27; + boundary27.push_back(20); + boundary27.push_back(34); + std::vector boundary28; + std::vector boundary29; + boundary29.push_back(28); + boundary29.push_back(30); + std::vector boundary30; + std::vector boundary31; + boundary31.push_back(30); + boundary31.push_back(32); + std::vector boundary32; + std::vector boundary33; + boundary33.push_back(32); + boundary33.push_back(34); + std::vector boundary34; + std::vector boundary35; + boundary35.push_back(28); + boundary35.push_back(42); + std::vector boundary36; + boundary36.push_back(29); + boundary36.push_back(43); + boundary36.push_back(35); + boundary36.push_back(37); + std::vector boundary37; + boundary37.push_back(30); + boundary37.push_back(44); + std::vector boundary38; + boundary38.push_back(31); + boundary38.push_back(45); + boundary38.push_back(37); + boundary38.push_back(39); + std::vector boundary39; + boundary39.push_back(32); + boundary39.push_back(46); + std::vector boundary40; + boundary40.push_back(33); + boundary40.push_back(47); + boundary40.push_back(39); + boundary40.push_back(41); + std::vector boundary41; + boundary41.push_back(34); + boundary41.push_back(48); + std::vector boundary42; + std::vector boundary43; + boundary43.push_back(42); + boundary43.push_back(44); + std::vector boundary44; + std::vector boundary45; + boundary45.push_back(44); + boundary45.push_back(46); + std::vector boundary46; + std::vector boundary47; + boundary47.push_back(46); + boundary47.push_back(48); + std::vector boundary48; + std::vector< std::vector > boundaries; + boundaries.push_back(boundary0); + boundaries.push_back(boundary1); + boundaries.push_back(boundary2); + boundaries.push_back(boundary3); + boundaries.push_back(boundary4); + boundaries.push_back(boundary5); + boundaries.push_back(boundary6); + boundaries.push_back(boundary7); + boundaries.push_back(boundary8); + boundaries.push_back(boundary9); + boundaries.push_back(boundary10); + boundaries.push_back(boundary11); + boundaries.push_back(boundary12); + boundaries.push_back(boundary13); + boundaries.push_back(boundary14); + boundaries.push_back(boundary15); + boundaries.push_back(boundary16); + boundaries.push_back(boundary17); + boundaries.push_back(boundary18); + boundaries.push_back(boundary19); + boundaries.push_back(boundary20); + boundaries.push_back(boundary21); + boundaries.push_back(boundary22); + boundaries.push_back(boundary23); + boundaries.push_back(boundary24); + boundaries.push_back(boundary25); + boundaries.push_back(boundary26); + boundaries.push_back(boundary27); + boundaries.push_back(boundary28); + boundaries.push_back(boundary29); + boundaries.push_back(boundary30); + boundaries.push_back(boundary31); + boundaries.push_back(boundary32); + boundaries.push_back(boundary33); + boundaries.push_back(boundary34); + boundaries.push_back(boundary35); + boundaries.push_back(boundary36); + boundaries.push_back(boundary37); + boundaries.push_back(boundary38); + boundaries.push_back(boundary39); + boundaries.push_back(boundary40); + boundaries.push_back(boundary41); + boundaries.push_back(boundary42); + boundaries.push_back(boundary43); + boundaries.push_back(boundary44); + boundaries.push_back(boundary45); + boundaries.push_back(boundary46); + boundaries.push_back(boundary47); + boundaries.push_back(boundary48); + + + + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(boundaries[i][j] == bd[j]); + } + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + + std::vector coboundaryElements; + coboundaryElements.push_back(7); + coboundaryElements.push_back(1); + coboundaryElements.push_back(8); + coboundaryElements.push_back(9); + coboundaryElements.push_back(1); + coboundaryElements.push_back(3); + coboundaryElements.push_back(10); + coboundaryElements.push_back(11); + coboundaryElements.push_back(3); + coboundaryElements.push_back(5); + coboundaryElements.push_back(12); + coboundaryElements.push_back(13); + coboundaryElements.push_back(5); + coboundaryElements.push_back(8); + coboundaryElements.push_back(8); + coboundaryElements.push_back(10); + coboundaryElements.push_back(10); + coboundaryElements.push_back(12); + coboundaryElements.push_back(12); + coboundaryElements.push_back(7); + coboundaryElements.push_back(21); + coboundaryElements.push_back(15); + coboundaryElements.push_back(8); + coboundaryElements.push_back(22); + coboundaryElements.push_back(9); + coboundaryElements.push_back(23); + coboundaryElements.push_back(15); + coboundaryElements.push_back(17); + coboundaryElements.push_back(10); + coboundaryElements.push_back(24); + coboundaryElements.push_back(11); + coboundaryElements.push_back(25); + coboundaryElements.push_back(17); + coboundaryElements.push_back(19); + coboundaryElements.push_back(12); + coboundaryElements.push_back(26); + coboundaryElements.push_back(13); + coboundaryElements.push_back(27); + coboundaryElements.push_back(19); + coboundaryElements.push_back(22); + coboundaryElements.push_back(22); + coboundaryElements.push_back(24); + coboundaryElements.push_back(24); + coboundaryElements.push_back(26); + coboundaryElements.push_back(26); + coboundaryElements.push_back(21); + coboundaryElements.push_back(35); + coboundaryElements.push_back(29); + coboundaryElements.push_back(22); + coboundaryElements.push_back(36); + coboundaryElements.push_back(23); + coboundaryElements.push_back(37); + coboundaryElements.push_back(29); + coboundaryElements.push_back(31); + coboundaryElements.push_back(24); + coboundaryElements.push_back(38); + coboundaryElements.push_back(25); + coboundaryElements.push_back(39); + coboundaryElements.push_back(31); + coboundaryElements.push_back(33); + coboundaryElements.push_back(26); + coboundaryElements.push_back(40); + coboundaryElements.push_back(27); + coboundaryElements.push_back(41); + coboundaryElements.push_back(33); + coboundaryElements.push_back(36); + coboundaryElements.push_back(36); + coboundaryElements.push_back(38); + coboundaryElements.push_back(38); + coboundaryElements.push_back(40); + coboundaryElements.push_back(40); + coboundaryElements.push_back(35); + coboundaryElements.push_back(43); + coboundaryElements.push_back(36); + coboundaryElements.push_back(37); + coboundaryElements.push_back(43); + coboundaryElements.push_back(45); + coboundaryElements.push_back(38); + coboundaryElements.push_back(39); + coboundaryElements.push_back(45); + coboundaryElements.push_back(47); + coboundaryElements.push_back(40); + coboundaryElements.push_back(41); + coboundaryElements.push_back(47); + size_t number = 0; + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + std::vector< size_t > bd = increasing.get_coboundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(coboundaryElements[number] == bd[j]); + ++number; + } + + } +} + +BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + std::vector dim; + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(2); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + dim.push_back(1); + dim.push_back(0); + + for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]); + } +} + +BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { + std::vector< double > increasingFiltrationOfTopDimensionalCells; + increasingFiltrationOfTopDimensionalCells.push_back(1); + increasingFiltrationOfTopDimensionalCells.push_back(2); + increasingFiltrationOfTopDimensionalCells.push_back(3); + increasingFiltrationOfTopDimensionalCells.push_back(4); + increasingFiltrationOfTopDimensionalCells.push_back(5); + increasingFiltrationOfTopDimensionalCells.push_back(6); + increasingFiltrationOfTopDimensionalCells.push_back(7); + increasingFiltrationOfTopDimensionalCells.push_back(8); + increasingFiltrationOfTopDimensionalCells.push_back(9); + + std::vector dimensions; + dimensions.push_back(3); + dimensions.push_back(3); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + + std::vector< unsigned > dim; + dim.push_back(0); + dim.push_back(0); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + dim.push_back(0); + dim.push_back(1); + dim.push_back(1); + dim.push_back(2); + + std::vector fil; + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(1); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(2); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(3); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(4); + fil.push_back(5); + fil.push_back(5); + fil.push_back(5); + fil.push_back(5); + fil.push_back(6); + fil.push_back(6); + fil.push_back(6); + fil.push_back(6); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(7); + fil.push_back(8); + fil.push_back(8); + fil.push_back(8); + fil.push_back(8); + fil.push_back(9); + fil.push_back(9); + fil.push_back(9); + fil.push_back(9); + + + Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); + size_t position = 0; + for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { + BOOST_CHECK(increasing.dimension(*it) == dim[position]); + BOOST_CHECK(increasing.filtration(*it) == fil[position]); + ++position; + } +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a66d90b6..2ef89f84 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,10 +44,10 @@ else() # Gudhi compilation part include_directories(include) - add_subdirectory(example/Simplex_tree) - add_subdirectory(example/Persistent_cohomology) - add_subdirectory(example/Skeleton_blocker) - add_subdirectory(example/Contraction) + #add_subdirectory(example/Simplex_tree) + #add_subdirectory(example/Persistent_cohomology) + #add_subdirectory(example/Skeleton_blocker) + #add_subdirectory(example/Contraction) add_subdirectory(example/Bitmap_cubical_complex) # data points generator -- 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 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 d9f8f2d006c1c57c05eeb6eddbc625e44ebd8831 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 11 Dec 2015 10:11:32 +0000 Subject: Adding corecntions suggested by the Editorial Board to the Bitmap_cubical_complex class. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@942 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 81338409d0c6dc3435474f08f499dd5b72812ad6 --- .../doc/Gudhi_Cubical_Complex_doc.h | 106 +++++ src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf | Bin 0 -> 13940 bytes src/Bitmap_cubical_complex/doc/exampleBitmap.pdf | Bin 0 -> 11122 bytes .../example/Bitmap_cubical_complex.cpp | 5 +- .../include/gudhi/Bitmap_cubical_complex.h | 455 +++++++-------------- .../include/gudhi/Bitmap_cubical_complex/counter.h | 171 ++++++++ .../include/gudhi/Bitmap_cubical_complex_base.h | 22 +- src/Bitmap_cubical_complex/include/gudhi/counter.h | 177 -------- 8 files changed, 440 insertions(+), 496 deletions(-) create mode 100644 src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h create mode 100644 src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf create mode 100644 src/Bitmap_cubical_complex/doc/exampleBitmap.pdf create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/counter.h diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h new file mode 100644 index 00000000..4acf2b3a --- /dev/null +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -0,0 +1,106 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 . + */ + + +#pragma once + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +/** \defgroup cubical_complex Cubical complex +* +* \author Pawel Dlotko +* +* @{ +* + +*Cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. +* +* An \emph{elementary interval} is an interval of a form $[n,n+1]$, or $[n,n]$, for $n \in \mathcal{Z}$. The first one is called \emph{non-degenerated}, while the second one is \emph{degenerated} interval. A \emph{boundary of a elementary +*interval} is a chain $\partial [n,n+1] = [n+1,n+1]-[n,n]$ in case of non-degenerated elementary interval and $\partial [n,n] = 0$ in case of degenerated elementary interval. An \emph{elementary cube} $C$ is a +*product of elementary intervals, $C=I_1 \times \ldots \times I_n$. \emph{Embedding dimension} of a cube is n, the number of elementary intervals (degenerated or not) in the product. A \emph{dimension of a cube} $C=I_1 \times ... \times I_n$ is the +*number of non degenerated elementary intervals in the product. A \emph{boundary of a cube} $C=I_1 \times \ldots \times I_n$ is a chain obtained in the following way: +*\[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\] +*A \emph{cubical complex} $\mathcal{K}$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube $C$ in cubical complex $\mathcal{K}$ is \emph{maximal} if it is not in +*a boundary of any other cube in $\mathcal{K}$. A \emph{support} of a cube $C$ is the set in $\mathbb{R}^n$ occupied by $C$ ($n$ is the embedding dimension of $C$). +* +*Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may be a set of two elements). +* +*For further details and theory of cubical complexes, please consult a book:\\ +*Computational homology, by Tomasz Kaczynski, Konstantin Mischaikow, and Marion Mrozek, Appl. Math. Sci., vol. 157, Springer-Verlag, New York, 2004 +* +*as well as the paper: +*Efficient computation of persistent homology for cubical data by Hubert Wagner, Chao Chen, Erald Vuçini (published in the proceedings of Workshop on Topology-based Methods in Data +*Analysis and Visualization) +* +*\section{Data structure.} +* +*The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in $\mathbb{R}^n$. This extra +*assumption allows for a memory efficient way of storing cubical complexes in a form of so called bitmaps. Let $R = [b_1,e_1] \times \ldots \times [b_n,e_n]$, for $b_1,...b_n,e_1,...,e_n \in \mathbb{Z}$ +*, $b_i \leq d_i$ be the considered rectangular region and let $\mathcal{K}$ be a filtered cubical complex having the rectangle $R$ as its support. Note that the structure of the coordinate system gives a way +*a lexicographical ordering of cells of $\mathcal{K}$. This ordering is a base of the presented bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector +*of the values of filtration. This, together with dimension of $\mathcal{K}$ and the sizes of $\mathcal{K}$ in all directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube $C \in \mathcal{K}$. +* +*\image html "bitmapAllCubes.pdf" "Cubical complex in $\mathbb{R}^2". +* +*Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical complexes in $\mathbb{R}$. The number of all cubes in each direction is +*equal $2n+1$, where $n$ is the number of maximal cubes in the considered direction. Let us consider a cube at the position $k$ in the bitmap. Knowing the sizes of the bitmap, +*by a series of modulo operation, we can determine which elementary intervals are present in the product that gives the cube $C$. In a similar way, we can compute boundary +*and the coboundary of each cube. Further details can be found in the literature. +* +*\section{Input Format.} +* +*In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors +*that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \emph{Bitmap\_cubical\_complex} class. +*Currently one input from a text file is used. It uses a format used already in Perseus software $(http://www.sas.upenn.edu/~vnanda/perseus/)$ by Vidit Nanda. +*Below we are providing a description of the format. +* +*\begin{enumerate} +*\item The first line of the file is $d$, the embedding dimension of a complex. +*\item The next $d$ lines consist of positive numbers being the numbers of top dimensional cubes in the given direction. Let us call those numbers $n_1,\ldots,n_d$. +*\item Later there is a sequence of $n_1 \dot \ldots \dot n_d$ numbers in a lexicographical ordering. Those numbers are filtrations of top dimensional cubes. +*\end{enumerate} +* +*\image html "exampleBitmap.pdf" "Example of a input data." +* +*The input file for the following complex is: +*\begin{verbatim} +*2 +*3 +*3 +*1 +*2 +*3 +*8 +*20 +*4 +*7 +*6 +*5 +*\end{verbatim} +* +* +} +} diff --git a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf new file mode 100644 index 00000000..694105e4 Binary files /dev/null and b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf differ diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf b/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf new file mode 100644 index 00000000..ef930c0c Binary files /dev/null and b/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf differ diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index 31da3609..e56428b6 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -59,16 +59,13 @@ lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for exam Bitmap_cubical_complex b( argv[1] ); - // Compute the persistence diagram of the complex persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); pcoh.init_coefficients( p ); //initilizes the coefficient field for homology pcoh.compute_persistent_cohomology( min_persistence ); - - stringstream ss; ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); + std::ofstream out(ss.str().c_str()); pcoh.output_diagram(out); out.close(); diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index f2c753d9..b8887e71 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -34,7 +34,9 @@ namespace Cubical_complex { //global variable, was used just for debugging. -const bool globalDbg = false; +const bool globalDbg = false; + +template class is_before_in_filtration; template class Bitmap_cubical_complex : public Bitmap_cubical_complex_base @@ -45,71 +47,8 @@ public: //*********************************************// friend class Simplex_handle; typedef size_t Simplex_key; - typedef T Filtration_value; - - -//*********************************************// -//Simplex handle class -//*********************************************// - /** - * Handle of a cell, required for compatibility with the function to compute persistence in Gudhi. - * Elements of this class are: the pointer to the bitmap B in which the considered cell is - * together with a position of this cell in B. Given this data, - * one can get all the information about the considered cell. - **/ - class Simplex_handle - { - public: - Simplex_handle() - { - if ( globalDbg ){cerr << "Simplex_handle()\n";} - this->b = 0; - this->position = 0; - } - - Simplex_handle(Bitmap_cubical_complex* b) - { - if ( globalDbg ) - { - cerr << "Simplex_handle(Bitmap_cubical_complex* b)\n"; - } - this->b = b; - this->position = 0; - } - - //Simplex_handle( const Simplex_handle& org ):b(org.b) - //{ - // if ( globalDbg ){cerr << "Simplex_handle( const Simplex_handle& org )\n";} - // this->position = org.position; - //} - - Simplex_handle operator = ( const Simplex_handle& rhs ) - { - if ( globalDbg ){cerr << "Simplex_handle operator = \n";} - this->position = rhs.position; - this->b = rhs.b; - return *this; - } - - Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position) - { - if ( globalDbg ) - { - cerr << "Simplex_handle(Bitmap_cubical_complex* b , Simplex_key position)\n"; - cerr << "Position : " << position << endl; - } - this->b = b; - this->position = position; - } - friend class Bitmap_cubical_complex; - private: - Bitmap_cubical_complex* b; - Simplex_key position; - //Assumption -- field above always keep the REAL position of simplex in the bitmap, - //no matter what keys have been. - //to deal with the keys, the class Bitmap_cubical_complex have extra vectors: key_associated_to_simplex and - //simplex_associated_to_key that allow to move between actual cell and the key assigned to it. - }; + typedef T Filtration_value; + typedef Simplex_key Simplex_handle; //*********************************************// @@ -125,39 +64,37 @@ public: * Constructor form a Perseus-style file. **/ Bitmap_cubical_complex( const char* perseus_style_file ): - Bitmap_cubical_complex_base(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1), - simplex_associated_to_key(this->total_number_of_cells+1) + Bitmap_cubical_complex_base(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) { if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) { - this->key_associated_to_simplex[i] = this->simplex_associated_to_key[i] = i; + this->key_associated_to_simplex[i] = i; } - //we initialize this only once, in each constructor, when the bitmap is constructed. + //we initialize this only once, in each constructor, when the bitmap is constructed. //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. - this->initialize_elements_ordered_according_to_filtration(); + this->initialize_simplex_associated_to_key(); } /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells * in the following directions and vector of element of a type T * with filtration on top dimensional cells. **/ Bitmap_cubical_complex( std::vector& dimensions , std::vector& top_dimensional_cells ): Bitmap_cubical_complex_base(dimensions,top_dimensional_cells), - key_associated_to_simplex(this->total_number_of_cells+1), - simplex_associated_to_key(this->total_number_of_cells+1) + key_associated_to_simplex(this->total_number_of_cells+1) { for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) { - this->key_associated_to_simplex[i] = this->simplex_associated_to_key[i] = i; + this->key_associated_to_simplex[i] = i; } - //we initialize this only once, in each constructor, when the bitmap is constructed. + //we initialize this only once, in each constructor, when the bitmap is constructed. //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. - this->initialize_elements_ordered_according_to_filtration(); + this->initialize_simplex_associated_to_key(); } //*********************************************// @@ -174,15 +111,17 @@ public: /** * Returns a Simplex_handle to a cube that do not exist in this complex. **/ - Simplex_handle null_simplex() - { - return Simplex_handle(this,this->data.size()); - } + static Simplex_handle null_simplex() + { + if ( globalDbg ){cerr << "Simplex_handle null_simplex()\n";} + return std::numeric_limits::max(); + } + /** * Returns dimension of the complex. **/ - size_t dimension() + inline size_t dimension()const { return this->sizes.size(); } @@ -190,10 +129,10 @@ public: /** * Return dimension of a cell pointed by the Simplex_handle. **/ - unsigned dimension(const Simplex_handle& sh) + inline unsigned dimension(const Simplex_handle& sh)const { if ( globalDbg ){cerr << "unsigned dimension(const Simplex_handle& sh)\n";} - if ( sh.position != this->data.size() ) return sh.b->get_dimension_of_a_cell( sh.position ); + if ( sh != std::numeric_limits::max() ) return this->get_dimension_of_a_cell( sh ); return -1; } @@ -204,26 +143,30 @@ public: { if ( globalDbg ){cerr << "T filtration(const Simplex_handle& sh)\n";} //Returns the filtration value of a simplex. - if ( sh.position != this->data.size() ) return sh.b->data[ sh.position ]; + if ( sh != std::numeric_limits::max() ) return this->data[sh]; return std::numeric_limits::max(); } /** * Return a key which is not a key of any cube in the considered data structure. **/ - Simplex_key null_key() + static Simplex_key null_key() { if ( globalDbg ){cerr << "Simplex_key null_key()\n";} - return this->data.size(); + return std::numeric_limits::max(); } /** * Return the key of a cube pointed by the Simplex_handle. **/ - Simplex_key key(const Simplex_handle& sh) + Simplex_key key(const Simplex_handle& sh)const { - if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} - return sh.b->key_associated_to_simplex[ sh.position ]; + if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} + if ( sh != std::numeric_limits::max() ) + { + return this->key_associated_to_simplex[sh]; + } + return this->null_key(); } /** @@ -231,8 +174,12 @@ public: **/ Simplex_handle simplex(Simplex_key key) { - if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} - return Simplex_handle( this , this->simplex_associated_to_key[ key ] ); + if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} + if ( key != std::numeric_limits::max() ) + { + return this->simplex_associated_to_key[ key ]; + } + return null_simplex(); } /** @@ -240,15 +187,29 @@ public: **/ void assign_key(Simplex_handle& sh, Simplex_key key) { - if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} - this->key_associated_to_simplex[sh.position] = key; - this->simplex_associated_to_key[key] = sh.position; + if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} + + + + + + + + +if ( key == std::numeric_limits::max() ) return;//TODO FAKE!!! CHEATING!!! + + + + + + this->key_associated_to_simplex[sh] = key; + this->simplex_associated_to_key[key] = sh; } /** * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. **/ - void initialize_elements_ordered_according_to_filtration(); + void initialize_simplex_associated_to_key(); @@ -256,104 +217,42 @@ public: //Iterators //*********************************************// - /** - * Boundary_simplex_iterator class allows iteration on boundary of each cube. - **/ - class Boundary_simplex_range; - class Boundary_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > - { - //Iterator on the simplices belonging to the boundary of a simplex. - //value_type must be 'Simplex_handle'. - public: - Boundary_simplex_iterator( Simplex_handle& sh ):sh(sh) - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator( Simplex_handle& sh )\n";} - this->position = 0; - this->boundary_elements = this->sh.b->get_boundary_of_a_cell( this->sh.position ); - } - Boundary_simplex_iterator operator++() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator operator++()\n";} - ++this->position; - return *this; - } - Boundary_simplex_iterator operator++(int) - { - Boundary_simplex_iterator result = *this; - ++(*this); - return result; - } - Boundary_simplex_iterator operator =( const Boundary_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator operator =\n";} - this->sh = rhs.sh; - this->boundary_elements.clear(); - this->boundary_elementsinsert - (this->boundary_elements.end(), rhs.boundary_elements.begin(), rhs.boundary_elements.end()); - } - bool operator == ( const Boundary_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "bool operator ==\n";} - if ( this->position == rhs.position ) - { - if ( this->boundary_elements.size() != rhs.boundary_elements.size() )return false; - for ( size_t i = 0 ; i != this->boundary_elements.size() ; ++i ) - { - if ( this->boundary_elements[i] != rhs.boundary_elements[i] )return false; - } - return true; - } - return false; - } - - bool operator != ( const Boundary_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "bool operator != \n";} - return !(*this == rhs); - } - Simplex_handle operator*() - { - if ( globalDbg ){cerr << "Simplex_handle operator*\n";} - return Simplex_handle( this->sh.b , this->boundary_elements[this->position] ); - } - - friend class Boundary_simplex_range; - private: - Simplex_handle sh; - std::vector< size_t > boundary_elements; - size_t position; - }; /** * Boundary_simplex_range class provides ranges for boundary iterators. - **/ + **/ + typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; class Boundary_simplex_range { //Range giving access to the simplices in the boundary of a simplex. //.begin() and .end() return type Boundary_simplex_iterator. - public: - Boundary_simplex_range(const Simplex_handle& sh):sh(sh){}; - Boundary_simplex_iterator begin() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator begin\n";} - Boundary_simplex_iterator it( this->sh ); - return it; - } - Boundary_simplex_iterator end() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator end()\n";} - Boundary_simplex_iterator it( this->sh ); - it.position = it.boundary_elements.size(); - return it; - } - private: - Simplex_handle sh; - }; + public: + typedef Boundary_simplex_iterator const_iterator; + Boundary_simplex_range(const Simplex_handle& sh , Bitmap_cubical_complex* CC_):sh(sh),CC(CC_) + { + this->boundary_elements = this->CC->get_boundary_of_a_cell( sh ); + } + Boundary_simplex_iterator begin() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator begin\n";} + return this->boundary_elements.begin(); + + } + Boundary_simplex_iterator end() + { + if ( globalDbg ){cerr << "Boundary_simplex_iterator end()\n";} + return this->boundary_elements.end(); + } + private: + Simplex_handle sh; + Bitmap_cubical_complex* CC; + std::vector< Simplex_handle > boundary_elements; + }; /** - * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. + * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. * Secondary criteria for filtration are: * (1) Dimension of a cube (lower dimensional comes first). * (2) Position in the data structure (the ones that are earlies in the data structure comes first). @@ -385,17 +284,13 @@ public: this->b = rhs.b; this->position = rhs.position; } - bool operator == ( const Filtration_simplex_iterator& rhs ) + bool operator == ( const Filtration_simplex_iterator& rhs )const { if ( globalDbg ){cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";} - if ( this->position == rhs.position ) - { - return true; - } - return false; + return ( this->position == rhs.position ); } - bool operator != ( const Filtration_simplex_iterator& rhs ) + bool operator != ( const Filtration_simplex_iterator& rhs )const { if ( globalDbg ){cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";} return !(*this == rhs); @@ -403,7 +298,7 @@ public: Simplex_handle operator*() { if ( globalDbg ){cerr << "Simplex_handle operator*()\n";} - return Simplex_handle( this->b , this->b->elements_ordered_according_to_filtration[ this->position ] ); + return this->b->simplex_associated_to_key[ this->position ]; } friend class Filtration_simplex_range; @@ -420,7 +315,8 @@ public: { //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. - public: + public: + typedef Filtration_simplex_iterator const_iterator; Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; Filtration_simplex_iterator begin() { @@ -431,7 +327,7 @@ public: { if ( globalDbg ){cerr << "Filtration_simplex_iterator end()\n";} Filtration_simplex_iterator it( this->b ); - it.position = this->b->elements_ordered_according_to_filtration.size(); + it.position = this->b->simplex_associated_to_key.size(); return it; } private: @@ -443,19 +339,19 @@ public: //*********************************************// //Methods to access iterators from the container: /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class + * boundary_simplex_range creates an object of a Boundary_simplex_range class * that provides ranges for the Boundary_simplex_iterator. **/ Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) { if ( globalDbg ){cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n";} - //Returns a range giving access to all simplices of the boundary of a simplex, + //Returns a range giving access to all simplices of the boundary of a simplex, //i.e. the set of codimension 1 subsimplices of the Simplex. - return Boundary_simplex_range(sh); + return Boundary_simplex_range(sh,this); } /** - * filtration_simplex_range creates an object of a Filtration_simplex_range class + * filtration_simplex_range creates an object of a Filtration_simplex_range class * that provides ranges for the Filtration_simplex_iterator. **/ Filtration_simplex_range filtration_simplex_range() @@ -470,9 +366,9 @@ public: //*********************************************// //Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. - //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so + //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so //I understand that this is something that was planned (for simplicial maps?) - //but was never finished. The only idea I have here is to use the same empty structure from + //but was never finished. The only idea I have here is to use the same empty structure from //IndexingTag.h file, but only if the compiler needs it. If the compiler //do not need it, then I would rather not add here elements which I do not understand. //typedef Indexing_tag @@ -481,7 +377,7 @@ public: **/ std::pair endpoints( Simplex_handle sh ) { - std::vector< size_t > bdry = this->get_boundary_of_a_cell( sh.position ); + std::vector< size_t > bdry = this->get_boundary_of_a_cell( sh ); if ( globalDbg ) { cerr << "std::pair endpoints( Simplex_handle sh )\n"; @@ -490,7 +386,7 @@ public: //this method returns two first elements from the boundary of sh. if ( bdry.size() < 2 ) throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); - return std::make_pair( Simplex_handle(this,bdry[0]) , Simplex_handle(this,bdry[1]) ); + return std::make_pair( bdry[0] , bdry[1] ); } @@ -508,9 +404,9 @@ public: if ( globalDbg ){cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n";} //find the position of the first simplex of a dimension d this->position = 0; - while ( - (this->position != b->data.size()) && - ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) + while ( + (this->position != b->data.size()) && + ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) ) { ++this->position; @@ -523,9 +419,9 @@ public: if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator++()\n";} //increment the position as long as you did not get to the next element of the dimension dimension. ++this->position; - while ( - (this->position != this->b->data.size()) && - ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) + while ( + (this->position != this->b->data.size()) && + ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) ) { ++this->position; @@ -544,17 +440,13 @@ public: this->b = rhs.b; this->position = rhs.position; } - bool operator == ( const Skeleton_simplex_iterator& rhs ) + bool operator == ( const Skeleton_simplex_iterator& rhs )const { if ( globalDbg ){cerr << "bool operator ==\n";} - if ( this->position == rhs.position ) - { - return true; - } - return false; + return ( this->position == rhs.position ); } - bool operator != ( const Skeleton_simplex_iterator& rhs ) + bool operator != ( const Skeleton_simplex_iterator& rhs )const { if ( globalDbg ){cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";} return !(*this == rhs); @@ -562,7 +454,7 @@ public: Simplex_handle operator*() { if ( globalDbg ){cerr << "Simplex_handle operator*() \n";} - return Simplex_handle( this->b , this->position ); + return this->position; } friend class Skeleton_simplex_range; @@ -578,7 +470,8 @@ public: { //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. - public: + public: + typedef Skeleton_simplex_iterator const_iterator; Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; Skeleton_simplex_iterator begin() { @@ -606,107 +499,59 @@ public: return Skeleton_simplex_range( this , dimension ); } + friend class is_before_in_filtration; -//*********************************************// -//functions used for debugging: - /** - * Function used for debugging purposes. - **/ - //void printkey_associated_to_simplex() - //{ - // for ( size_t i = 0 ; i != this->data.size() ; ++i ) - // { - // cerr << i << " -> " << this->simplex_associated_to_key[i] << endl; - // } - //} - - /** - * Function used for debugging purposes. - **/ - size_t printRealPosition( const Simplex_handle& sh ) - { - return sh.position; - } - -private: +protected: std::vector< size_t > key_associated_to_simplex; std::vector< size_t > simplex_associated_to_key; - std::vector< size_t > elements_ordered_according_to_filtration; - //filed above is needed by Filtration_simplex_iterator. If this iterator is not used, this field is not initialized. };//Bitmap_cubical_complex - + template -bool compare_elements_for_elements_ordered_according_to_filtration -( const std::pair< size_t , std::pair< T , char > >& f , const std::pair< size_t , std::pair< T , char > >& s ) +void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { - if ( globalDbg ){cerr << "compare_elements_for_elements_ordered_according_to_filtration\n";} - if ( f.second.first < s.second.first ) - { - return true; - } - else + if ( globalDbg ) { - if ( f.second.first > s.second.first ) - { - return false; - } - else - { - //in this case f.second.first == s.second.first, and we use dimension to compare: - if ( f.second.second < s.second.second ) - { - return true; - } - else - { - if ( f.second.second > s.second.second ) - { - return false; - } - else - { - //in this case, both the filtration value and the dimensions for those cells are the same. - //Since it may be nice to have a stable sorting procedure, in this case, - //we compare positions in the bitmap: - return ( f.first < s.first ); - } - } - } + cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; } + std::vector data_of_elements_from_bitmap( this->data.size() ); + std::iota (std::begin(data_of_elements_from_bitmap), std::end(data_of_elements_from_bitmap), 0); + std::sort( data_of_elements_from_bitmap.begin() , + data_of_elements_from_bitmap.end() , + is_before_in_filtration(this) ); + this->simplex_associated_to_key = data_of_elements_from_bitmap; } - + + template -void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() +class is_before_in_filtration { - if ( globalDbg ) - { - cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; - } - //( position , (filtration , dimension) ) - std::vector< std::pair< size_t , std::pair< T , char > > > data_of_elements_from_bitmap( this->data.size() ); - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - //TODO -- this can be optimized by having a counter here. - //We do not need to re-compute the dimension for every cell from scratch - data_of_elements_from_bitmap[i] = - std::make_pair( i , std::make_pair( this->data[i] , this->get_dimension_of_a_cell(i) ) ); - } - std::sort( data_of_elements_from_bitmap.begin() , - data_of_elements_from_bitmap.end() , - compare_elements_for_elements_ordered_according_to_filtration ); - - std::vector< size_t > - elements_ordered_according_to_filtration_then_to_dimension_then_to_position - ( this->data.size() ); - for ( size_t i = 0 ; i != data_of_elements_from_bitmap.size() ; ++i ) +public: + explicit is_before_in_filtration(Bitmap_cubical_complex * CC) + : CC_(CC) { } + + bool operator()( const typename Bitmap_cubical_complex::Simplex_handle sh1, const typename Bitmap_cubical_complex::Simplex_handle sh2) const { - elements_ordered_according_to_filtration_then_to_dimension_then_to_position[i] - = data_of_elements_from_bitmap[i].first; - } - this->elements_ordered_according_to_filtration = - elements_ordered_according_to_filtration_then_to_dimension_then_to_position; -} + // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. + T fil1 = CC_->data[sh1]; + T fil2 = CC_->data[sh2]; + if ( fil1 != fil2 ) + { + return fil1 < fil2; + } + //in this case they are on the same filtration level, so the dimension decide. + size_t dim1 = CC_->get_dimension_of_a_cell(sh1); + size_t dim2 = CC_->get_dimension_of_a_cell(sh2); + if ( dim1 != dim2 ) + { + return dim1 < dim2; + } + //in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply compare their positions in the bitmap: + return sh1 < sh2; + } +protected: + Bitmap_cubical_complex* CC_; + }; //****************************************************************************************************************// @@ -716,4 +561,4 @@ void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtrat } -} \ No newline at end of file +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h new file mode 100644 index 00000000..3a17b4a0 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h @@ -0,0 +1,171 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 . + */ + +#pragma once + +#include +#include + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +/** +* This is an implementation of a counter being a vector of integers. +* The constructor of the class takes as an input two vectors W and V. +* It assumes that W < V coordinatewise. +* If the initial counter W is not specified, it is assumed to be vector of zeros. +* The class allows to iterate between W and V by using increment() function. +* The increment() function returns a bool value. +* The current counter reach the end counter V if the value returned by the increment function is FALSE. +* This class is needed for the implementation of a bitmapCubicalComplex. +**/ + +class counter +{ +public: + /** + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. + * The default beginning value is a vector of the same length as the endd, filled-in with zeros. + **/ + counter(std::vector const& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} + //counter(std::vector< int >& endd) + //{ + // for ( size_t i = 0 ; i != endd.size() ; ++i ) + // { + // this->current.push_back(0); + // this->begin.push_back(0); + // this->end.push_back( endd[i] ); + // } + //} + + + /** + * Constructor of a counter class. It takes as the input beginn and end vector. + * It assumes that begin vector is lexicographically below the end vector. + **/ + counter(std::vector< unsigned >& beginn , std::vector< unsigned >& endd):begin(beginn),end(endd),current(endd.size(),0) + { + if ( beginn.size() != endd.size() ) + throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + } + + /** + * Function to increment the counter. If the value returned by the function is true, + * then the incrementation process was successful. + * If the value of the function is false, that means, that the counter have reached its end-value. + **/ + bool increment() + { + size_t i = 0; + while( (i != this->end.size()) && (this->current[i] == this->end[i]) ) + { + ++i; + } + + if ( i == this->end.size() )return false; + ++this->current[i]; + for ( size_t j = 0 ; j != i ; ++j ) + { + this->current[j] = this->begin[j]; + } + return true; + } + + /** + * Function to check if we are at the end of counter. + **/ + bool isFinal() + { + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( this->current[i] == this->end[i] )return true; + } + return false; + } + + /** + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. + * Its aim is to find an counter corresponding to the element the following + * boundary element is identified with when periodic boundary conditions are imposed. + **/ + std::vector< unsigned > find_opposite( std::vector< bool >& directionsForPeriodicBCond ) + { + std::vector< unsigned > result; + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( (this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true) ) + { + result.push_back( this->begin[i] ); + } + else + { + result.push_back( this->current[i] ); + } + } + return result; + } + + /** + * Function checking at which positions the current value of a counter is the final value of the counter. + **/ + std::vector< bool > directions_of_finals() + { + std::vector< bool > result; + for ( size_t i = 0 ; i != this->current.size() ; ++i ) + { + if ( this->current[i] == this->end[i] ) + { + result.push_back( true ); + } + else + { + result.push_back( false ); + } + } + return result; + } + + /** + * Function to write counter to the stream. + **/ + friend std::ostream& operator<<(std::ostream& out , const counter& c ) + { + //cerr << "c.current.size() : " << c.current.size() << endl; + for ( size_t i = 0 ; i != c.current.size() ; ++i ) + { + out << c.current[i] << " "; + } + return out; + } +private: + std::vector< unsigned > begin; + std::vector< unsigned > end; + std::vector< unsigned > current; +}; + +} +} \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 2c2bd481..4e63b9c3 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -30,7 +30,7 @@ #include #include #include -#include "counter.h" +#include "Bitmap_cubical_complex/counter.h" using namespace std; @@ -182,11 +182,9 @@ public: public: Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) { - for ( size_t i = 0 ; i != b.dimension() ; ++i ) - { - this->counter.push_back(0); - } - } + this->counter = std::vector(b.dimension()); + std::fill( this->counter.begin() , this->counter.end() , 0 ); + } Top_dimensional_cells_iterator operator++() { //first find first element of the counter that can be increased: @@ -264,7 +262,7 @@ public: } friend class Bitmap_cubical_complex_base; protected: - std::vector< unsigned > counter; + std::vector< size_t > counter; Bitmap_cubical_complex_base& b; }; Top_dimensional_cells_iterator top_dimensional_cells_begin() @@ -478,12 +476,16 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( si getchar(); } - std::vector< size_t > boundary_elements; + std::vector< size_t > boundary_elements( 2*dimensions_in_which_cell_has_nonzero_length.size() ); if ( dimensions_in_which_cell_has_nonzero_length.size() == 0 )return boundary_elements; for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) { - boundary_elements.push_back( cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); - boundary_elements.push_back( cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + //boundary_elements.push_back( cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + //boundary_elements.push_back( cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); + boundary_elements[2*i] = cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ]; + boundary_elements[2*i+1] = cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ]; + + if (bdg) cerr << "multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " << multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; diff --git a/src/Bitmap_cubical_complex/include/gudhi/counter.h b/src/Bitmap_cubical_complex/include/gudhi/counter.h deleted file mode 100644 index a5fda36f..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/counter.h +++ /dev/null @@ -1,177 +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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-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 . - */ - -#pragma once - -#include -#include - -using namespace std; - -namespace Gudhi -{ - -namespace Cubical_complex -{ - -/** -* This is an implementation of a counter being a vector of integers. -* The constructor of the class takes as an input two vectors W and V. -* It assumes that W < V coordinatewise. -* If the initial counter W is not specified, it is assumed to be vector of zeros. -* The class allows to iterate between W and V by using increment() function. -* The increment() function returns a bool value. -* The current counter reach the end counter V if the value returned by the increment function is FALSE. -* This class is needed for the implementation of a bitmapCubicalComplex. -**/ - -class counter -{ -public: - /** - * Constructor of a counter class. It takes only the parameter which is the end value of the counter. - * The default beginning value is a vector of the same length as the endd, filled-in with zeros. - **/ - counter(std::vector const& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} - //counter(std::vector< int >& endd) - //{ - // for ( size_t i = 0 ; i != endd.size() ; ++i ) - // { - // this->current.push_back(0); - // this->begin.push_back(0); - // this->end.push_back( endd[i] ); - // } - //} - - - /** - * Constructor of a counter class. It takes as the input beginn and end vector. - * It assumes that begin vector is lexicographically below the end vector. - **/ - counter(std::vector< unsigned >& beginn , std::vector< unsigned >& endd) - { - if ( beginn.size() != endd.size() ) - throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; - for ( size_t i = 0 ; i != endd.size() ; ++i ) - { - this->current.push_back(0); - this->begin.push_back(0); - this->end.push_back( endd[i] ); - } - } - - /** - * Function to increment the counter. If the value returned by the function is true, - * then the incrementation process was successful. - * If the value of the function is false, that means, that the counter have reached its end-value. - **/ - bool increment() - { - size_t i = 0; - while( (i != this->end.size()) && (this->current[i] == this->end[i]) ) - { - ++i; - } - - if ( i == this->end.size() )return false; - ++this->current[i]; - for ( size_t j = 0 ; j != i ; ++j ) - { - this->current[j] = this->begin[j]; - } - return true; - } - - /** - * Function to check if we are at the end of counter. - **/ - bool isFinal() - { - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( this->current[i] == this->end[i] )return true; - } - return false; - } - - /** - * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. - * Its aim is to find an counter corresponding to the element the following - * boundary element is identified with when periodic boundary conditions are imposed. - **/ - std::vector< unsigned > find_opposite( std::vector< bool >& directionsForPeriodicBCond ) - { - std::vector< unsigned > result; - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( (this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true) ) - { - result.push_back( this->begin[i] ); - } - else - { - result.push_back( this->current[i] ); - } - } - return result; - } - - /** - * Function checking at which positions the current value of a counter is the final value of the counter. - **/ - std::vector< bool > directions_of_finals() - { - std::vector< bool > result; - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( this->current[i] == this->end[i] ) - { - result.push_back( true ); - } - else - { - result.push_back( false ); - } - } - return result; - } - - /** - * Function to write counter to the stream. - **/ - friend std::ostream& operator<<(std::ostream& out , const counter& c ) - { - //cerr << "c.current.size() : " << c.current.size() << endl; - for ( size_t i = 0 ; i != c.current.size() ; ++i ) - { - out << c.current[i] << " "; - } - return out; - } -private: - std::vector< unsigned > begin; - std::vector< unsigned > end; - std::vector< unsigned > current; -}; - -} -} \ No newline at end of file -- cgit v1.2.3 From f0ca2ba2080c8f2b01a7cd459560980dfcb964f8 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 11 Dec 2015 12:44:20 +0000 Subject: Pictures in png format git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@943 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 470f82a103e17ffbda2b784fa829e5b0b11458e6 --- .../doc/Gudhi_Cubical_Complex_doc.h | 1 + src/Bitmap_cubical_complex/doc/bitmapAllCubes.png | Bin 0 -> 38944 bytes src/Bitmap_cubical_complex/doc/exampleBitmap.png | Bin 0 -> 9594 bytes 3 files changed, 1 insertion(+) create mode 100644 src/Bitmap_cubical_complex/doc/bitmapAllCubes.png create mode 100644 src/Bitmap_cubical_complex/doc/exampleBitmap.png diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index 4acf2b3a..6e821ce4 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -102,5 +102,6 @@ namespace Cubical_complex *\end{verbatim} * * +*@}//end of the group } } diff --git a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png new file mode 100644 index 00000000..77167b13 Binary files /dev/null and b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.png differ diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.png b/src/Bitmap_cubical_complex/doc/exampleBitmap.png new file mode 100644 index 00000000..f8207473 Binary files /dev/null and b/src/Bitmap_cubical_complex/doc/exampleBitmap.png differ -- cgit v1.2.3 From fd41fbbb321b36c143129b5a311e015bf7c44a6f Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 11 Dec 2015 13:04:06 +0000 Subject: Removed pdf to use png Biblio issue git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@944 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 68e93aa53ebadcde4b44eec881b72080e6ceaa70 --- biblio/bibliography.bib | 27 +++++++ .../doc/Gudhi_Cubical_Complex_doc.h | 89 ++++++++++----------- src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf | Bin 13940 -> 0 bytes src/Bitmap_cubical_complex/doc/exampleBitmap.pdf | Bin 11122 -> 0 bytes src/Doxyfile | 3 +- 5 files changed, 71 insertions(+), 48 deletions(-) delete mode 100644 src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf delete mode 100644 src/Bitmap_cubical_complex/doc/exampleBitmap.pdf diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index 3fd1c10a..9fc01a5d 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -927,3 +927,30 @@ misc{jplex_cite, year = "2009", note = "http://comptop.stanford.edu/programs/jplex/" } + +@book{kaczynski2004computational, + title={Computational Homology}, + author={Kaczynski, T. and Mischaikow, K. and Mrozek, M.}, + isbn={9780387408538}, + lccn={03061109}, + series={Applied Mathematical Sciences}, + url={https://books.google.fr/books?id=AShKtpi3GecC}, + year={2004}, + publisher={Springer New York} +} + +@ARTICLE{peikert2012topological, +year={2012}, +isbn={978-3-642-23174-2}, +booktitle={Topological Methods in Data Analysis and Visualization II}, +series={Mathematics and Visualization}, +editor={Peikert, Ronald and Hauser, Helwig and Carr, Hamish and Fuchs, Raphael}, +doi={10.1007/978-3-642-23175-9_7}, +title={Efficient Computation of Persistent Homology for Cubical Data}, +url={http://dx.doi.org/10.1007/978-3-642-23175-9_7}, +publisher={Springer Berlin Heidelberg}, +author={Wagner, Hubert and Chen, Chao and Vucini, Erald}, +pages={91-106}, +language={English} +} + diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index 6e821ce4..1a6310fb 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -38,70 +38,65 @@ namespace Cubical_complex *Cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. * -* An \emph{elementary interval} is an interval of a form $[n,n+1]$, or $[n,n]$, for $n \in \mathcal{Z}$. The first one is called \emph{non-degenerated}, while the second one is \emph{degenerated} interval. A \emph{boundary of a elementary -*interval} is a chain $\partial [n,n+1] = [n+1,n+1]-[n,n]$ in case of non-degenerated elementary interval and $\partial [n,n] = 0$ in case of degenerated elementary interval. An \emph{elementary cube} $C$ is a -*product of elementary intervals, $C=I_1 \times \ldots \times I_n$. \emph{Embedding dimension} of a cube is n, the number of elementary intervals (degenerated or not) in the product. A \emph{dimension of a cube} $C=I_1 \times ... \times I_n$ is the -*number of non degenerated elementary intervals in the product. A \emph{boundary of a cube} $C=I_1 \times \ldots \times I_n$ is a chain obtained in the following way: -*\[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\] -*A \emph{cubical complex} $\mathcal{K}$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube $C$ in cubical complex $\mathcal{K}$ is \emph{maximal} if it is not in -*a boundary of any other cube in $\mathcal{K}$. A \emph{support} of a cube $C$ is the set in $\mathbb{R}^n$ occupied by $C$ ($n$ is the embedding dimension of $C$). +* An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerated, while the second one is \a degenerated interval. A boundary of a elementary +*interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerated elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerated elementary interval. An elementary cube \f$ C \f$ is a + +*product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. Embedding dimension of a cube is n, the number of elementary intervals (degenerated or not) in the product. A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the +*number of non degenerated elementary intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained in the following way: +*\f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f] +*A cubical complex \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex \f$\mathcal{K}\f$ is maximal if it is not in +*a boundary of any other cube in \f$\mathcal{K}\f$. A \a support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension of \f$C\f$). * *Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may be a set of two elements). * -*For further details and theory of cubical complexes, please consult a book:\\ -*Computational homology, by Tomasz Kaczynski, Konstantin Mischaikow, and Marion Mrozek, Appl. Math. Sci., vol. 157, Springer-Verlag, New York, 2004 +*For further details and theory of cubical complexes, please consult \cite kaczynski2004computational . * -*as well as the paper: -*Efficient computation of persistent homology for cubical data by Hubert Wagner, Chao Chen, Erald Vuçini (published in the proceedings of Workshop on Topology-based Methods in Data -*Analysis and Visualization) +*as well as the following paper \cite peikert2012topological . * -*\section{Data structure.} +*\section datastructure Data structure. * -*The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in $\mathbb{R}^n$. This extra -*assumption allows for a memory efficient way of storing cubical complexes in a form of so called bitmaps. Let $R = [b_1,e_1] \times \ldots \times [b_n,e_n]$, for $b_1,...b_n,e_1,...,e_n \in \mathbb{Z}$ -*, $b_i \leq d_i$ be the considered rectangular region and let $\mathcal{K}$ be a filtered cubical complex having the rectangle $R$ as its support. Note that the structure of the coordinate system gives a way -*a lexicographical ordering of cells of $\mathcal{K}$. This ordering is a base of the presented bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector -*of the values of filtration. This, together with dimension of $\mathcal{K}$ and the sizes of $\mathcal{K}$ in all directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube $C \in \mathcal{K}$. +*The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in \f$\mathbb{R}^n\f$. This extra +*assumption allows for a memory efficient way of storing cubical complexes in a form of so called bitmaps. Let \f$R = [b_1,e_1] \times \ldots \times [b_n,e_n]\f$, for \f$b_1,...b_n,e_1,...,e_n \in \mathbb{Z}\f$ +*, \f$b_i \leq d_i\f$ be the considered rectangular region and let \f$\mathcal{K}\f$ be a filtered cubical complex having the rectangle \f$R\f$ as its support. Note that the structure of the coordinate system gives a way +*a lexicographical ordering of cells of \f$\mathcal{K}\f$. This ordering is a base of the presented bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector +*of the values of filtration. This, together with dimension of \f$\mathcal{K}\f$ and the sizes of \f$\mathcal{K}\f$ in all directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube \f$C \in \mathcal{K}\f$. * -*\image html "bitmapAllCubes.pdf" "Cubical complex in $\mathbb{R}^2". +*\image html "bitmapAllCubes.png" "Cubical complex. * -*Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical complexes in $\mathbb{R}$. The number of all cubes in each direction is -*equal $2n+1$, where $n$ is the number of maximal cubes in the considered direction. Let us consider a cube at the position $k$ in the bitmap. Knowing the sizes of the bitmap, -*by a series of modulo operation, we can determine which elementary intervals are present in the product that gives the cube $C$. In a similar way, we can compute boundary +*Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical complexes in \f$\mathbb{R}\f$. The number of all cubes in each direction is +*equal \f$2n+1\f$, where \f$n\f$ is the number of maximal cubes in the considered direction. Let us consider a cube at the position \f$k\f$ in the bitmap. Knowing the sizes of the bitmap, +*by a series of modulo operation, we can determine which elementary intervals are present in the product that gives the cube \f$C\f$. In a similar way, we can compute boundary *and the coboundary of each cube. Further details can be found in the literature. * -*\section{Input Format.} +*\section inputformat Input Format. * *In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors -*that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \emph{Bitmap\_cubical\_complex} class. -*Currently one input from a text file is used. It uses a format used already in Perseus software $(http://www.sas.upenn.edu/~vnanda/perseus/)$ by Vidit Nanda. +*that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. +*Currently one input from a text file is used. It uses a format used already in Perseus software (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. *Below we are providing a description of the format. * -*\begin{enumerate} -*\item The first line of the file is $d$, the embedding dimension of a complex. -*\item The next $d$ lines consist of positive numbers being the numbers of top dimensional cubes in the given direction. Let us call those numbers $n_1,\ldots,n_d$. -*\item Later there is a sequence of $n_1 \dot \ldots \dot n_d$ numbers in a lexicographical ordering. Those numbers are filtrations of top dimensional cubes. -*\end{enumerate} * -*\image html "exampleBitmap.pdf" "Example of a input data." +*\image html "exampleBitmap.png" "Example of a input data." * *The input file for the following complex is: -*\begin{verbatim} -*2 -*3 -*3 -*1 -*2 -*3 -*8 -*20 -*4 -*7 -*6 -*5 -*\end{verbatim} -* -* +*\verbatim +2 +3 +3 +1 +2 +3 +8 +20 +4 +7 +6 +5 +\endverbatim + +*/ +/** @} */ // end defgroup cubical_complex + *@}//end of the group } } diff --git a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf b/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf deleted file mode 100644 index 694105e4..00000000 Binary files a/src/Bitmap_cubical_complex/doc/bitmapAllCubes.pdf and /dev/null differ diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf b/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf deleted file mode 100644 index ef930c0c..00000000 Binary files a/src/Bitmap_cubical_complex/doc/exampleBitmap.pdf and /dev/null differ diff --git a/src/Doxyfile b/src/Doxyfile index faa0d3fe..7a21c254 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -834,7 +834,8 @@ EXAMPLE_RECURSIVE = NO IMAGE_PATH = doc/Skeleton_blocker/ \ doc/common/ \ - doc/Contraction/ + doc/Contraction/ \ + doc/Bitmap_cubical_complex # The INPUT_FILTER tag can be used to specify a program that doxygen should -- 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 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 5eae3bbe5c06a3b601b885ea9f2561743f4aeb1a Mon Sep 17 00:00:00 2001 From: pdlotko Date: Tue, 22 Dec 2015 07:57:35 +0000 Subject: Changes according to Marc's comments from 18 December. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@947 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3afdd0423f3b36d8103360ef11fbb5f1c9a348a5 --- .../example/Random_bitmap_cubical_complex.cpp | 2 +- .../include/gudhi/Bitmap_cubical_complex.h | 90 +++--------- .../include/gudhi/Bitmap_cubical_complex/counter.h | 6 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 163 ++++++++------------- 4 files changed, 93 insertions(+), 168 deletions(-) diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index 60cfc113..36c22344 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -85,7 +85,7 @@ The program will create random cubical complex of that sizes and compute persist stringstream ss; ss << "randomComplex_persistence"; - std::ofstream out((char*)ss.str().c_str()); + std::ofstream out(ss.str().c_str()); pcoh.output_diagram(out); out.close(); diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index b8887e71..c082caba 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -45,7 +45,6 @@ public: //*********************************************// //Typedefs and typenames //*********************************************// - friend class Simplex_handle; typedef size_t Simplex_key; typedef T Filtration_value; typedef Simplex_key Simplex_handle; @@ -83,7 +82,7 @@ public: * in the following directions and vector of element of a type T * with filtration on top dimensional cells. **/ - Bitmap_cubical_complex( std::vector& dimensions , std::vector& top_dimensional_cells ): + Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells ): Bitmap_cubical_complex_base(dimensions,top_dimensional_cells), key_associated_to_simplex(this->total_number_of_cells+1) { @@ -114,7 +113,7 @@ public: static Simplex_handle null_simplex() { if ( globalDbg ){cerr << "Simplex_handle null_simplex()\n";} - return std::numeric_limits::max(); + return std::numeric_limits::max(); } @@ -129,22 +128,22 @@ public: /** * Return dimension of a cell pointed by the Simplex_handle. **/ - inline unsigned dimension(const Simplex_handle& sh)const + inline unsigned dimension(Simplex_handle sh)const { if ( globalDbg ){cerr << "unsigned dimension(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) return this->get_dimension_of_a_cell( sh ); + if ( sh != std::numeric_limits::max() ) return this->get_dimension_of_a_cell( sh ); return -1; } /** * Return the filtration of a cell pointed by the Simplex_handle. **/ - T filtration(const Simplex_handle& sh) + T filtration(Simplex_handle sh) { if ( globalDbg ){cerr << "T filtration(const Simplex_handle& sh)\n";} //Returns the filtration value of a simplex. - if ( sh != std::numeric_limits::max() ) return this->data[sh]; - return std::numeric_limits::max(); + if ( sh != std::numeric_limits::max() ) return this->data[sh]; + return std::numeric_limits::max(); } /** @@ -153,16 +152,16 @@ public: static Simplex_key null_key() { if ( globalDbg ){cerr << "Simplex_key null_key()\n";} - return std::numeric_limits::max(); + return std::numeric_limits::max(); } /** * Return the key of a cube pointed by the Simplex_handle. **/ - Simplex_key key(const Simplex_handle& sh)const + Simplex_key key(Simplex_handle sh)const { if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) + if ( sh != std::numeric_limits::max() ) { return this->key_associated_to_simplex[sh]; } @@ -175,7 +174,7 @@ public: Simplex_handle simplex(Simplex_key key) { if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} - if ( key != std::numeric_limits::max() ) + if ( key != std::numeric_limits::max() ) { return this->simplex_associated_to_key[ key ]; } @@ -185,23 +184,10 @@ public: /** * Assign key to a cube pointed by the Simplex_handle **/ - void assign_key(Simplex_handle& sh, Simplex_key key) + void assign_key(Simplex_handle sh, Simplex_key key) { if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} - - - - - - - - -if ( key == std::numeric_limits::max() ) return;//TODO FAKE!!! CHEATING!!! - - - - - + if ( key == std::numeric_limits::max() ) return; this->key_associated_to_simplex[sh] = key; this->simplex_associated_to_key[key] = sh; } @@ -222,33 +208,9 @@ if ( key == std::numeric_limits::max() ) return;//TODO FAKE!!! CHEATING!!! /** * Boundary_simplex_range class provides ranges for boundary iterators. **/ - typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; - class Boundary_simplex_range - { - //Range giving access to the simplices in the boundary of a simplex. - //.begin() and .end() return type Boundary_simplex_iterator. - public: - typedef Boundary_simplex_iterator const_iterator; - Boundary_simplex_range(const Simplex_handle& sh , Bitmap_cubical_complex* CC_):sh(sh),CC(CC_) - { - this->boundary_elements = this->CC->get_boundary_of_a_cell( sh ); - } - Boundary_simplex_iterator begin() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator begin\n";} - return this->boundary_elements.begin(); + typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; + typedef typename std::vector< Simplex_handle > Boundary_simplex_range; - } - Boundary_simplex_iterator end() - { - if ( globalDbg ){cerr << "Boundary_simplex_iterator end()\n";} - return this->boundary_elements.end(); - } - private: - Simplex_handle sh; - Bitmap_cubical_complex* CC; - std::vector< Simplex_handle > boundary_elements; - }; /** @@ -341,13 +303,10 @@ if ( key == std::numeric_limits::max() ) return;//TODO FAKE!!! CHEATING!!! /** * boundary_simplex_range creates an object of a Boundary_simplex_range class * that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh) - { - if ( globalDbg ){cerr << "Boundary_simplex_range boundary_simplex_range(Simplex_handle& sh)\n";} - //Returns a range giving access to all simplices of the boundary of a simplex, - //i.e. the set of codimension 1 subsimplices of the Simplex. - return Boundary_simplex_range(sh,this); + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) + { + return this->get_boundary_of_a_cell(sh); } /** @@ -513,13 +472,12 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() if ( globalDbg ) { cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; - } - std::vector data_of_elements_from_bitmap( this->data.size() ); - std::iota (std::begin(data_of_elements_from_bitmap), std::end(data_of_elements_from_bitmap), 0); - std::sort( data_of_elements_from_bitmap.begin() , - data_of_elements_from_bitmap.end() , + } + this->simplex_associated_to_key = std::vector( this->data.size() ); + std::iota (std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); + std::sort( simplex_associated_to_key.begin() , + simplex_associated_to_key.end() , is_before_in_filtration(this) ); - this->simplex_associated_to_key = data_of_elements_from_bitmap; } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h index 3a17b4a0..c13d96e1 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h @@ -51,7 +51,7 @@ public: * Constructor of a counter class. It takes only the parameter which is the end value of the counter. * The default beginning value is a vector of the same length as the endd, filled-in with zeros. **/ - counter(std::vector const& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} + counter(const std::vector& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} //counter(std::vector< int >& endd) //{ // for ( size_t i = 0 ; i != endd.size() ; ++i ) @@ -67,7 +67,7 @@ public: * Constructor of a counter class. It takes as the input beginn and end vector. * It assumes that begin vector is lexicographically below the end vector. **/ - counter(std::vector< unsigned >& beginn , std::vector< unsigned >& endd):begin(beginn),end(endd),current(endd.size(),0) + counter(const std::vector< unsigned >& beginn , const std::vector< unsigned >& endd):begin(beginn),end(endd),current(endd.size(),0) { if ( beginn.size() != endd.size() ) throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; @@ -112,7 +112,7 @@ public: * Its aim is to find an counter corresponding to the element the following * boundary element is identified with when periodic boundary conditions are imposed. **/ - std::vector< unsigned > find_opposite( std::vector< bool >& directionsForPeriodicBCond ) + std::vector< unsigned > find_opposite( const std::vector< bool >& directionsForPeriodicBCond ) { std::vector< unsigned > result; for ( size_t i = 0 ; i != this->current.size() ; ++i ) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 4e63b9c3..fdc8511c 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -44,19 +44,19 @@ namespace Cubical_complex /** - * This is a class implementing a basic bitmap data structure to store cubical complexes. + * This is a class implementing a basic bitmap data structure to store cubical complexes. * It implements only the most basic subroutines. - * The idea of the bitmap is the following. Our aim is to have a memory efficient - * data structure to store d-dimensional cubical complex + * The idea of the bitmap is the following. Our aim is to have a memory efficient + * data structure to store d-dimensional cubical complex * C being a cubical decomposition - * of a rectangular region of a space. This is achieved by storing C as a - * vector of bits (this is where the name 'bitmap' came from). + * of a rectangular region of a space. This is achieved by storing C as a + * vector of bits (this is where the name 'bitmap' came from). * Each cell is represented by a single - * bit (in case of black and white bitmaps, or by a single element of a type T - * (here T is a filtration type of a bitmap, typically a double). + * bit (in case of black and white bitmaps, or by a single element of a type T + * (here T is a filtration type of a bitmap, typically a double). * All the informations needed for homology and - * persistent homology computations (like dimension of a cell, boundary and - * coboundary elements of a cell, are then obtained from the + * persistent homology computations (like dimension of a cell, boundary and + * coboundary elements of a cell, are then obtained from the * position of the element in C. * The default filtration used in this implementation is the lower star filtration. */ @@ -65,49 +65,49 @@ class Bitmap_cubical_complex_base { public: /** - * There are a few constructors of a Bitmap_cubical_complex_base class. - * First one, that takes vector, creates an empty bitmap of a dimension equal + * There are a few constructors of a Bitmap_cubical_complex_base class. + * First one, that takes vector, creates an empty bitmap of a dimension equal * the number of elements in the * input vector and size in the i-th dimension equal the number in the position i-of the input vector. */ - Bitmap_cubical_complex_base( std::vector& sizes ); + Bitmap_cubical_complex_base( const std::vector& sizes ); /** - * The second constructor takes as a input a Perseus style file. For more details, - * please consult the documentations of + * The second constructor takes as a input a Perseus style file. For more details, + * please consult the documentations of * Perseus software as well as examples attached to this * implementation. **/ Bitmap_cubical_complex_base( const char* perseus_style_file ); /** - * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) + * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) * together with vector of filtration values of top dimensional cells. **/ - Bitmap_cubical_complex_base( std::vector& dimensions , const std::vector& top_dimensional_cells ); + Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells ); /** - * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell - * and get_cell_data are the basic + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell + * and get_cell_data are the basic * functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a * non-negative integer, indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to * the positions of (co)boundary element of the input cell. */ inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; /** - * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, - * get_dimension_of_a_cell and get_cell_data are the basic + * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, + * get_dimension_of_a_cell and get_cell_data are the basic * functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. - * The input parameter of all of those function is a non-negative integer, + * value form a position of a cell in the structure of a bitmap. + * The input parameter of all of those function is a non-negative integer, * indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if - * non-negative integers pointing to the + * In the case of functions that compute (co)boundary, the output is a vector if + * non-negative integers pointing to the * positions of (co)boundary element of the input cell. **/ inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; /** - * In the case of get_dimension_of_a_cell function, the output is a non-negative integer + * In the case of get_dimension_of_a_cell function, the output is a non-negative integer * indicating the dimension of a cell. **/ inline unsigned get_dimension_of_a_cell( size_t cell )const; @@ -118,11 +118,11 @@ public: /** - * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. + * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. * Then, there are a few ways one can pick the filtration of lower dimensional - * cells. The most typical one is by so called lower star filtration. This function is always called by any + * cells. The most typical one is by so called lower star filtration. This function is always called by any * constructor which takes the top dimensional cells. If you use such a constructor, - * then there is no need to call this function. Call it only if you are putting the filtration + * then there is no need to call this function. Call it only if you are putting the filtration * of the cells by your own (for instance by using Top_dimensional_cells_iterator). **/ void impose_lower_star_filtration();//assume that top dimensional cells are already set. @@ -149,7 +149,7 @@ public: //ITERATORS /** - * Iterator through all cells in the complex (in order they appear in the structure -- i.e. + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ typedef typename std::vector< T >::iterator all_cells_iterator; @@ -174,7 +174,7 @@ public: } /** - * Iterator through top dimensional cells of the complex. The cells appear in order they are stored + * Iterator through top dimensional cells of the complex. The cells appear in order they are stored * in the structure (i.e. in lexicographical order) **/ class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > @@ -184,7 +184,7 @@ public: { this->counter = std::vector(b.dimension()); std::fill( this->counter.begin() , this->counter.end() , 0 ); - } + } Top_dimensional_cells_iterator operator++() { //first find first element of the counter that can be increased: @@ -298,7 +298,7 @@ protected: std::vector multipliers; std::vector data; size_t total_number_of_cells; - void set_up_containers( std::vector& sizes ) + void set_up_containers( const std::vector& sizes ) { unsigned multiplier = 1; for ( size_t i = 0 ; i != sizes.size() ; ++i ) @@ -315,7 +315,7 @@ protected: this->data = data; } - size_t compute_position_in_bitmap( std::vector< unsigned >& counter ) + size_t compute_position_in_bitmap( const std::vector< unsigned >& counter ) { size_t position = 0; for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) @@ -337,9 +337,9 @@ protected: return counter; } - std::vector< size_t > + std::vector< size_t > generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions - ( std::vector< bool >& directions_for_periodic_b_cond ); + ( const std::vector< bool >& directions_for_periodic_b_cond ); }; @@ -348,7 +348,7 @@ protected: template ostream& operator << ( ostream & out , const Bitmap_cubical_complex_base& b ) { - for ( typename Bitmap_cubical_complex_base::all_cells_const_iterator + for ( typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) { out << *it << " "; @@ -359,14 +359,14 @@ ostream& operator << ( ostream & out , const Bitmap_cubical_complex_base& b ) template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( std::vector& sizes ) +( const std::vector& sizes ) { this->set_up_containers( sizes ); } template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) +( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) { this->set_up_containers( sizes_in_following_directions ); @@ -377,7 +377,7 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base } if ( number_of_top_dimensional_elements != top_dimensional_cells.size() ) { - cerr << + cerr << "Error in constructor\ Bitmap_cubical_complex_base\ ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ @@ -432,10 +432,10 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus inFiltration >> filtrationLevel; if ( dbg ) { - cerr << "Cell of an index : " - << it.compute_index_in_bitmap() - << " and dimension: " - << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) << " get the value : " << filtrationLevel << endl; } *it = filtrationLevel; @@ -449,51 +449,18 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const { - bool bdg = false; - //first of all, we need to take the list of coordinates in which the cell has nonzero length. - //We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensions_in_which_cell_has_nonzero_length; - unsigned dimension = 0; + std::vector< size_t > boundary_elements; size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { unsigned position = cell1/multipliers[i-1]; if ( position%2 == 1 ) - { - dimensions_in_which_cell_has_nonzero_length.push_back(i-1); - dimension++; + { + boundary_elements.push_back( cell - multipliers[ i-1 ] ); + boundary_elements.push_back( cell + multipliers[ i-1 ] ); } cell1 = cell1%multipliers[i-1]; } - - if (bdg) - { - cerr << "dimensions_in_which_cell_has_nonzero_length : \n"; - for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) - { - cerr << dimensions_in_which_cell_has_nonzero_length[i] << endl; - } - getchar(); - } - - std::vector< size_t > boundary_elements( 2*dimensions_in_which_cell_has_nonzero_length.size() ); - if ( dimensions_in_which_cell_has_nonzero_length.size() == 0 )return boundary_elements; - for ( size_t i = 0 ; i != dimensions_in_which_cell_has_nonzero_length.size() ; ++i ) - { - //boundary_elements.push_back( cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); - //boundary_elements.push_back( cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ] ); - boundary_elements[2*i] = cell - multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ]; - boundary_elements[2*i+1] = cell + multipliers[ dimensions_in_which_cell_has_nonzero_length[i] ]; - - - - if (bdg) cerr << "multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " - << multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; - if (bdg) cerr << "cell - multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " - << cell - multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; - if (bdg) cerr << "cell + multipliers[dimensions_in_which_cell_has_nonzero_length[i]] : " - << cell + multipliers[dimensions_in_which_cell_has_nonzero_length[i]] << endl; - } return boundary_elements; } @@ -504,7 +471,7 @@ template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { bool bdg = false; - //first of all, we need to take the list of coordinates in which the cell has nonzero length. + //first of all, we need to take the list of coordinates in which the cell has nonzero length. //We do it by using modified version to compute dimension of a cell: std::vector< unsigned > dimensions_in_which_cell_has_zero_length; unsigned dimension = 0; @@ -547,20 +514,20 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( cerr << "Dimension : " << i << endl; if (counter[dimensions_in_which_cell_has_zero_length[i]] == 0) { - cerr << "In dimension : " << i + cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; } - if ( counter[dimensions_in_which_cell_has_zero_length[i]] - == + if ( counter[dimensions_in_which_cell_has_zero_length[i]] + == 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) { - cerr << "In dimension : " << i + cerr << "In dimension : " << i << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; } } - if ( (cell > multipliers[dimensions_in_which_cell_has_zero_length[i]]) + if ( (cell > multipliers[dimensions_in_which_cell_has_zero_length[i]]) && (counter[dimensions_in_which_cell_has_zero_length[i]] != 0) ) //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != 0 ) { @@ -570,13 +537,13 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( } coboundary_elements.push_back( cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] ); } - if ( - (cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && - (counter[dimensions_in_which_cell_has_zero_length[i]] - != - 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) + if ( + (cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && + (counter[dimensions_in_which_cell_has_zero_length[i]] + != + 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) ) - //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != + //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != //2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) { coboundary_elements.push_back( cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] ); @@ -629,12 +596,12 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { bool dbg = false; - //this vector will be used to check which elements have already been taken care of + //this vector will be used to check which elements have already been taken care of //in imposing lower star filtration: std::vector is_this_cell_considered( this->data.size() , false ); std::vector indices_to_consider; - //we assume here that we already have a filtration on the top dimensional cells and + //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) @@ -699,7 +666,7 @@ bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , ch template std::vector< size_t > Bitmap_cubical_complex_base:: generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions -( std::vector< bool >& directions_for_periodic_b_cond ) +( const std::vector< bool >& directions_for_periodic_b_cond ) { bool dbg = false; if ( this->sizes.size() != directions_for_periodic_b_cond.size() ) @@ -758,4 +725,4 @@ generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions } -} \ No newline at end of file +} -- cgit v1.2.3 From 1884df27964e344ac0004964c633ba01d4a6ae29 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Sun, 27 Dec 2015 09:25:07 +0000 Subject: COrrestions suggested by Marc just before Chrismas. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@948 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b5391c6584d8042646fea5ca17e250fcfc3dd85f --- .../include/gudhi/Bitmap_cubical_complex.h | 6 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 121 +++++++++------------ 2 files changed, 55 insertions(+), 72 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index c082caba..b324d272 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -278,7 +278,8 @@ public: //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. public: - typedef Filtration_simplex_iterator const_iterator; + typedef Filtration_simplex_iterator const_iterator; + typedef Filtration_simplex_iterator iterator; Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; Filtration_simplex_iterator begin() { @@ -430,7 +431,8 @@ public: //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. public: - typedef Skeleton_simplex_iterator const_iterator; + typedef Skeleton_simplex_iterator const_iterator; + typedef Skeleton_simplex_iterator iterator; Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; Skeleton_simplex_iterator begin() { diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index fdc8511c..54d60325 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -183,7 +183,7 @@ public: Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) { this->counter = std::vector(b.dimension()); - std::fill( this->counter.begin() , this->counter.end() , 0 ); + //std::fill( this->counter.begin() , this->counter.end() , 0 ); } Top_dimensional_cells_iterator operator++() { @@ -327,7 +327,8 @@ protected: std::vector compute_counter_for_given_cell( size_t cell )const { - std::vector counter; + std::vector counter; + counter.reserve( this->sizes.size() ); for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) { counter.push_back(cell/this->multipliers[dim-1]); @@ -380,11 +381,11 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base cerr << "Error in constructor\ Bitmap_cubical_complex_base\ - ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ + ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ Number of top dimensional elements that follow from sizes_in_following_directions vector is different\ than the size of top_dimensional_cells vector." << endl; throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ - std::vector top_dimensional_cells )\ + std::vector top_dimensional_cells )\ . Number of top dimensional elements that follow from sizes_in_following_directions vector is different than the\ size of top_dimensional_cells vector."); } @@ -411,7 +412,8 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;} - std::vector sizes; + std::vector sizes; + sizes.reserve( dimensionOfData ); for ( size_t i = 0 ; i != dimensionOfData ; ++i ) { unsigned size_in_this_dimension; @@ -449,17 +451,21 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const { - std::vector< size_t > boundary_elements; + std::vector< size_t > boundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + boundary_elements.reserve( this->dimension()*2 ); + size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { - unsigned position = cell1/multipliers[i-1]; + unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 1 ) { - boundary_elements.push_back( cell - multipliers[ i-1 ] ); - boundary_elements.push_back( cell + multipliers[ i-1 ] ); + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); } - cell1 = cell1%multipliers[i-1]; + cell1 = cell1%this->multipliers[i-1]; } return boundary_elements; } @@ -470,84 +476,48 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( si template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { - bool bdg = false; //first of all, we need to take the list of coordinates in which the cell has nonzero length. //We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensions_in_which_cell_has_zero_length; + std::vector< unsigned > dimensions_in_which_cell_has_zero_length; + + //Speed traded of for memory. Check if it is better in practice. + dimensions_in_which_cell_has_zero_length.reserve( this->dimension()*2 ); + unsigned dimension = 0; size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { - unsigned position = cell1/multipliers[i-1]; + unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 0 ) { dimensions_in_which_cell_has_zero_length.push_back(i-1); dimension++; } - cell1 = cell1%multipliers[i-1]; + cell1 = cell1%this->multipliers[i-1]; } std::vector counter = this->compute_counter_for_given_cell( cell ); - //reverse(counter.begin() , counter.end()); + std::vector< size_t > coboundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + coboundary_elements.reserve ( dimensions_in_which_cell_has_zero_length.size()*2 ); - if (bdg) - { - cerr << "dimensions_in_which_cell_has_zero_length : \n"; - for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) - { - cerr << dimensions_in_which_cell_has_zero_length[i] << endl; - } - cerr << "\n counter : " << endl; - for ( size_t i = 0 ; i != counter.size() ; ++i ) - { - cerr << counter[i] << endl; - } - getchar(); - } - - std::vector< size_t > coboundary_elements; if ( dimensions_in_which_cell_has_zero_length.size() == 0 )return coboundary_elements; for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) { - if ( bdg ) - { - cerr << "Dimension : " << i << endl; - if (counter[dimensions_in_which_cell_has_zero_length[i]] == 0) - { - cerr << "In dimension : " << i - << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; - } - if ( counter[dimensions_in_which_cell_has_zero_length[i]] - == - 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) - { - cerr << "In dimension : " << i - << " we cannot substract, since we will jump out of a Bitmap_cubical_complex_base \n"; - } - } - - - if ( (cell > multipliers[dimensions_in_which_cell_has_zero_length[i]]) + if ( (cell > this->multipliers[dimensions_in_which_cell_has_zero_length[i]]) && (counter[dimensions_in_which_cell_has_zero_length[i]] != 0) ) - //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != 0 ) { - if ( bdg ) - { - cerr << "Subtracting : " << cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] << endl; - } - coboundary_elements.push_back( cell - multipliers[dimensions_in_which_cell_has_zero_length[i]] ); + coboundary_elements.push_back( cell - this->multipliers[dimensions_in_which_cell_has_zero_length[i]] ); } if ( - (cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && + (cell + this->multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && (counter[dimensions_in_which_cell_has_zero_length[i]] != 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) ) - //if ( counter[dimensions_in_which_cell_has_zero_length[i]] != - //2*this->sizes[dimensions_in_which_cell_has_zero_length[i]] ) { - coboundary_elements.push_back( cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] ); - if ( bdg )cerr << "Adding : " << cell + multipliers[dimensions_in_which_cell_has_zero_length[i]] << endl; + coboundary_elements.push_back( cell + this->multipliers[dimensions_in_which_cell_has_zero_length[i]] ); } } return coboundary_elements; @@ -566,12 +536,12 @@ unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell( size_t cell )c unsigned dimension = 0; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { - unsigned position = cell/multipliers[i-1]; + unsigned position = cell/this->multipliers[i-1]; if (dbg)cerr << "i-1 :" << i-1 << endl; if (dbg)cerr << "cell : " << cell << endl; if (dbg)cerr << "position : " << position << endl; - if (dbg)cerr << "multipliers["<multipliers[i-1]; } return dimension; } @@ -599,8 +569,15 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() //this vector will be used to check which elements have already been taken care of //in imposing lower star filtration: std::vector is_this_cell_considered( this->data.size() , false ); - - std::vector indices_to_consider; + + size_t size_to_reserve = 1; + for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) + { + size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); + } + + std::vector indices_to_consider; + indices_to_consider.reserve( size_to_reserve ); //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); @@ -672,12 +649,17 @@ generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions if ( this->sizes.size() != directions_for_periodic_b_cond.size() ) throw "directions_for_periodic_b_cond vector size is different from the size of the bitmap. Program terminate \n"; - std::vector sizes( this->sizes.size() ); - for ( size_t i = 0 ; i != this->sizes.size() ; ++i )sizes[i] = 2*this->sizes[i]; + std::vector sizes; + sizes.reserve( this->sizes.size() ); + for ( size_t i = 0 ; i != this->sizes.size() ; ++i ) + { + sizes.push_back(2*this->sizes[i]); + } counter c( sizes ); - std::vector< size_t > result; + std::vector< size_t > result; + result.reserve( this->data.size() ); for ( size_t i = 0 ; i != this->data.size() ; ++i ) { @@ -685,7 +667,6 @@ generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions if ( !c.isFinal() ) { position = i; - //result.push_back( i ); } else { -- cgit v1.2.3 From 28d0848f733f0dc6a019b3328c80168d10e0a5ae Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 8 Jan 2016 13:26:27 +0000 Subject: Adding a first vesion of a functionality that provide periodic boundary codnitions. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@955 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ae60d98a6b2c15c2f7152663c3b05d40f0a56e86 --- .../example/Bitmap_cubical_complex.cpp | 146 ++++++++++----------- ...ubical_complex_periodic_boundary_conditions.cpp | 72 ++++++++++ src/Bitmap_cubical_complex/example/CMakeLists.txt | 3 + 3 files changed, 148 insertions(+), 73 deletions(-) create mode 100644 src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index e56428b6..ed141ed9 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -1,73 +1,73 @@ - /* 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): Pawel Dlotko - * - * 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 . - */ - - -//for persistence algorithm -#include -#include -#include - - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff -#include -#include - -using namespace std; - -int main( int argc , char** argv ) -{ - cout << "This program computes persistent homology, by using bitmap_cubical_complex class,\ - of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are\ - numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are\ - filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a\ - Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex b( argv[1] ); - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out(ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 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): Pawel Dlotko + * + * 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 +#include +#include + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + + +int main( int argc , char** argv ) +{ + cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex b( argv[1] ); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp new file mode 100644 index 00000000..fa60d4f3 --- /dev/null +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp @@ -0,0 +1,72 @@ + /* 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): Pawel Dlotko + * + * 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 +#include +#include + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + +int main( int argc , char** argv ) +{ + cout << "This program computes persistent homology, by using Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex_periodic_boundary_conditions b( argv[1] ); + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex_periodic_boundary_conditions, Field_Zp > pcoh(b,true); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index dd252a79..26796e9d 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -10,3 +10,6 @@ add_executable ( Random_bitmap_cubical_complex Random_bitmap_cubical_complex.cpp target_link_libraries(Random_bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap_cubical_complex 2 100 100) +add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp ) +target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) + -- cgit v1.2.3 From 11b195d4e26d48cdc56883957cbad16e298e43ca Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 12 Jan 2016 16:07:10 +0000 Subject: Fix alpha complex remarks and bugs git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@957 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fa837fd1a4373c2322db16353d98767907f34c79 --- CMakeLists.txt | 4 +- biblio/how_to_cite_cgal.bib | 947 +++++++++++++++++++++ src/Alpha_complex/test/CMakeLists.txt | 2 - src/GudhUI/alpha_complex_persistence.cpp | 78 -- src/GudhUI/utils/Bar_code_persistence.h | 3 +- src/GudhUI/utils/Persistence_compute.h | 15 +- src/Persistent_cohomology/example/CMakeLists.txt | 100 ++- .../example/alpha_complex_persistence.cpp | 92 +- .../example/rips_persistence.cpp | 3 +- src/Simplex_tree/include/gudhi/Simplex_tree.h | 81 +- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 56 +- src/common/include/gudhi/distance_functions.h | 4 +- src/common/include/gudhi/reader_utils.h | 4 +- 13 files changed, 1140 insertions(+), 249 deletions(-) create mode 100644 biblio/how_to_cite_cgal.bib delete mode 100644 src/GudhUI/alpha_complex_persistence.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d0770dd7..54e86f72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ 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_MODULE_PATH = ${CMAKE_MODULE_PATH}") # Generate GUDHI official version file @@ -22,7 +22,7 @@ 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 -fsanitize=memory -fno-omit-frame-pointer -Wall -Wpedantic -Wsign-compare") + 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 -O1") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") endif() diff --git a/biblio/how_to_cite_cgal.bib b/biblio/how_to_cite_cgal.bib new file mode 100644 index 00000000..7336ee81 --- /dev/null +++ b/biblio/how_to_cite_cgal.bib @@ -0,0 +1,947 @@ +@book{ cgal:eb-15b +, title = "{CGAL} User and Reference Manual" +, author = "{The CGAL Project}" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, year = 2015 +, url = "http://doc.cgal.org/4.7/Manual/packages.html" +} +@incollection{cgal:h-af-15b +, author = "Michael Hemmer" +, title = "Algebraic Foundations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAlgebraicFoundationsSummary" +, year = 2015 +} + +@incollection{cgal:hhkps-nt-15b +, author = "Michael Hemmer and Susan Hert and Sylvain Pion and Stefan Schirra" +, title = "Number Types" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgNumberTypesSummary" +, year = 2015 +} + +@incollection{cgal:h-ma-15b +, author = "Michael Hemmer and Sylvain Pion" +, title = "Modular Arithmetic" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgModularArithmeticSummary" +, year = 2015 +} + +@incollection{cgal:h-p-15b +, author = "Michael Hemmer" +, title = "Polynomial" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolynomialSummary" +, year = 2015 +} + +@incollection{cgal:bht-ak-15b +, author = "Eric Berberich and Michael Hemmer and Michael Kerber and Sylvain Lazard and Luis Pe{\~n}aranda and Monique Teillaud" +, title = "Algebraic Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAlgebraicKerneldSummary" +, year = 2015 +} + +@incollection{cgal:h-msms-15b +, author = "Michael Hoffmann" +, title = "Monotone and Sorted Matrix Search" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMatrixSearchSummary" +, year = 2015 +} + +@incollection{cgal:fgsw-lqps-15b +, author = "Kaspar Fischer and Bernd G{\"a}rtner and Sven Sch{\"o}nherr and Frans Wessendorp" +, title = "Linear and Quadratic Programming Solver" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgQPSolverSummary" +, year = 2015 +} + +@incollection{cgal:bfghhkps-lgk23-15b +, author = "Herv{\'e} Br{\"o}nnimann and Andreas Fabri and Geert-Jan Giezeman and Susan Hert and Michael Hoffmann and Lutz Kettner and Sylvain Pion and Stefan Schirra" +, title = "{2D} and {3D} Linear Geometry Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgKernel23Summary" +, year = 2015 +} + +@incollection{cgal:s-gkd-15b +, author = "Michael Seel" +, title = "{dD} Geometry Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgKernelDSummary" +, year = 2015 +} + +@incollection{cgal:cpt-cgk2-15b +, author = "Pedro Machado Manh{\~a}es de Castro and Sylvain Pion and Monique Teillaud" +, title = "{2D} Circular Geometry Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgCircularKernel2Summary" +, year = 2015 +} + +@incollection{cgal:cclt-sgk3-15b +, author = "Pedro Machado Manh{\~a}es de Castro and Fr{\'e}d{\'e}ric Cazals and S{\'e}bastien Loriot and Monique Teillaud" +, title = "{3D} Spherical Geometry Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSphericalKernel3Summary" +, year = 2015 +} + +@incollection{cgal:hs-chep2-15b +, author = "Susan Hert and Stefan Schirra" +, title = "{2D} Convex Hulls and Extreme Points" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgConvexHull2Summary" +, year = 2015 +} + +@incollection{cgal:hs-ch3-15b +, author = "Susan Hert and Stefan Schirra" +, title = "{3D} Convex Hulls" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgConvexHull3Summary" +, year = 2015 +} + +@incollection{cgal:hs-chdt3-15b +, author = "Susan Hert and Michael Seel" +, title = "{dD} Convex Hulls and Delaunay Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgConvexHullDSummary" +, year = 2015 +} + +@incollection{cgal:gw-p2-15b +, author = "Geert-Jan Giezeman and Wieger Wesselink" +, title = "{2D} Polygons" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolygon2Summary" +, year = 2015 +} + +@incollection{cgal:fwzh-rbso2-15b +, author = "Efi Fogel and Ophir Setter and Ron Wein and Guy Zucker and Baruch Zukerman and Dan Halperin" +, title = "{2D} Regularized Boolean Set-Operations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBooleanSetOperations2Summary" +, year = 2015 +} + +@incollection{cgal:s-bonp2-15b +, author = "Michael Seel" +, title = "{2D} Boolean Operations on Nef Polygons" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgNef2Summary" +, year = 2015 +} + +@incollection{cgal:hk-bonpes2-15b +, author = "Peter Hachenberger and Lutz Kettner" +, title = "{2D} Boolean Operations on Nef Polygons Embedded on the Sphere" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgNefS2Summary" +, year = 2015 +} + +@incollection{cgal:h-pp2-15b +, author = "Susan Hert" +, title = "{2D} Polygon Partitioning" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolygonPartitioning2Summary" +, year = 2015 +} + +@incollection{cgal:c-sspo2-15b +, author = "Fernando Cacciola" +, title = "{2D} Straight Skeleton and Polygon Offsetting" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgStraightSkeleton2Summary" +, year = 2015 +} + +@incollection{cgal:w-rms2-15b +, author = "Ron Wein and Alon Baram and Eyal Flato and Efi Fogel and Michael Hemmer and Sebastian Morr" +, title = "{2D} Minkowski Sums" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMinkowskiSum2Summary" +, year = 2015 +} + +@incollection{cgal:f-ps2-15b +, author = "Andreas Fabri" +, title = "{2D} Polyline Simplification" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolylineSimplification2Summary" +, year = 2015 +} + +@incollection{hhb-visibility-2-15b +, author = "Michael Hemmer and Kan Huang and Francisc Bungiu and Ning Xu" +, title = "{2D} Visibility Computation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgVisibility_2Summary" +, year = 2015 +} + +@incollection{cgal:k-ps-15b +, author = "Lutz Kettner" +, title = "{3D} Polyhedral Surface" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolyhedronSummary" +, year = 2015 +} + +@incollection{cgal:k-hds-15b +, author = "Lutz Kettner" +, title = "Halfedge Data Structures" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgHDSSummary" +, year = 2015 +} + +@incollection{cgal:bsmf-sm-15b +, author = "Mario Botsch and Daniel Sieger and Philipp Moeller and Andreas Fabri" +, title = "Surface Mesh" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceMeshSummary" +, year = 2015 +} + +@incollection{cgal:d-cm-15b +, author = "Guillaume Damiand" +, title = "Combinatorial Maps" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgCombinatorialMapsSummary" +, year = 2015 +} + +@incollection{cgal:d-lcc-12-15b +, author = "Guillaume Damiand" +, title = "Linear Cell Complex" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgLinearCellComplexSummary" +, year = 2015 +} + +@incollection{cgal:hk-bonp3-15b +, author = "Peter Hachenberger and Lutz Kettner" +, title = "{3D} Boolean Operations on Nef Polyhedra" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgNef3Summary" +, year = 2015 +} + +@incollection{cgal:h-emspe-15b +, author = "Peter Hachenberger" +, title = "Convex Decomposition of Polyhedra" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgConvexDecomposition3Summary" +, year = 2015 +} + +@incollection{cgal:h-msp3-15b +, author = "Peter Hachenberger" +, title = "{3D} Minkowski Sum of Polyhedra" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMinkowskiSum3Summary" +, year = 2015 +} + +@incollection{cgal:wfzh-a2-15b +, author = "Ron Wein and Eric Berberich and Efi Fogel and Dan Halperin and Michael Hemmer and Oren Salzman and Baruch Zukerman" +, title = "{2D} Arrangements" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgArrangement2Summary" +, year = 2015 +} + +@incollection{cgal:wfz-ic2-15b +, author = "Baruch Zukerman and Ron Wein and Efi Fogel" +, title = "{2D} Intersection of Curves" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgIntersectionOfCurves2Summary" +, year = 2015 +} + +@incollection{cgal:p-sr2-15b +, author = "Eli Packer" +, title = "{2D} Snap Rounding" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSnapRounding2Summary" +, year = 2015 +} + +@incollection{cgal:w-e2-15b +, author = "Ron Wein" +, title = "{2D} Envelopes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgEnvelope2Summary" +, year = 2015 +} + +@incollection{cgal:mwz-e3-15b +, author = "Dan Halperin and Michal Meyerovitch and Ron Wein and Baruch Zukerman" +, title = "{3D} Envelopes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgEnvelope3Summary" +, year = 2015 +} + +@incollection{cgal:y-t2-15b +, author = "Mariette Yvinec" +, title = "{2D} Triangulation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTriangulation2Summary" +, year = 2015 +} + +@incollection{cgal:py-tds2-15b +, author = "Sylvain Pion and Mariette Yvinec" +, title = "{2D} Triangulation Data Structure" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTDS2Summary" +, year = 2015 +} + +@incollection{cgal:k-pt2-13-15b +, author = "Nico Kruithof" +, title = "{2D} Periodic Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPeriodic2Triangulation2Summary" +, year = 2015 +} + +@incollection{cgal:pt-t3-15b +, author = "Cl{\'e}ment Jamin and Sylvain Pion and Monique Teillaud" +, title = "{3D} Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTriangulation3Summary" +, year = 2015 +} + +@incollection{cgal:pt-tds3-15b +, author = "Cl{\'e}ment Jamin and Sylvain Pion and Monique Teillaud" +, title = "{3D} Triangulation Data Structure" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTDS3Summary" +, year = 2015 +} + +@incollection{cgal:ct-pt3-15b +, author = "Manuel Caroli and Monique Teillaud" +, title = "{3D} Periodic Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPeriodic3Triangulation3Summary" +, year = 2015 +} + +@incollection{cgal:hdj-t-15b +, author = "Samuel Hornus and Olivier Devillers and Cl{\'e}ment Jamin" +, title = "{dD} Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTriangulationsSummary" +, year = 2015 +} + +@incollection{cgal:d-as2-15b +, author = "Tran Kai Frank Da" +, title = "{2D} Alpha Shapes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAlphaShape2Summary" +, year = 2015 +} + +@incollection{cgal:dy-as3-15b +, author = "Tran Kai Frank Da and S{\'e}bastien Loriot and Mariette Yvinec" +, title = "{3D} Alpha Shapes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAlphaShapes3Summary" +, year = 2015 +} + +@incollection{cgal:k-sdg2-15b +, author = "Menelaos Karavelas" +, title = "{2D} Segment Delaunay Graphs" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSegmentDelaunayGraph2Summary" +, year = 2015 +} + +@incollection{cgal:cdp-sdglinf2-15b +, author = "Panagiotis Cheilaris and Sandeep Kumar Dey and Evanthia Papadopoulou" +, title = "L Infinity Segment Delaunay Graphs" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSDGLinfSummary" +, year = 2015 +} + +@incollection{cgal:ky-ag2-15b +, author = "Menelaos Karavelas and Mariette Yvinec" +, title = "{2D} Apollonius Graphs (Delaunay Graphs of Disks)" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgApolloniusGraph2Summary" +, year = 2015 +} + +@incollection{cgal:k-vda2-15b +, author = "Menelaos Karavelas" +, title = "{2D} Voronoi Diagram Adaptor" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgVoronoiDiagramAdaptor2Summary" +, year = 2015 +} + +@incollection{cgal:r-ctm2-15b +, author = "Laurent Rineau" +, title = "{2D} Conforming Triangulations and Meshes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMesh2Summary" +, year = 2015 +} + +@incollection{cgal:ry-smg-15b +, author = "Laurent Rineau and Mariette Yvinec" +, title = "{3D} Surface Mesh Generation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceMesher3Summary" +, year = 2015 +} + +@incollection{cgal:asg-srps-15b +, author = "Pierre Alliez and Laurent Saboret and Ga{\"e}l Guennebaud" +, title = "Surface Reconstruction from Point Sets" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceReconstructionFromPointSetsSummary" +, year = 2015 +} + +@incollection{cgal:ssr3-15b +, author = "Thijs van Lankveld" +, title = "Scale-Space Surface Reconstruction" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgScaleSpaceReconstruction3Summary" +, year = 2015 +} + +@incollection{cgal:dc-afsr-15b +, author = "Tran Kai Frank Da and David Cohen-Steiner" +, title = "Advancing Front Surface Reconstruction" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAdvancingFrontSurfaceReconstructionSummary" +, year = 2015 +} + +@incollection{cgal:k-ssm3-15b +, author = "Nico Kruithof" +, title = "{3D} Skin Surface Meshing" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSkinSurface3Summary" +, year = 2015 +} + +@incollection{cgal:rty-m3-15b +, author = "Pierre Alliez and Cl{\'e}ment Jamin and Laurent Rineau and St{\'e}phane Tayeb and Jane Tournois and Mariette Yvinec" +, title = "{3D} Mesh Generation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMesh_3Summary" +, year = 2015 +} + +@incollection{cgal:lty-pmp-15b +, author = "S{\'e}bastien Loriot and Jane Tournois and Ilker O. Yaz" +, title = "Polygon Mesh Processing" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolygonMeshProcessingSummary" +, year = 2015 +} + +@incollection{cgal:s-ssm2-15b +, author = "Le-Jeng Andy Shiue" +, title = "{3D} Surface Subdivision Methods" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceSubdivisionMethods3Summary" +, year = 2015 +} + +@incollection{cgal:y-smsimpl-15b +, author = "Ilker O. Yaz and S{\'e}bastien Loriot" +, title = "Triangulated Surface Mesh Segmentation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceSegmentationSummary" +, year = 2015 +} + +@incollection{cgal:c-tsms-12-15b +, author = "Fernando Cacciola" +, title = "Triangulated Surface Mesh Simplification" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceMeshSimplificationSummary" +, year = 2015 +} + +@incollection{cgal:lsxy-tsmd-15b +, author = "S{\'e}bastien Loriot and Olga Sorkine-Hornung and Yin Xu and Ilker O. Yaz" +, title = "Triangulated Surface Mesh Deformation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceModelingSummary" +, year = 2015 +} + +@incollection{cgal:sal-pptsm2-15b +, author = "Laurent Saboret and Pierre Alliez and Bruno L{\'e}vy" +, title = "Planar Parameterization of Triangulated Surface Meshes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceParameterizationSummary" +, year = 2015 +} + +@incollection{cgal:klcdv-tsmsp-15b +, author = "Stephen Kiazyk and S{\'e}bastien Loriot and {\'E}ric Colin de Verdi{\`e}re" +, title = "Triangulated Surface Mesh Shortest Paths" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceMeshShortestPathSummary" +, year = 2015 +} + +@incollection{cgal:glt-tsms-15b +, author = "Xiang Gao and S{\'e}bastien Loriot and Andrea Tagliasacchi" +, title = "Triangulated Surface Mesh Skeletonization" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMeanCurvatureSkeleton3Summary" +, year = 2015 +} + +@incollection{cgal:cp-arutsm-15b +, author = "Marc Pouget and Fr{\'e}d{\'e}ric Cazals" +, title = "Approximation of Ridges and Umbilics on Triangulated Surface Meshes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgRidges_3Summary" +, year = 2015 +} + +@incollection{cgal:pc-eldp-15b +, author = "Marc Pouget and Fr{\'e}d{\'e}ric Cazals" +, title = "Estimation of Local Differential Properties of Point-Sampled Surfaces" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgJet_fitting_3Summary" +, year = 2015 +} + +@incollection{cgal:ass-psp-15b +, author = "Pierre Alliez and Cl{\'e}ment Jamin and Quentin M{\'e}rigot and Jocelyn Meyron and Laurent Saboret and Nader Salman and Shihao Wu" +, title = "Point Set Processing" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPointSetProcessingSummary" +, year = 2015 +} + +@incollection{cgal:ovja-pssd-15b +, author = "Sven Oesau and Yannick Verdie and Cl{\'e}ment Jamin and Pierre Alliez" +, title = "Point Set Shape Detection" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPointSetShapeDetection3Summary" +, year = 2015 +} + +@incollection{cgal:m-ps-15b +, author = "Abdelkrim Mebarki" +, title = "{2D} Placement of Streamlines" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPlacementOfStreamlines2Summary" +, year = 2015 +} + +@incollection{cgal:b-ss2-15b +, author = "Matthias B{\"a}sken" +, title = "{2D} Range and Neighbor Search" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPointSet2Summary" +, year = 2015 +} + +@incollection{cgal:f-isl-15b +, author = "Andreas Fabri" +, title = "Interval Skip List" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgIntervalSkipListSummary" +, year = 2015 +} + +@incollection{cgal:tf-ssd-15b +, author = "Hans Tangelder and Andreas Fabri" +, title = "{dD} Spatial Searching" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSpatialSearchingDSummary" +, year = 2015 +} + +@incollection{cgal:n-rstd-15b +, author = "Gabriele Neyer" +, title = "{dD} Range and Segment Trees" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgRangeSegmentTreesDSummary" +, year = 2015 +} + +@incollection{cgal:kmz-isiobd-15b +, author = "Lutz Kettner and Andreas Meyer and Afra Zomorodian" +, title = "Intersecting Sequences of {dD} Iso-oriented Boxes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBoxIntersectionDSummary" +, year = 2015 +} + +@incollection{cgal:atw-aabb-15b +, author = "Pierre Alliez and St{\'e}phane Tayeb and Camille Wormser" +, title = "{3D} Fast Intersection and Distance Computation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAABB_treeSummary" +, year = 2015 +} + +@incollection{cgal:dd-ss-15b +, author = "Christophe Delage and Olivier Devillers" +, title = "Spatial Sorting" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSpatialSortingSummary" +, year = 2015 +} + +@incollection{cgal:fghhs-bv-15b +, author = "Kaspar Fischer and Bernd G{\"a}rtner and Thomas Herrmann and Michael Hoffmann and Sven Sch{\"o}nherr" +, title = "Bounding Volumes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBoundingVolumesSummary" +, year = 2015 +} + +@incollection{cgal:hp-ia-15b +, author = "Michael Hoffmann and Eli Packer" +, title = "Inscribed Areas" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgInscribedAreasSummary" +, year = 2015 +} + +@incollection{cgal:fghhs-od-15b +, author = "Kaspar Fischer and Bernd G{\"a}rtner and Thomas Herrmann and Michael Hoffmann and Sven Sch{\"o}nherr" +, title = "Optimal Distances" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgOptimalDistancesSummary" +, year = 2015 +} + +@incollection{cgal:ap-pcad-15b +, author = "Pierre Alliez and Sylvain Pion and Ankit Gupta" +, title = "Principal Component Analysis" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPrincipalComponentAnalysisDSummary" +, year = 2015 +} + +@incollection{cgal:f-i-15b +, author = "Julia Fl{\"o}totto" +, title = "{2D} and Surface Function Interpolation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgInterpolation2Summary" +, year = 2015 +} + +@incollection{cgal:abha-gbc-15b +, author = "Dmitry Anisimov and David Bommes and Kai Hormann and Pierre Alliez" +, title = "{2D} Generalized Barycentric Coordinates" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBarycentric_coordinates_2Summary" +, year = 2015 +} + +@incollection{cgal:r-kds-15b +, author = "Daniel Russel" +, title = "Kinetic Data Structures" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgKdsSummary" +, year = 2015 +} + +@incollection{cgal:r-kdsf-15b +, author = "Daniel Russel" +, title = "Kinetic Framework" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgKdsFrameworkSummary" +, year = 2015 +} + +@incollection{cgal:hkpw-se-15b +, author = "Michael Hoffmann and Lutz Kettner and Sylvain Pion and Ron Wein" +, title = "STL Extensions for {CGAL}" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgStlExtensionSummary" +, year = 2015 +} + +@incollection{cgal:cfw-cbgl-15b +, author = "Andreas Fabri and Fernando Cacciola and Philipp Moeller and Ron Wein" +, title = "{CGAL} and the {Boost} Graph Library" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBGLSummary" +, year = 2015 +} + +@incollection{cgal:fs-cbpm-15b +, author = "Andreas Fabri and Laurent Saboret" +, title = "{CGAL} and {Boost} Property Maps" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgProperty_mapSummary" +, year = 2015 +} + +@incollection{cgal:dksy-hc-15b +, author = "Olivier Devillers and Lutz Kettner and Sylvain Pion and Michael Seel and Mariette Yvinec" +, title = "Handles and Circulators" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgHandlesAndCirculatorsSummary" +, year = 2015 +} + +@incollection{cgal:dhhk-gog-15b +, author = "Pedro M. M. de Castro and Olivier Devillers and Susan Hert and Michael Hoffmann and Lutz Kettner and Sven Sch{\"o}nherr and Alexandru Tifrea" +, title = "Geometric Object Generators" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgGeneratorsSummary" +, year = 2015 +} + +@incollection{cgal:kps-pthum-15b +, author = "Lutz Kettner and Sylvain Pion and Michael Seel" +, title = "Profiling tools, Hash Map, Union-find, Modifiers" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgProfilingToolsSummary" +, year = 2015 +} + +@incollection{cgal:fgk-ios-12-15b +, author = "Andreas Fabri and Geert-Jan Giezeman and Lutz Kettner" +, title = "IO Streams" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgIOstreamsSummary" +, year = 2015 +} + +@incollection{cgal:fp-gv-15b +, author = "Andreas Fabri and Sylvain Pion" +, title = "Geomview" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgGeomviewSummary" +, year = 2015 +} + +@incollection{cgal:fr-cqgvf-15b +, author = "Andreas Fabri and Laurent Rineau" +, title = "{CGAL} and the {Qt} Graphics View Framework" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgGraphicsViewSummary" +, year = 2015 +} + +@incollection{cgal:lp-gi-15b +, author = "Olivier Devillers and S{\'e}bastien Loriot and Sylvain Pion" +, title = "{CGAL} Ipelets" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgCGALIpeletsSummary" +, year = 2015 +} diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index d7c13da0..fa24e1b1 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -18,8 +18,6 @@ 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/GudhUI/alpha_complex_persistence.cpp b/src/GudhUI/alpha_complex_persistence.cpp deleted file mode 100644 index 4f85459a..00000000 --- a/src/GudhUI/alpha_complex_persistence.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - - -#include - -// to construct a Delaunay_triangulation from a OFF file -#include -#include -#include - -#include "utils/Bar_code_persistence.h" - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off " << // alpha_square_max_value[double] " << - "coeff_field_characteristic[integer > 0] min_persistence[double >= -1.0]" << std::endl; - std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0 2 0.02" << 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]); - } - - QApplication qtapp(argc, argv); - - std::string off_file_name(argv[1]); - // double alpha_square_max_value = atof(argv[2]); - double alpha_square_max_value = 1e20; - int coeff_field_characteristic = atoi(argv[2]); // argv[3] - double min_persistence = atof(argv[3]); // argv[4] - - // ---------------------------------------------------------------------------- - // 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, 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::alphacomplex::Alpha_complex, - Gudhi::persistent_cohomology::Field_Zp > pcoh(alpha_complex_from_file); - - std::cout << "coeff_field_characteristic " << coeff_field_characteristic << - " - min_persistence " << min_persistence << std::endl; - - // initializes the coefficient field for homology - pcoh.init_coefficients(coeff_field_characteristic); - - pcoh.compute_persistent_cohomology(min_persistence); - - pcoh.output_diagram(); - - std::vector> persistence_vector; - pcoh.get_persistence(persistence_vector); - - Bar_code_persistence bc_persistence; - - for (auto persistence : persistence_vector) { - bc_persistence.insert(persistence.first, persistence.second); - } - - bc_persistence.show(); - - return qtapp.exec(); -} diff --git a/src/GudhUI/utils/Bar_code_persistence.h b/src/GudhUI/utils/Bar_code_persistence.h index a1a46ea8..a4cd8156 100644 --- a/src/GudhUI/utils/Bar_code_persistence.h +++ b/src/GudhUI/utils/Bar_code_persistence.h @@ -39,7 +39,7 @@ class Bar_code_persistence { max_death = death; } - void show() { + void show(const std::string& window_title) { // Create a view, put a scene in it QGraphicsView * view = new QGraphicsView(); QGraphicsScene * scene = new QGraphicsScene(); @@ -78,6 +78,7 @@ class Bar_code_persistence { QGraphicsTextItem* dimText = scene->addText(scale_value, QFont("Helvetica", 8)); dimText->setPos(scale - (3.0 * scale_value.size()), height + 9.0 * (modulo % 2)); } + view->setWindowTitle(window_title.c_str()); // Show the view view->show(); } diff --git a/src/GudhUI/utils/Persistence_compute.h b/src/GudhUI/utils/Persistence_compute.h index 0b9961d3..1f04cc6b 100644 --- a/src/GudhUI/utils/Persistence_compute.h +++ b/src/GudhUI/utils/Persistence_compute.h @@ -46,10 +46,6 @@ struct Persistence_params { * Show persistence into output stream */ template class Persistence_compute { - private: - SkBlComplex& complex_; - std::ostream& stream_; - public: typedef typename SkBlComplex::Vertex_handle Vertex_handle; typedef typename SkBlComplex::Edge_handle Edge_handle; @@ -61,9 +57,7 @@ template class Persistence_compute { * double threshold * int p for coefficient Z_p */ - Persistence_compute(SkBlComplex& complex, std::ostream& stream, const Persistence_params& params) : - // double threshold = 0.5,unsigned dim_max = 8): - complex_(complex), stream_(stream) { + Persistence_compute(SkBlComplex& complex, std::ostream& stream, const Persistence_params& params) { // for now everything is copied, todo boost adapt iterators to points of SkBlComplex instead of copying to an // initial vector typedef std::vector Point_t; @@ -87,10 +81,11 @@ template class Persistence_compute { pcoh.init_coefficients(params.p); // put params.min_pers pcoh.compute_persistent_cohomology(params.min_pers); - stream_ << "persistence: \n"; - stream_ << "p dimension birth death: \n"; + stream << "persistence: \n"; + stream << "p dimension birth death: \n"; - pcoh.output_diagram(stream_); + pcoh.output_diagram(stream); + } }; diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index eb4ee3e3..9e96adc0 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -22,63 +22,61 @@ add_executable(persistence_from_file persistence_from_file.cpp) target_link_libraries(persistence_from_file ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) add_test(persistence_from_file_3_2_0 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 2 -m 0) add_test(persistence_from_file_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) - -if(GMPXX_FOUND AND GMP_FOUND) - message("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}") - message("GMP_LIBRARIES = ${GMP_LIBRARIES}") - - add_executable(rips_multifield_persistence rips_multifield_persistence.cpp ) - target_link_libraries(rips_multifield_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) - add_test(rips_multifield_persistence_2_71 ${CMAKE_CURRENT_BINARY_DIR}/rips_multifield_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 71 -m 100) - - add_executable ( performance_rips_persistence performance_rips_persistence.cpp ) - target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) - - if(CGAL_FOUND) - 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) - #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) - - - - if (NOT CGAL_VERSION VERSION_LESS 4.7.0) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - - include( ${CGAL_USE_FILE} ) - # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. - # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 - # A workaround is to add "-std=c++11" again. - # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html - # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html - # but it implies to use cmake version 3.1 at least. - if(NOT MSVC) - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) - if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +if(GMPXX_FOUND AND GMP_FOUND) + message("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}") + message("GMP_LIBRARIES = ${GMP_LIBRARIES}") + + add_executable(rips_multifield_persistence rips_multifield_persistence.cpp ) + target_link_libraries(rips_multifield_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) + add_test(rips_multifield_persistence_2_71 ${CMAKE_CURRENT_BINARY_DIR}/rips_multifield_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 71 -m 100) + + add_executable ( performance_rips_persistence performance_rips_persistence.cpp ) + target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) + + if(CGAL_FOUND) + 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) + #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) + + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() endif() - endif() - # - End of workaround + # - End of workaround - find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) - message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") - include( ${EIGEN3_USE_FILE} ) + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) - add_executable (alphacomplexpersistence alpha_complex_persistence.cpp) - target_link_libraries(alphacomplexpersistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_executable (alpha_complex_persistence alpha_complex_persistence.cpp) + target_link_libraries(alpha_complex_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") - endif() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") - endif () - - - - endif() + # message(WARNING "CGAL not found.") + endif() +else() + # message(WARNING "GMP not found.") endif() diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp index fbadf673..0dabdeac 100644 --- a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -1,34 +1,35 @@ #include #include +#include + // to construct a Delaunay_triangulation from a OFF file #include #include #include -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value[double] " << - "coeff_field_characteristic[integer > 0] min_persistence[double >= -1.0]" << std::endl; - std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0 2 0.02" << std::endl; - exit(-1); // ----- >> -} +void program_options(int argc, char * argv[] + , std::string & off_file_points + , std::string & output_file_diag + , Filtration_value & alpha_square_max_value + , int & coeff_field_characteristic + , Filtration_value & min_persistence); int main(int argc, char **argv) { - if (argc != 5) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } + std::string off_file_points; + std::string output_file_diag; + 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); - std::string off_file_name(argv[1]); - double alpha_square_max_value = atof(argv[2]); - int coeff_field_characteristic = atoi(argv[3]); - double min_persistence = atof(argv[4]); // ---------------------------------------------------------------------------- // 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, alpha_square_max_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_points, alpha_square_max_value); // ---------------------------------------------------------------------------- // Display information about the alpha complex @@ -49,7 +50,66 @@ int main(int argc, char **argv) { pcoh.compute_persistent_cohomology(min_persistence); - pcoh.output_diagram(); + // Output the diagram in filediag + if (output_file_diag.empty()) { + pcoh.output_diagram(); + } else { + std::cout << "Result in file: " << output_file_diag << std::endl; + std::ofstream out(output_file_diag); + pcoh.output_diagram(out); + out.close(); + } return 0; } + +void program_options(int argc, char * argv[] + , std::string & off_file_points + , std::string & output_file_diag + , Filtration_value & alpha_square_max_value + , int & coeff_field_characteristic + , Filtration_value & min_persistence) { + namespace po = boost::program_options; + po::options_description hidden("Hidden options"); + hidden.add_options() + ("input-file", po::value(&off_file_points), + "Name of file containing a point set. Format is one point per line: X1 ... Xd "); + + po::options_description visible("Allowed options", 100); + visible.add_options() + ("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()), + "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.") + ("min-persistence,m", po::value(&min_persistence), + "Minimal lifetime of homology feature to be recorded. Default is 0. Enter a negative value to see zero length intervals"); + + po::positional_options_description pos; + pos.add("input-file", 1); + + po::options_description all; + all.add(visible).add(hidden); + + po::variables_map vm; + po::store(po::command_line_parser(argc, argv). + options(all).positional(pos).run(), vm); + po::notify(vm); + + if (vm.count("help") || !vm.count("input-file")) { + std::cout << std::endl; + std::cout << "Compute the persistent homology with coefficient field Z/pZ \n"; + std::cout << "of an Alpha complex defined on a set of input points.\n \n"; + std::cout << "The output diagram contains one bar per line, written with the convention: \n"; + std::cout << " p dim b d \n"; + std::cout << "where dim is the dimension of the homological feature,\n"; + std::cout << "b and d are respectively the birth and death of the feature and \n"; + std::cout << "p is the characteristic of the field Z/pZ used for homology coefficients." << std::endl << std::endl; + + std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl << std::endl; + std::cout << visible << std::endl; + std::abort(); + } +} diff --git a/src/Persistent_cohomology/example/rips_persistence.cpp b/src/Persistent_cohomology/example/rips_persistence.cpp index 9b1ef42f..fa0449a8 100644 --- a/src/Persistent_cohomology/example/rips_persistence.cpp +++ b/src/Persistent_cohomology/example/rips_persistence.cpp @@ -30,6 +30,7 @@ #include #include +#include // infinity using namespace Gudhi; using namespace Gudhi::persistent_cohomology; @@ -114,7 +115,7 @@ void program_options(int argc, char * argv[] ("help,h", "produce help message") ("output-file,o", po::value(&filediag)->default_value(std::string()), "Name of file in which the persistence diagram is written. Default print in std::cout") - ("max-edge-length,r", po::value(&threshold)->default_value(0), + ("max-edge-length,r", po::value(&threshold)->default_value(std::numeric_limits::infinity()), "Maximal length of an edge for the Rips complex construction.") ("cpx-dimension,d", po::value(&dim_max)->default_value(1), "Maximal dimension of the Rips complex we want to compute.") diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 4b04e75a..d4f9aeae 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1160,43 +1160,28 @@ std::cout << "prune_above_filtration - filtration=" << filtration << std::endl; 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; -} - + std::vector> simplex_list_to_removed; // 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); + // 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() > threshold_); + 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); } -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); + 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 + if (simplex_list_to_removed.size() > 0) + initialize_filtration(); } } } @@ -1205,6 +1190,7 @@ std::cout << "prune_above_filtration - resize" << new_size << std::endl; * @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). */ void remove_maximal_simplex(Simplex_handle sh) { // Guarantee the simplex has no children @@ -1213,49 +1199,18 @@ std::cout << "prune_above_filtration - resize" << new_size << std::endl; // Simplex is a leaf, it means the child is the Siblings owning the leaf Siblings* child = sh->second.children(); + 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 -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/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index f6bd5411..0d73d347 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -351,7 +351,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // 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; + 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) << "] "; for (auto vertex : st.simplex_vertex_range(f_simplex)) { @@ -549,7 +549,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { // 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; + 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) << "] "; for (auto vertex : st.simplex_vertex_range(f_simplex)) { @@ -805,7 +805,7 @@ struct MyOptions : Simplex_tree_options_full_featured { }; typedef Simplex_tree miniST; -/*BOOST_AUTO_TEST_CASE(remove_maximal_simplex) { +BOOST_AUTO_TEST_CASE(remove_maximal_simplex) { std::cout << "********************************************************************" << std::endl; std::cout << "REMOVE MAXIMAL SIMPLEX" << std::endl; @@ -887,7 +887,7 @@ typedef Simplex_tree miniST; st.remove_maximal_simplex(st.find({7})); BOOST_CHECK(st == st_wo_seven); -}*/ +} BOOST_AUTO_TEST_CASE(prune_above_filtration) { std::cout << "********************************************************************" << std::endl; @@ -939,10 +939,10 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { 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 + // Display the Simplex_tree 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; + 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) << "] "; for (auto vertex : st.simplex_vertex_range(f_simplex)) { @@ -955,35 +955,45 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { // Set the st_pruned filtration for operator== st_pruned.set_filtration(2.5); st.prune_above_filtration(2.5); - /*BOOST_CHECK(st == st_pruned); + BOOST_CHECK(st == st_pruned); + + // Display the Simplex_tree + std::cout << "The complex pruned at 2.5 contains " << st.num_simplices() << " simplices" << std::endl; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << 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) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; + } 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); + + // Display the Simplex_tree + std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices" << std::endl; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << 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) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; + } + + 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/include/gudhi/distance_functions.h b/src/common/include/gudhi/distance_functions.h index e5c79ded..cd518581 100644 --- a/src/common/include/gudhi/distance_functions.h +++ b/src/common/include/gudhi/distance_functions.h @@ -23,6 +23,8 @@ #ifndef DISTANCE_FUNCTIONS_H_ #define DISTANCE_FUNCTIONS_H_ +#include // for std::sqrt + /* Compute the Euclidean distance between two Points given * by a range of coordinates. The points are assumed to have * the same dimension. */ @@ -35,7 +37,7 @@ double euclidean_distance(Point &p1, Point &p2) { double tmp = *it1 - *it2; dist += tmp*tmp; } - return sqrt(dist); + return std::sqrt(dist); } #endif // DISTANCE_FUNCTIONS_H_ diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index e05714c7..da2c2c36 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -58,7 +58,9 @@ inline void read_points(std::string file_name, std::vector< std::vector< double while (iss >> x) { point.push_back(x); } - points.push_back(point); + // Check for empty lines + if (!point.empty()) + points.push_back(point); } in_file.close(); } -- cgit v1.2.3 From 178f37684b9f3bebf95534568b5ef54c15e11c63 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 12 Jan 2016 16:21:20 +0000 Subject: Remove test from gudhUI cmake git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@958 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1f77ce3d6bd85fceba2e0eeeacd559315d9c9d89 --- src/GudhUI/CMakeLists.txt | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index 75adba08..24cb0be1 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -78,40 +78,6 @@ if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND ) target_link_libraries( GudhUI ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} ) target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) -############################################################################### - if (NOT CGAL_VERSION VERSION_LESS 4.7.0) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - - include( ${CGAL_USE_FILE} ) - # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. - # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 - # A workaround is to add "-std=c++11" again. - # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html - # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html - # but it implies to use cmake version 3.1 at least. - if(NOT MSVC) - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) - if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - endif() - endif() - # - End of workaround - - find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) - message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") - include( ${EIGEN3_USE_FILE} ) - - add_executable (acp alpha_complex_persistence.cpp) - target_link_libraries(acp ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${QT_LIBRARIES}) - - 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 () ############################################################################### else() -- cgit v1.2.3 From 0181c1f8c6122c50f991abea1ec8c4ec6bf392b4 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Wed, 13 Jan 2016 07:39:34 +0000 Subject: First version of a code changed so that it computes persistence of cubical complexes with or without periodic boundary conditions, but do not require duplication of code that link it to Gudhi persistence engine. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@961 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 506db0edd18818287fe110dcd04c15e369b28171 --- src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp | 4 ++-- .../Bitmap_cubical_complex_periodic_boundary_conditions.cpp | 11 +++++++---- .../example/Random_bitmap_cubical_complex.cpp | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index ed141ed9..39a55f24 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -54,11 +54,11 @@ lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for exam return 1; } - Bitmap_cubical_complex b( argv[1] ); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); pcoh.init_coefficients( p ); //initilizes the coefficient field for homology pcoh.compute_persistent_cohomology( min_persistence ); diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp index fa60d4f3..3d80c96d 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp @@ -22,10 +22,10 @@ #include -#include +#include +#include #include - using namespace Gudhi; using namespace Gudhi::Cubical_complex; using namespace Gudhi::persistent_cohomology; @@ -53,11 +53,14 @@ lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for exam return 1; } - Bitmap_cubical_complex_periodic_boundary_conditions b( argv[1] ); + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > b( argv[1] ); // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex_periodic_boundary_conditions, Field_Zp > pcoh(b,true); + persistent_cohomology::Persistent_cohomology< + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > + , Field_Zp + > pcoh(b,true); pcoh.init_coefficients( p ); //initilizes the coefficient field for homology pcoh.compute_persistent_cohomology( min_persistence ); diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index 36c22344..97347162 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -74,11 +74,11 @@ The program will create random cubical complex of that sizes and compute persist - Bitmap_cubical_complex b( sizes , data ); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( sizes , data ); // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex, Field_Zp > pcoh(b); + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); pcoh.init_coefficients( p ); //initilizes the coefficient field for homology pcoh.compute_persistent_cohomology( min_persistence ); -- cgit v1.2.3 From 12226486b5bf3f1d867f46aed5dc6d2c9727a03c Mon Sep 17 00:00:00 2001 From: pdlotko Date: Wed, 13 Jan 2016 08:41:26 +0000 Subject: Added tests for periodic boubnadry oconditions bitmap. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@962 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 49f059cdf9e0c8e20ff727564da13be14ebc2c04 --- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 270 +++++++++++++++++++++++- 1 file changed, 259 insertions(+), 11 deletions(-) diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 183b856a..4235761f 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -35,7 +35,7 @@ BOOST_AUTO_TEST_CASE(check_dimension) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); BOOST_CHECK(increasing.dimension() == 2); } @@ -88,18 +88,18 @@ BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > hole(dimensions, oneDimensionalCycle); int i = 0; - for (Bitmap_cubical_complex::Top_dimensional_cells_iterator + for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { BOOST_CHECK(*it == expectedFiltrationValues2[i]); ++i; } i = 0; - for (Bitmap_cubical_complex::Top_dimensional_cells_iterator + for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { BOOST_CHECK(*it == expectedFiltrationValues1[i]); ++i; @@ -309,7 +309,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { @@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector coboundaryElements; @@ -449,7 +449,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector dim; dim.push_back(0); @@ -523,7 +523,7 @@ BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { dimensions.push_back(3); dimensions.push_back(3); - Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector< unsigned > dim; dim.push_back(0); @@ -628,11 +628,259 @@ BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { fil.push_back(9); - Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); + Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Filtration_simplex_range range = increasing.filtration_simplex_range(); size_t position = 0; - for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { + for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { BOOST_CHECK(increasing.dimension(*it) == dim[position]); BOOST_CHECK(increasing.filtration(*it) == fil[position]); ++position; } } + + + +BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) { + std::vector< double > filtration; + filtration.push_back(0); + filtration.push_back(0); + filtration.push_back(0); + filtration.push_back(0); + + + std::vector dimensions; + dimensions.push_back(2); + dimensions.push_back(2); + + std::vector periodic_directions; + periodic_directions.push_back(true); + periodic_directions.push_back(true); + + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtration,periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector boundary0; + std::vector boundary1; + boundary1.push_back(0); + boundary1.push_back(2); + std::vector boundary2; + std::vector boundary3; + boundary3.push_back(2); + boundary3.push_back(0); + std::vector boundary4; + boundary4.push_back(0); + boundary4.push_back(8); + std::vector boundary5; + boundary5.push_back(1); + boundary5.push_back(9); + boundary5.push_back(4); + boundary5.push_back(6); + std::vector boundary6; + boundary6.push_back(2); + boundary6.push_back(10); + std::vector boundary7; + boundary7.push_back(3); + boundary7.push_back(11); + boundary7.push_back(6); + boundary7.push_back(4); + std::vector boundary8; + std::vector boundary9; + boundary9.push_back(8); + boundary9.push_back(10); + std::vector boundary10; + std::vector boundary11; + boundary11.push_back(10); + boundary11.push_back(8); + std::vector boundary12; + boundary12.push_back(8); + boundary12.push_back(0); + std::vector boundary13; + boundary13.push_back(9); + boundary13.push_back(1); + boundary13.push_back(12); + boundary13.push_back(14); + std::vector boundary14; + boundary14.push_back(10); + boundary14.push_back(2); + std::vector boundary15; + boundary15.push_back(11); + boundary15.push_back(3); + boundary15.push_back(14); + boundary15.push_back(12); + + std::vector< std::vector > boundaries; + boundaries.push_back( boundary0 ); + boundaries.push_back( boundary1 ); + boundaries.push_back( boundary2 ); + boundaries.push_back( boundary3 ); + boundaries.push_back( boundary4 ); + boundaries.push_back( boundary5 ); + boundaries.push_back( boundary6 ); + boundaries.push_back( boundary7 ); + boundaries.push_back( boundary8 ); + boundaries.push_back( boundary9 ); + boundaries.push_back( boundary10 ); + boundaries.push_back( boundary11 ); + boundaries.push_back( boundary12 ); + boundaries.push_back( boundary13 ); + boundaries.push_back( boundary14 ); + boundaries.push_back( boundary15 ); + + for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) { + std::vector< size_t > bd = cmplx.get_boundary_of_a_cell(i); + for (size_t j = 0; j != bd.size(); ++j) { + BOOST_CHECK(boundaries[i][j] == bd[j]); + } + } +} + + + + + + +BOOST_AUTO_TEST_CASE(coboudary_operator_2d_bitmap_with_periodic_bcond) { + std::vector< double > filtration; + filtration.push_back(0); + filtration.push_back(0); + filtration.push_back(0); + filtration.push_back(0); + + + std::vector dimensions; + dimensions.push_back(2); + dimensions.push_back(2); + + std::vector periodic_directions; + periodic_directions.push_back(true); + periodic_directions.push_back(true); + + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtration,periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector coboundary0; + coboundary0.push_back(4); + coboundary0.push_back(12); + coboundary0.push_back(1); + coboundary0.push_back(3); + std::vector coboundary1; + coboundary1.push_back(5); + coboundary1.push_back(13); + std::vector coboundary2; + coboundary2.push_back(6); + coboundary2.push_back(14); + coboundary2.push_back(1); + coboundary2.push_back(3); + std::vector coboundary3; + coboundary3.push_back(7); + coboundary3.push_back(15); + std::vector coboundary4; + coboundary4.push_back(5); + coboundary4.push_back(7); + std::vector coboundary5; + std::vector coboundary6; + coboundary6.push_back(5); + coboundary6.push_back(7); + std::vector coboundary7; + std::vector coboundary8; + coboundary8.push_back(4); + coboundary8.push_back(12); + coboundary8.push_back(9); + coboundary8.push_back(11); + std::vector coboundary9; + coboundary9.push_back(5); + coboundary9.push_back(13); + std::vector coboundary10; + coboundary10.push_back(6); + coboundary10.push_back(14); + coboundary10.push_back(9); + coboundary10.push_back(11); + std::vector coboundary11; + coboundary11.push_back(7); + coboundary11.push_back(15); + std::vector coboundary12; + coboundary12.push_back(13); + coboundary12.push_back(15); + std::vector coboundary13; + std::vector coboundary14; + coboundary14.push_back(13); + coboundary14.push_back(15); + std::vector coboundary15; + + std::vector< std::vector > coboundaries; + coboundaries.push_back( coboundary0 ); + coboundaries.push_back( coboundary1 ); + coboundaries.push_back( coboundary2 ); + coboundaries.push_back( coboundary3 ); + coboundaries.push_back( coboundary4 ); + coboundaries.push_back( coboundary5 ); + coboundaries.push_back( coboundary6 ); + coboundaries.push_back( coboundary7 ); + coboundaries.push_back( coboundary8 ); + coboundaries.push_back( coboundary9 ); + coboundaries.push_back( coboundary10 ); + coboundaries.push_back( coboundary11 ); + coboundaries.push_back( coboundary12 ); + coboundaries.push_back( coboundary13 ); + coboundaries.push_back( coboundary14 ); + coboundaries.push_back( coboundary15 ); + + for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) { + std::vector< size_t > cbd = cmplx.get_coboundary_of_a_cell(i); + for (size_t j = 0; j != cbd.size(); ++j) { + BOOST_CHECK(coboundaries[i][j] == cbd[j]); + } + } +} + + + + + + + +BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) { + std::vector< double > filtrationOrg; + filtrationOrg.push_back(0); + filtrationOrg.push_back(1); + filtrationOrg.push_back(2); + filtrationOrg.push_back(3); + + + std::vector dimensions; + dimensions.push_back(2); + dimensions.push_back(2); + + std::vector periodic_directions; + periodic_directions.push_back(true); + periodic_directions.push_back(true); + + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtrationOrg,periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector filtration; + filtration.push_back(0);//0 + filtration.push_back(0);//1 + filtration.push_back(0);//2 + filtration.push_back(1);//3 + filtration.push_back(0);//4 + filtration.push_back(0);//5 + filtration.push_back(0);//6 + filtration.push_back(1);//7 + filtration.push_back(0);//8 + filtration.push_back(0);//9 + filtration.push_back(0);//10 + filtration.push_back(1);//11 + filtration.push_back(2);//12 + filtration.push_back(2);//13 + filtration.push_back(2);//14 + filtration.push_back(3);//15 + + + for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) + { + BOOST_CHECK( filtration[i] == cmplx.get_cell_data(i) ); + } +} -- cgit v1.2.3 From 35143d2a24e7a601a4629a7cfe43ea6b8ea35f1a Mon Sep 17 00:00:00 2001 From: pdlotko Date: Wed, 13 Jan 2016 10:14:41 +0000 Subject: Adding documentation of the class. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@963 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6eec3b7216880475ed667660275c2314bf0feb0c --- .../include/gudhi/Bitmap_cubical_complex.h | 43 ++- .../include/gudhi/Bitmap_cubical_complex_base.h | 226 +++++++--------- ...cal_complex_periodic_boundary_conditions_base.h | 298 +++++++++++++++++++++ 3 files changed, 427 insertions(+), 140 deletions(-) create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index b324d272..63edcadd 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -23,7 +23,8 @@ #pragma once #include -#include "Bitmap_cubical_complex_base.h" +#include "Bitmap_cubical_complex_base.h" +#include "Bitmap_cubical_complex_periodic_boundary_conditions_base.h" @@ -38,15 +39,15 @@ const bool globalDbg = false; template class is_before_in_filtration; -template -class Bitmap_cubical_complex : public Bitmap_cubical_complex_base +template +class Bitmap_cubical_complex : public T { public: //*********************************************// //Typedefs and typenames //*********************************************// typedef size_t Simplex_key; - typedef T Filtration_value; + typedef typename T::filtration_type Filtration_value; typedef Simplex_key Simplex_handle; @@ -63,7 +64,7 @@ public: * Constructor form a Perseus-style file. **/ Bitmap_cubical_complex( const char* perseus_style_file ): - Bitmap_cubical_complex_base(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) + T(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) { if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) @@ -82,8 +83,28 @@ public: * in the following directions and vector of element of a type T * with filtration on top dimensional cells. **/ - Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells ): - Bitmap_cubical_complex_base(dimensions,top_dimensional_cells), + Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells ): + T(dimensions,top_dimensional_cells), + key_associated_to_simplex(this->total_number_of_cells+1) + { + for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) + { + this->key_associated_to_simplex[i] = i; + } + //we initialize this only once, in each constructor, when the bitmap is constructed. + //If the user decide to change some elements of the bitmap, then this procedure need + //to be called again. + this->initialize_simplex_associated_to_key(); + } + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * in the following directions and vector of element of a type T::filtration_type + * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. + * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. + **/ + Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ): + T(dimensions,top_dimensional_cells,directions_in_which_periodic_b_cond_are_to_be_imposed), key_associated_to_simplex(this->total_number_of_cells+1) { for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) @@ -138,9 +159,9 @@ public: /** * Return the filtration of a cell pointed by the Simplex_handle. **/ - T filtration(Simplex_handle sh) + typename T::filtration_type filtration(Simplex_handle sh) { - if ( globalDbg ){cerr << "T filtration(const Simplex_handle& sh)\n";} + if ( globalDbg ){cerr << "T::filtration_type filtration(const Simplex_handle& sh)\n";} //Returns the filtration value of a simplex. if ( sh != std::numeric_limits::max() ) return this->data[sh]; return std::numeric_limits::max(); @@ -493,8 +514,8 @@ public: bool operator()( const typename Bitmap_cubical_complex::Simplex_handle sh1, const typename Bitmap_cubical_complex::Simplex_handle sh2) const { // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. - T fil1 = CC_->data[sh1]; - T fil2 = CC_->data[sh2]; + typename T::filtration_type fil1 = CC_->data[sh1]; + typename T::filtration_type fil2 = CC_->data[sh2]; if ( fil1 != fil2 ) { return fil1 < fil2; diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 54d60325..600f250d 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -63,7 +63,12 @@ namespace Cubical_complex template class Bitmap_cubical_complex_base { -public: +public: + typedef T filtration_type; + /** + *Default constructor + **/ + Bitmap_cubical_complex_base(){} /** * There are a few constructors of a Bitmap_cubical_complex_base class. * First one, that takes vector, creates an empty bitmap of a dimension equal @@ -93,7 +98,7 @@ public: * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to * the positions of (co)boundary element of the input cell. */ - inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + virtual inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; /** * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, * get_dimension_of_a_cell and get_cell_data are the basic @@ -286,7 +291,12 @@ public: //****************************************************************************************************************// //****************************************************************************************************************// //****************************************************************************************************************// - + + +inline size_t number_cells()const +{ + return this->total_number_of_cells; +} //****************************************************************************************************************// //****************************************************************************************************************// @@ -305,14 +315,10 @@ protected: { this->sizes.push_back(sizes[i]); this->multipliers.push_back(multiplier); - //multiplier *= 2*(sizes[i]+1)+1; multiplier *= 2*sizes[i]+1; } - //std::reverse( this->sizes.begin() , this->sizes.end() ); - std::vector data(multiplier); - std::fill( data.begin() , data.end() , std::numeric_limits::max() ); + this->data = std::vector(multiplier, std::numeric_limits::max()); this->total_number_of_cells = multiplier; - this->data = data; } size_t compute_position_in_bitmap( const std::vector< unsigned >& counter ) @@ -336,11 +342,12 @@ protected: } std::reverse( counter.begin() , counter.end() ); return counter; - } - - std::vector< size_t > - generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions - ( const std::vector< bool >& directions_for_periodic_b_cond ); + } + void read_perseus_style_file( const char* perseus_style_file ); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); + Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); + Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); + Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ); }; @@ -364,11 +371,10 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base { this->set_up_containers( sizes ); } - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) -{ + +template +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) +{ this->set_up_containers( sizes_in_following_directions ); size_t number_of_top_dimensional_elements = 1; @@ -397,13 +403,19 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base (*it) = top_dimensional_cells[index]; ++index; } - this->impose_lower_star_filtration(); -} - + this->impose_lower_star_filtration(); +} template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file ) +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base +( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) { + this->setup_bitmap_based_on_top_dimensional_cells_list( sizes_in_following_directions , top_dimensional_cells ); +} + +template +void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) +{ bool dbg = false; ifstream inFiltration, inIds; inFiltration.open( perseus_style_file ); @@ -418,7 +430,7 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus { unsigned size_in_this_dimension; inFiltration >> size_in_this_dimension; - size_in_this_dimension = abs(size_in_this_dimension); + size_in_this_dimension = size_in_this_dimension; sizes.push_back( size_in_this_dimension ); if (dbg){cerr << "size_in_this_dimension : " << size_in_this_dimension << endl;} } @@ -427,7 +439,6 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); it = this->top_dimensional_cells_begin(); - //TODO -- over here we also need to read id's of cell and put them to bitmapElement structure! while ( !inFiltration.eof() ) { double filtrationLevel; @@ -444,7 +455,37 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus ++it; } inFiltration.close(); - this->impose_lower_star_filtration(); + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->read_perseus_style_file( perseus_style_file ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file ) +{ + this->read_perseus_style_file( perseus_style_file ); } @@ -468,60 +509,39 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( si cell1 = cell1%this->multipliers[i-1]; } return boundary_elements; -} - - +} + + + template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { - //first of all, we need to take the list of coordinates in which the cell has nonzero length. - //We do it by using modified version to compute dimension of a cell: - std::vector< unsigned > dimensions_in_which_cell_has_zero_length; - - //Speed traded of for memory. Check if it is better in practice. - dimensions_in_which_cell_has_zero_length.reserve( this->dimension()*2 ); - - unsigned dimension = 0; + std::vector counter = this->compute_counter_for_given_cell( cell ); + std::vector< size_t > coboundary_elements; size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 0 ) { - dimensions_in_which_cell_has_zero_length.push_back(i-1); - dimension++; + if ( (cell > this->multipliers[i-1]) && (counter[i-1] != 0) ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + } + if ( + (cell + this->multipliers[i-1] < this->data.size()) && (counter[i-1] != 2*this->sizes[i-1]) ) + { + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } } cell1 = cell1%this->multipliers[i-1]; } - - std::vector counter = this->compute_counter_for_given_cell( cell ); - std::vector< size_t > coboundary_elements; + return coboundary_elements; +} - //Speed traded of for memory. Check if it is better in practice. - coboundary_elements.reserve ( dimensions_in_which_cell_has_zero_length.size()*2 ); - if ( dimensions_in_which_cell_has_zero_length.size() == 0 )return coboundary_elements; - for ( size_t i = 0 ; i != dimensions_in_which_cell_has_zero_length.size() ; ++i ) - { - if ( (cell > this->multipliers[dimensions_in_which_cell_has_zero_length[i]]) - && (counter[dimensions_in_which_cell_has_zero_length[i]] != 0) ) - { - coboundary_elements.push_back( cell - this->multipliers[dimensions_in_which_cell_has_zero_length[i]] ); - } - if ( - (cell + this->multipliers[dimensions_in_which_cell_has_zero_length[i]] < this->data.size()) && - (counter[dimensions_in_which_cell_has_zero_length[i]] - != - 2*this->sizes[dimensions_in_which_cell_has_zero_length[i]]) - ) - { - coboundary_elements.push_back( cell + this->multipliers[dimensions_in_which_cell_has_zero_length[i]] ); - } - } - return coboundary_elements; -} @@ -555,7 +575,7 @@ unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell( size_t cell )c } template -T& Bitmap_cubical_complex_base::get_cell_data( size_t cell ) +inline T& Bitmap_cubical_complex_base::get_cell_data( size_t cell ) { return this->data[cell]; } @@ -602,10 +622,21 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) - { + { + if ( dbg ) + { + cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; + getchar(); + + } if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) { - this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + if ( dbg ) + { + cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; + getchar(); + } } if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) { @@ -640,69 +671,6 @@ bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , ch -template -std::vector< size_t > Bitmap_cubical_complex_base:: -generate_vector_of_shifts_for_bitmaps_with_periodic_boundary_conditions -( const std::vector< bool >& directions_for_periodic_b_cond ) -{ - bool dbg = false; - if ( this->sizes.size() != directions_for_periodic_b_cond.size() ) - throw "directions_for_periodic_b_cond vector size is different from the size of the bitmap. Program terminate \n"; - - std::vector sizes; - sizes.reserve( this->sizes.size() ); - for ( size_t i = 0 ; i != this->sizes.size() ; ++i ) - { - sizes.push_back(2*this->sizes[i]); - } - - counter c( sizes ); - - std::vector< size_t > result; - result.reserve( this->data.size() ); - - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - size_t position; - if ( !c.isFinal() ) - { - position = i; - } - else - { - std::vector< bool > finals = c.directions_of_finals(); - bool jump_in_position = false; - for ( size_t dir = 0 ; dir != finals.size() ; ++dir ) - { - if ( finals[dir] == false )continue; - if ( directions_for_periodic_b_cond[dir] ) - { - jump_in_position = true; - } - } - if ( jump_in_position == true ) - { - //in this case this guy is final, so we need to find 'the opposite one' - position = compute_position_in_bitmap( c.find_opposite( directions_for_periodic_b_cond ) ); - } - else - { - position = i; - } - } - result.push_back( position ); - if ( dbg ) - { - cerr << " position : " << position << endl; - cerr << c << endl; - getchar(); - } - - c.increment(); - } - - return result; -} } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h new file mode 100644 index 00000000..28911ea8 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -0,0 +1,298 @@ +#pragma once +#include +#include "Bitmap_cubical_complex_base.h" + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures +//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the +//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base + +template +class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base +{ +public: + //constructors that take an extra parameter: + Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); + + //overwritten methods co compute boundary and coboundary + virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + //inline unsigned get_dimension_of_a_cell( size_t cell )const; + +protected: + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; + void set_up_containers( const std::vector& sizes ) + { + + unsigned multiplier = 1; + for ( size_t i = 0 ; i != sizes.size() ; ++i ) + { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + + if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) + { + multiplier *= 2*sizes[i]; + } + else + { + multiplier *= 2*sizes[i]+1; + } + } + //std::reverse( this->sizes.begin() , this->sizes.end() ); + this->data = std::vector(multiplier,std::numeric_limits::max()); + this->total_number_of_cells = multiplier; + } + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ); + void construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); +}; + +template +void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( dimensions ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = topDimensionalCells[i]; + ++i; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) +{ + //for Perseus style files: + bool dbg = false; + + ifstream inFiltration; + inFiltration.open( perseus_style_file ); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); + + std::vector sizes; + sizes.reserve( dimensionOfData ); + for ( size_t i = 0 ; i != dimensionOfData ; ++i ) + { + int size_in_this_dimension; + inFiltration >> size_in_this_dimension; + if ( size_in_this_dimension < 0 ) + { + this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; + } + sizes.push_back( abs(size_in_this_dimension) ); + } + this->set_up_containers( sizes ); + + typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_begin(); + + while ( !inFiltration.eof() ) + { + double filtrationLevel; + inFiltration >> filtrationLevel; + if ( inFiltration.eof() )break; + + if ( dbg ) + { + cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << endl; + } + *it = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); + + /* + char* filename = (char*)perseus_style_file; + //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; + ifstream file( filename , ios::binary | ios::ate ); + unsigned realSizeOfFile = file.tellg(); + file.close(); + realSizeOfFile = realSizeOfFile/sizeof(T); + + unsigned w, h, d; + + w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); + + T* slice = new T[w*h*d]; + if (slice == NULL) + { + cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; + exit(EXIT_FAILURE); + } + + FILE* fp; + if ((fp=fopen( filename, "rb" )) == NULL ) + { + cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; + exit(1); + } + fread( slice,4,w*h*d,fp ); + fclose(fp); + std::vector data(slice,slice+w*h*d); + delete[] slice; + std::vector< unsigned > sizes; + sizes.push_back(w); + sizes.push_back(w); + sizes.push_back(w); + + std::vector< bool > directions; + directions.push_back( true ); + directions.push_back( true ); + directions.push_back( true ); + Bitmap_cubical_complex_periodic_boundary_conditions_base b( sizes, data, directions ); + *this = b; + */ +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ) +{ + std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + + + + + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + +//***********************Methods************************// + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const +{ + bool dbg = false; + if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} + + std::vector< size_t > boundary_elements; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/this->multipliers[i-1]; + //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. + + if ( position%2 == 1 ) + { + //if there are no periodic boundary conditions in this direction, we do not have to do anything. + if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //cerr << "A\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. + if ( position != 2*this->sizes[ i-1 ]-1 ) + { + //cerr << "B\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //cerr << "C\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} + } + } + } + cell1 = cell1%this->multipliers[i-1]; + } + return boundary_elements; +} + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const +{ + std::vector counter = this->compute_counter_for_given_cell( cell ); + std::vector< size_t > coboundary_elements; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/this->multipliers[i-1]; + //if the cell has zero length in this direction, then it will have cbd in this direction. + if ( position%2 == 0 ) + { + if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //no periodic boundary conditions in this direction + if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + } + if ( (counter[i-1] != 2*this->sizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) + { + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + } + else + { + //we want to have periodic boundary conditions in this direction + if ( counter[i-1] != 0 ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + else + { + //in this case counter[i-1] == 0. + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); + } + } + } + + cell1 = cell1%this->multipliers[i-1]; + } + return coboundary_elements; +} + + + +}//Cubical_complex +}//namespace Gudhi -- cgit v1.2.3 From f443bbd06cac275284f75936d6803105eb99fec6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 15 Jan 2016 13:00:53 +0000 Subject: make_filtration_non_decreasing fix. Make it non decreasing for border and not only for parent. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@972 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e71f40baa56de53e68b02603b64fb504b1f5d978 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 64 +++++++++++++++++++--- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 67 ++++++++++-------------- 2 files changed, 86 insertions(+), 45 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 3ba838a7..16485c89 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -47,6 +47,7 @@ #include #include // Inf #include +#include // for std::max namespace Gudhi { /** \defgroup simplex_tree Filtered Complexes @@ -128,6 +129,10 @@ 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; } @@ -221,7 +226,7 @@ class Simplex_tree { * * 'value_type' is Simplex_handle. */ typedef typename Filtration_simplex_range::const_iterator Filtration_simplex_iterator; - + /* @} */ // end name range and iterator types /** \name Range and iterator methods * @{ */ @@ -327,11 +332,10 @@ class Simplex_tree { Simplex_tree(const Simplex_tree& simplex_source) : null_vertex_(simplex_source.null_vertex_), threshold_(simplex_source.threshold_), + root_(nullptr, null_vertex_ , simplex_source.root_.members_), filtration_vect_(), dimension_(simplex_source.dimension_) { auto root_source = simplex_source.root_; - auto memb_source = root_source.members(); - root_ = Siblings(nullptr, null_vertex_, memb_source); rec_copy(&root_, &root_source); } @@ -343,7 +347,7 @@ class Simplex_tree { Siblings * newsib = new Siblings(sib, sh_source->first); newsib->members_.reserve(sh_source->second.children()->members().size()); for (auto & child : sh_source->second.children()->members()) - newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(sib, child.second.filtration())); + newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(newsib, child.second.filtration())); rec_copy(newsib, sh_source->second.children()); sh->second.assign_children(newsib); } @@ -1127,9 +1131,15 @@ 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) { if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children(), max_border_value->second.filtration()); } } return modified; @@ -1143,6 +1153,12 @@ class Simplex_tree { */ bool rec_make_filtration_non_decreasing(Siblings * sib, Filtration_value upper_filtration) { 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) { // Store the filtration modification information @@ -1150,7 +1166,7 @@ class Simplex_tree { sh->second.assign_filtration(upper_filtration); } if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children(), max_border_value->second.filtration()); } } // Make the modified information to be traced by upper call @@ -1223,6 +1239,42 @@ std::cout << "prune_above_filtration - filtration=" << filtration << std::endl; 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/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 1a050a25..25ae5ed3 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -802,13 +802,18 @@ BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) { typedef Simplex_tree<> typeST; 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({2, 1, 0}, 2.0); + st.insert_simplex_and_subfaces({3, 0}, 2.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 + + typeST st_bis = st; + // Check default insertion ensures the filtration values are non decreasing + 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 */ @@ -817,45 +822,29 @@ BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) { /* 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); + + // 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); + + BOOST_CHECK(st == st_bis); - // 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 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); + BOOST_CHECK(st.make_filtration_non_decreasing()); + BOOST_CHECK(st == st_bis); - // Check the filtration values are non decreasing + // 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); BOOST_CHECK(!st.make_filtration_non_decreasing()); - // Check the simplex tree has been modified from the original - BOOST_CHECK(st != st_copy); } -- 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(-) 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 57eb57ed2092beaceb978e31aebb500450b9599b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Feb 2016 09:07:16 +0000 Subject: rename alpha_shapes_persistence test with alpha_complex_3d_persistence git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@991 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 455ee94450098bbcc000fb2ab2c4d39a326dea2c --- src/Persistent_cohomology/example/CMakeLists.txt | 39 ++- .../example/alpha_complex_3d_persistence.cpp | 294 +++++++++++++++++++++ .../example/alpha_shapes_persistence.cpp | 294 --------------------- 3 files changed, 313 insertions(+), 314 deletions(-) create mode 100644 src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp delete mode 100644 src/Persistent_cohomology/example/alpha_shapes_persistence.cpp diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index 5fec8ad4..779a9e89 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -40,30 +40,29 @@ 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) - 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) - #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) + include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround + + add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp) + target_link_libraries(alpha_complex_3d_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) + add_test(alpha_complex_3d_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_complex_3d_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) if (NOT CGAL_VERSION VERSION_LESS 4.7.0) message(STATUS "CGAL version: ${CGAL_VERSION}.") - include( ${CGAL_USE_FILE} ) - # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. - # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 - # A workaround is to add "-std=c++11" again. - # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html - # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html - # but it implies to use cmake version 3.1 at least. - if(NOT MSVC) - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) - if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - endif() - endif() - # - End of workaround - find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") diff --git a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp new file mode 100644 index 00000000..ac208957 --- /dev/null +++ b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp @@ -0,0 +1,294 @@ +/* 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 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#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; +typedef CGAL::Alpha_shape_cell_base_3 Fb; +typedef CGAL::Triangulation_data_structure_3 Tds; +typedef CGAL::Delaunay_triangulation_3 Triangulation_3; +typedef CGAL::Alpha_shape_3 Alpha_shape_3; + +// From file type definition +typedef Kernel::Point_3 Point_3; + +// filtration with alpha values needed type definition +typedef Alpha_shape_3::FT Alpha_value_type; +typedef CGAL::Object Object; +typedef CGAL::Dispatch_output_iterator< +CGAL::cpp11::tuple, +CGAL::cpp11::tuple >, + std::back_insert_iterator< std::vector > > > Dispatch; +typedef Alpha_shape_3::Cell_handle Cell_handle; +typedef Alpha_shape_3::Facet Facet; +typedef Alpha_shape_3::Edge Edge_3; +typedef std::list Vertex_list; + +// gudhi type definition +typedef 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; + +Vertex_list from(const Cell_handle& ch) { + Vertex_list the_list; + for (auto i = 0; i < 4; i++) { +#ifdef DEBUG_TRACES + std::cout << "from cell[" << i << "]=" << ch->vertex(i)->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(ch->vertex(i)); + } + return the_list; +} + +Vertex_list from(const Facet& fct) { + Vertex_list the_list; + for (auto i = 0; i < 4; i++) { + if (fct.second != i) { +#ifdef DEBUG_TRACES + std::cout << "from facet=[" << i << "]" << fct.first->vertex(i)->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(fct.first->vertex(i)); + } + } + return the_list; +} + +Vertex_list from(const Edge_3& edg) { + Vertex_list the_list; + for (auto i = 0; i < 4; i++) { + if ((edg.second == i) || (edg.third == i)) { +#ifdef DEBUG_TRACES + std::cout << "from edge[" << i << "]=" << edg.first->vertex(i)->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(edg.first->vertex(i)); + } + } + return the_list; +} + +Vertex_list from(const Alpha_shape_3::Vertex_handle& vh) { + Vertex_list the_list; +#ifdef DEBUG_TRACES + std::cout << "from vertex=" << vh->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(vh); + return the_list; +} + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << + " path_to_file_graph coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n"; + exit(-1); +} + +int main(int argc, char * const argv[]) { + // program args management + if (argc != 4) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; + 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]); + } + + Filtration_value min_persistence = 0.0; + returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); + if ((returnedScanValue == EOF) || (min_persistence < -1.0)) { + std::cerr << "Error: " << argv[3] << " is not correct\n"; + usage(argv[0]); + } + + // Read points from file + std::string filegraph = argv[1]; + std::list lp; + std::ifstream is(filegraph.c_str()); + int n; + is >> n; +#ifdef DEBUG_TRACES + std::cout << "Reading " << n << " points " << std::endl; +#endif // DEBUG_TRACES + Point_3 p; + for (; n > 0; n--) { + is >> p; + lp.push_back(p); + } + + // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. + Alpha_shape_3 as(lp.begin(), lp.end(), 0, Alpha_shape_3::GENERAL); +#ifdef DEBUG_TRACES + std::cout << "Alpha shape computed in GENERAL mode" << std::endl; +#endif // DEBUG_TRACES + + // filtration with alpha values from alpha shape + std::vector the_objects; + std::vector the_alpha_values; + + Dispatch disp = CGAL::dispatch_output(std::back_inserter(the_objects), + std::back_inserter(the_alpha_values)); + + as.filtration_with_alpha_values(disp); +#ifdef DEBUG_TRACES + std::cout << "filtration_with_alpha_values returns : " << the_objects.size() << " objects" << std::endl; +#endif // DEBUG_TRACES + + Alpha_shape_3::size_type count_vertices = 0; + Alpha_shape_3::size_type count_edges = 0; + Alpha_shape_3::size_type count_facets = 0; + Alpha_shape_3::size_type count_cells = 0; + + // Loop on objects vector + Vertex_list vertex_list; + ST simplex_tree; + Alpha_shape_simplex_tree_map map_cgal_simplex_tree; + std::vector::iterator the_alpha_value_iterator = the_alpha_values.begin(); + int dim_max = 0; + Filtration_value filtration_max = 0.0; + for (auto object_iterator : the_objects) { + // Retrieve Alpha shape vertex list from object + if (const Cell_handle * cell = CGAL::object_cast(&object_iterator)) { + vertex_list = from(*cell); + count_cells++; + if (dim_max < 3) { + // Cell is of dim 3 + dim_max = 3; + } + } else if (const Facet * facet = CGAL::object_cast(&object_iterator)) { + vertex_list = from(*facet); + count_facets++; + if (dim_max < 2) { + // Facet is of dim 2 + dim_max = 2; + } + } else if (const Edge_3 * edge = CGAL::object_cast(&object_iterator)) { + vertex_list = from(*edge); + count_edges++; + if (dim_max < 1) { + // Edge_3 is of dim 1 + dim_max = 1; + } + } else if (const Alpha_shape_3::Vertex_handle * vertex = + CGAL::object_cast(&object_iterator)) { + count_vertices++; + vertex_list = from(*vertex); + } + // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex + Simplex_tree_vector_vertex the_simplex_tree; + for (auto the_alpha_shape_vertex : vertex_list) { + Alpha_shape_simplex_tree_map::iterator the_map_iterator = map_cgal_simplex_tree.find(the_alpha_shape_vertex); + if (the_map_iterator == map_cgal_simplex_tree.end()) { + // alpha shape not found + Simplex_tree_vertex vertex = map_cgal_simplex_tree.size(); +#ifdef DEBUG_TRACES + std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] not found - insert " << vertex << std::endl; +#endif // DEBUG_TRACES + the_simplex_tree.push_back(vertex); + map_cgal_simplex_tree.insert(Alpha_shape_simplex_tree_pair(the_alpha_shape_vertex, vertex)); + } else { + // alpha shape found + Simplex_tree_vertex vertex = the_map_iterator->second; +#ifdef DEBUG_TRACES + std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] found in " << vertex << std::endl; +#endif // DEBUG_TRACES + the_simplex_tree.push_back(vertex); + } + } + // Construction of the simplex_tree + Filtration_value filtr = /*std::sqrt*/(*the_alpha_value_iterator); +#ifdef DEBUG_TRACES + std::cout << "filtration = " << filtr << std::endl; +#endif // DEBUG_TRACES + if (filtr > filtration_max) { + filtration_max = filtr; + } + simplex_tree.insert_simplex(the_simplex_tree, filtr); + if (the_alpha_value_iterator != the_alpha_values.end()) + ++the_alpha_value_iterator; + else + std::cout << "This shall not happen" << std::endl; + } + simplex_tree.set_filtration(filtration_max); + simplex_tree.set_dimension(dim_max); + +#ifdef DEBUG_TRACES + std::cout << "vertices \t\t" << count_vertices << std::endl; + std::cout << "edges \t\t" << count_edges << std::endl; + std::cout << "facets \t\t" << count_facets << std::endl; + std::cout << "cells \t\t" << count_cells << std::endl; + + + std::cout << "Information of the Simplex Tree: " << std::endl; + std::cout << " Number of vertices = " << simplex_tree.num_vertices() << " "; + std::cout << " Number of simplices = " << simplex_tree.num_simplices() << std::endl << std::endl; + std::cout << " Dimension = " << simplex_tree.dimension() << " "; + std::cout << " filtration = " << simplex_tree.filtration() << std::endl << std::endl; +#endif // DEBUG_TRACES + +#ifdef DEBUG_TRACES + std::cout << "Iterator on vertices: " << std::endl; + for (auto vertex : simplex_tree.complex_vertex_range()) { + std::cout << vertex << " "; + } +#endif // DEBUG_TRACES + + // Sort the simplices in the order of the filtration + simplex_tree.initialize_filtration(); + + 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); + // initializes the coefficient field for homology + pcoh.init_coefficients(coeff_field_characteristic); + + pcoh.compute_persistent_cohomology(min_persistence); + + pcoh.output_diagram(); + + return 0; +} diff --git a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp b/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp deleted file mode 100644 index ac208957..00000000 --- a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp +++ /dev/null @@ -1,294 +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 . - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#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; -typedef CGAL::Alpha_shape_cell_base_3 Fb; -typedef CGAL::Triangulation_data_structure_3 Tds; -typedef CGAL::Delaunay_triangulation_3 Triangulation_3; -typedef CGAL::Alpha_shape_3 Alpha_shape_3; - -// From file type definition -typedef Kernel::Point_3 Point_3; - -// filtration with alpha values needed type definition -typedef Alpha_shape_3::FT Alpha_value_type; -typedef CGAL::Object Object; -typedef CGAL::Dispatch_output_iterator< -CGAL::cpp11::tuple, -CGAL::cpp11::tuple >, - std::back_insert_iterator< std::vector > > > Dispatch; -typedef Alpha_shape_3::Cell_handle Cell_handle; -typedef Alpha_shape_3::Facet Facet; -typedef Alpha_shape_3::Edge Edge_3; -typedef std::list Vertex_list; - -// gudhi type definition -typedef 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; - -Vertex_list from(const Cell_handle& ch) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { -#ifdef DEBUG_TRACES - std::cout << "from cell[" << i << "]=" << ch->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(ch->vertex(i)); - } - return the_list; -} - -Vertex_list from(const Facet& fct) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { - if (fct.second != i) { -#ifdef DEBUG_TRACES - std::cout << "from facet=[" << i << "]" << fct.first->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(fct.first->vertex(i)); - } - } - return the_list; -} - -Vertex_list from(const Edge_3& edg) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { - if ((edg.second == i) || (edg.third == i)) { -#ifdef DEBUG_TRACES - std::cout << "from edge[" << i << "]=" << edg.first->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(edg.first->vertex(i)); - } - } - return the_list; -} - -Vertex_list from(const Alpha_shape_3::Vertex_handle& vh) { - Vertex_list the_list; -#ifdef DEBUG_TRACES - std::cout << "from vertex=" << vh->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(vh); - return the_list; -} - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << - " path_to_file_graph coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n"; - exit(-1); -} - -int main(int argc, char * const argv[]) { - // program args management - if (argc != 4) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; - 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]); - } - - Filtration_value min_persistence = 0.0; - returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); - if ((returnedScanValue == EOF) || (min_persistence < -1.0)) { - std::cerr << "Error: " << argv[3] << " is not correct\n"; - usage(argv[0]); - } - - // Read points from file - std::string filegraph = argv[1]; - std::list lp; - std::ifstream is(filegraph.c_str()); - int n; - is >> n; -#ifdef DEBUG_TRACES - std::cout << "Reading " << n << " points " << std::endl; -#endif // DEBUG_TRACES - Point_3 p; - for (; n > 0; n--) { - is >> p; - lp.push_back(p); - } - - // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. - Alpha_shape_3 as(lp.begin(), lp.end(), 0, Alpha_shape_3::GENERAL); -#ifdef DEBUG_TRACES - std::cout << "Alpha shape computed in GENERAL mode" << std::endl; -#endif // DEBUG_TRACES - - // filtration with alpha values from alpha shape - std::vector the_objects; - std::vector the_alpha_values; - - Dispatch disp = CGAL::dispatch_output(std::back_inserter(the_objects), - std::back_inserter(the_alpha_values)); - - as.filtration_with_alpha_values(disp); -#ifdef DEBUG_TRACES - std::cout << "filtration_with_alpha_values returns : " << the_objects.size() << " objects" << std::endl; -#endif // DEBUG_TRACES - - Alpha_shape_3::size_type count_vertices = 0; - Alpha_shape_3::size_type count_edges = 0; - Alpha_shape_3::size_type count_facets = 0; - Alpha_shape_3::size_type count_cells = 0; - - // Loop on objects vector - Vertex_list vertex_list; - ST simplex_tree; - Alpha_shape_simplex_tree_map map_cgal_simplex_tree; - std::vector::iterator the_alpha_value_iterator = the_alpha_values.begin(); - int dim_max = 0; - Filtration_value filtration_max = 0.0; - for (auto object_iterator : the_objects) { - // Retrieve Alpha shape vertex list from object - if (const Cell_handle * cell = CGAL::object_cast(&object_iterator)) { - vertex_list = from(*cell); - count_cells++; - if (dim_max < 3) { - // Cell is of dim 3 - dim_max = 3; - } - } else if (const Facet * facet = CGAL::object_cast(&object_iterator)) { - vertex_list = from(*facet); - count_facets++; - if (dim_max < 2) { - // Facet is of dim 2 - dim_max = 2; - } - } else if (const Edge_3 * edge = CGAL::object_cast(&object_iterator)) { - vertex_list = from(*edge); - count_edges++; - if (dim_max < 1) { - // Edge_3 is of dim 1 - dim_max = 1; - } - } else if (const Alpha_shape_3::Vertex_handle * vertex = - CGAL::object_cast(&object_iterator)) { - count_vertices++; - vertex_list = from(*vertex); - } - // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex - Simplex_tree_vector_vertex the_simplex_tree; - for (auto the_alpha_shape_vertex : vertex_list) { - Alpha_shape_simplex_tree_map::iterator the_map_iterator = map_cgal_simplex_tree.find(the_alpha_shape_vertex); - if (the_map_iterator == map_cgal_simplex_tree.end()) { - // alpha shape not found - Simplex_tree_vertex vertex = map_cgal_simplex_tree.size(); -#ifdef DEBUG_TRACES - std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] not found - insert " << vertex << std::endl; -#endif // DEBUG_TRACES - the_simplex_tree.push_back(vertex); - map_cgal_simplex_tree.insert(Alpha_shape_simplex_tree_pair(the_alpha_shape_vertex, vertex)); - } else { - // alpha shape found - Simplex_tree_vertex vertex = the_map_iterator->second; -#ifdef DEBUG_TRACES - std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] found in " << vertex << std::endl; -#endif // DEBUG_TRACES - the_simplex_tree.push_back(vertex); - } - } - // Construction of the simplex_tree - Filtration_value filtr = /*std::sqrt*/(*the_alpha_value_iterator); -#ifdef DEBUG_TRACES - std::cout << "filtration = " << filtr << std::endl; -#endif // DEBUG_TRACES - if (filtr > filtration_max) { - filtration_max = filtr; - } - simplex_tree.insert_simplex(the_simplex_tree, filtr); - if (the_alpha_value_iterator != the_alpha_values.end()) - ++the_alpha_value_iterator; - else - std::cout << "This shall not happen" << std::endl; - } - simplex_tree.set_filtration(filtration_max); - simplex_tree.set_dimension(dim_max); - -#ifdef DEBUG_TRACES - std::cout << "vertices \t\t" << count_vertices << std::endl; - std::cout << "edges \t\t" << count_edges << std::endl; - std::cout << "facets \t\t" << count_facets << std::endl; - std::cout << "cells \t\t" << count_cells << std::endl; - - - std::cout << "Information of the Simplex Tree: " << std::endl; - std::cout << " Number of vertices = " << simplex_tree.num_vertices() << " "; - std::cout << " Number of simplices = " << simplex_tree.num_simplices() << std::endl << std::endl; - std::cout << " Dimension = " << simplex_tree.dimension() << " "; - std::cout << " filtration = " << simplex_tree.filtration() << std::endl << std::endl; -#endif // DEBUG_TRACES - -#ifdef DEBUG_TRACES - std::cout << "Iterator on vertices: " << std::endl; - for (auto vertex : simplex_tree.complex_vertex_range()) { - std::cout << vertex << " "; - } -#endif // DEBUG_TRACES - - // Sort the simplices in the order of the filtration - simplex_tree.initialize_filtration(); - - 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); - // initializes the coefficient field for homology - pcoh.init_coefficients(coeff_field_characteristic); - - pcoh.compute_persistent_cohomology(min_persistence); - - pcoh.output_diagram(); - - return 0; -} -- 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(-) 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 74dcaacda1c887b008ea8c95b28962de1c02a2d0 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Feb 2016 15:24:51 +0000 Subject: alpha off reader test strategy modification git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@995 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: aa4ba97eecefb03e01a53ae1e2b50248a0857043 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 2 +- .../example/Alpha_complex_from_off.cpp | 33 +++++++++++++++------- .../example/Alpha_complex_from_points.cpp | 2 +- src/Alpha_complex/example/CMakeLists.txt | 19 +++++++++++-- .../example/alphaoffreader_for_doc_32.txt | 26 ++++++++--------- src/Alpha_complex/test/CMakeLists.txt | 14 +++++++++ src/Simplex_tree/include/gudhi/Simplex_tree.h | 15 ++++++---- 7 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 12d62ac0..8eea6ba7 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -67,7 +67,7 @@ namespace alphacomplex { * * When launching: * - * \code $> ./alphapoints 60.0 + * \code $> ./alphapoints * \endcode * * the program output is: diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 780f904b..80445a22 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -5,14 +5,14 @@ #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; + 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) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + if ((argc != 3) && (argc != 4)) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; usage(argv[0]); } @@ -25,21 +25,34 @@ 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); + std::streambuf* streambufffer; + std::ofstream ouput_file_stream; + + if (argc == 4) { + ouput_file_stream.open(std::string(argv[3])); + streambufffer = ouput_file_stream.rdbuf(); + } else { + streambufffer = std::cout.rdbuf(); + } + + std::ostream output_stream(streambufffer); + // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- - std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << + 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; - std::cout << "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 : alpha_complex_from_file.filtration_simplex_range()) { - std::cout << " ( "; + output_stream << " ( "; for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { - std::cout << vertex << " "; + output_stream << vertex << " "; } - std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; - std::cout << 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 dab161c9..815e40d7 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -10,7 +10,7 @@ typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; int main(int argc, char **argv) { - double alpha_square_max_value = 32.0; + double alpha_square_max_value = 60.0; // ---------------------------------------------------------------------------- // Init of a list of points diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 33ff6805..d93dd436 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -27,12 +27,25 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - - 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}) + add_test(alphapoints ${CMAKE_CURRENT_BINARY_DIR}/alphapoints) + + # 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) + 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() else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt index 553431a9..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] - ( 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] + ( 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/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index fa24e1b1..52ec0a78 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -8,6 +8,20 @@ if(CGAL_FOUND) message(STATUS "CGAL version: ${CGAL_VERSION}.") include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index dbef8517..3911f497 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -307,7 +307,8 @@ class Simplex_tree { * of the simplex. * * @param[in] sh Simplex for which the boundary is computed. */ - Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) { + template + Boundary_simplex_range boundary_simplex_range(DictionaryIterator sh) { return Boundary_simplex_range(Boundary_simplex_iterator(this, sh), Boundary_simplex_iterator(this)); } @@ -528,7 +529,11 @@ class Simplex_tree { /** \brief Returns true if the node in the simplex tree pointed by * sh has children.*/ - bool has_children(Simplex_handle sh) const { + /*bool has_children(Simplex_handle sh) const { + return (sh->second.children()->parent() == sh->first); + }*/ + template + bool has_children(DictionaryIterator sh) const { return (sh->second.children()->parent() == sh->first); } @@ -1128,7 +1133,7 @@ class Simplex_tree { bool make_filtration_non_decreasing() { bool modified = false; // 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) { + for (auto sh = root_.members().rbegin(); sh != root_.members().rend(); ++sh) { if (has_children(sh)) { modified |= rec_make_filtration_non_decreasing(sh->second.children()); } @@ -1144,10 +1149,11 @@ class Simplex_tree { bool rec_make_filtration_non_decreasing(Siblings * sib) { bool modified = false; + // 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 = sib->members().begin(); sh != sib->members().end(); ++sh) { // 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), + 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); } ); @@ -1175,7 +1181,6 @@ class Simplex_tree { * call `initialize_filtration()` to recompute it. */ void prune_above_filtration(Filtration_value filtration) { -std::cout << "prune_above_filtration - filtration=" << filtration << std::endl; // No action if filtration is not stored if (Options::store_filtration) { if (filtration < threshold_) { -- cgit v1.2.3 From 8cb0b53a28b9d4cf6b97abcffbb527b51e322a22 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 3 Feb 2016 10:15:31 +0000 Subject: make_filtration_non_decreasing and rec_make_filtration_non_decreasing must go through the tree in reverse mode (starting from the right part) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@997 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0c8f8aeabd7dcba26971381c425ef7b0b417138c --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 33 +++++++++++----------- .../gudhi/Simplex_tree/Simplex_tree_iterators.h | 3 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 3911f497..0d12e9b7 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef GUDHI_USE_TBB #include @@ -307,8 +308,8 @@ class Simplex_tree { * of the simplex. * * @param[in] sh Simplex for which the boundary is computed. */ - template - Boundary_simplex_range boundary_simplex_range(DictionaryIterator sh) { + template + Boundary_simplex_range boundary_simplex_range(SimplexHandle sh) { return Boundary_simplex_range(Boundary_simplex_iterator(this, sh), Boundary_simplex_iterator(this)); } @@ -529,11 +530,8 @@ class Simplex_tree { /** \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); - }*/ - template - bool has_children(DictionaryIterator sh) const { + template + bool has_children(SimplexHandle sh) const { return (sh->second.children()->parent() == sh->first); } @@ -765,7 +763,8 @@ class Simplex_tree { } /** Returns the Siblings containing a simplex.*/ - Siblings * self_siblings(Simplex_handle sh) { + template + Siblings* self_siblings(SimplexHandle sh) { if (sh->second.children()->parent() == sh->first) return sh->second.children()->oncles(); else @@ -1133,9 +1132,9 @@ class Simplex_tree { bool make_filtration_non_decreasing() { bool modified = false; // 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().rbegin(); sh != root_.members().rend(); ++sh) { - if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children()); + for (auto& sh : boost::adaptors::reverse(root_.members())) { + if (has_children(&sh)) { + modified |= rec_make_filtration_non_decreasing(sh.second.children()); } } return modified; @@ -1150,22 +1149,22 @@ class Simplex_tree { bool modified = false; // 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 = sib->members().begin(); sh != sib->members().end(); ++sh) { + for (auto& sh : boost::adaptors::reverse(sib->members())) { // Find the maximum filtration value in the border - Boundary_simplex_range boundary = boundary_simplex_range(sh); + 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) { + if (sh.second.filtration() < max_filt_border_value) { // Store the filtration modification information modified = true; - sh->second.assign_filtration(max_filt_border_value); + sh.second.assign_filtration(max_filt_border_value); } - if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children()); + if (has_children(&sh)) { + 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/include/gudhi/Simplex_tree/Simplex_tree_iterators.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h index 936b7a1f..7e0a454d 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h @@ -104,7 +104,8 @@ class Simplex_tree_boundary_simplex_iterator : public boost::iterator_facade< st_(st) { } - Simplex_tree_boundary_simplex_iterator(SimplexTree * st, Simplex_handle sh) + template + Simplex_tree_boundary_simplex_iterator(SimplexTree * st, SimplexHandle sh) : last_(sh->first), sib_(nullptr), st_(st) { -- 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(-) 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 9781709e1c8ba405140345ba2e7d3e521e533e16 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 3 Feb 2016 11:52:24 +0000 Subject: it is a simplex and not a simplex handle git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@999 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4bfc8fe6051480854acbd68fdb5c6f09624aa3da --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 0d12e9b7..3569b323 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1132,9 +1132,9 @@ class Simplex_tree { bool make_filtration_non_decreasing() { bool modified = false; // 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 : boost::adaptors::reverse(root_.members())) { - if (has_children(&sh)) { - modified |= rec_make_filtration_non_decreasing(sh.second.children()); + for (auto& simplex : boost::adaptors::reverse(root_.members())) { + if (has_children(&simplex)) { + modified |= rec_make_filtration_non_decreasing(simplex.second.children()); } } return modified; @@ -1149,22 +1149,22 @@ class Simplex_tree { bool modified = false; // 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 : boost::adaptors::reverse(sib->members())) { + for (auto& simplex : boost::adaptors::reverse(sib->members())) { // Find the maximum filtration value in the border - Boundary_simplex_range boundary = boundary_simplex_range(&sh); + Boundary_simplex_range boundary = boundary_simplex_range(&simplex); 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) { + if (simplex.second.filtration() < max_filt_border_value) { // Store the filtration modification information modified = true; - sh.second.assign_filtration(max_filt_border_value); + simplex.second.assign_filtration(max_filt_border_value); } - if (has_children(&sh)) { - modified |= rec_make_filtration_non_decreasing(sh.second.children()); + if (has_children(&simplex)) { + modified |= rec_make_filtration_non_decreasing(simplex.second.children()); } } // Make the modified information to be traced by upper call -- cgit v1.2.3 From 7fe2c44c56e4fbd176131f31bc4338932f7a9d32 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Fri, 5 Feb 2016 12:24:49 +0000 Subject: Over here I have linkd phat with Gudhi. So far it is done only for cubical complexes, but since I am ONLY using Filtration_simplex_iterator, there should be no problem to have it run with any other class we have. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1004 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ddb3e2c5fa0c2a816e7435c57d32c0644f8163d2 --- ...ubical_complex_periodic_boundary_conditions.cpp | 159 +++++++++++---------- src/Bitmap_cubical_complex/example/CMakeLists.txt | 2 + .../example/Compute_persistence_with_phat.cpp | 60 ++++++++ 3 files changed, 146 insertions(+), 75 deletions(-) create mode 100644 src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp index 3d80c96d..df01240b 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp @@ -1,75 +1,84 @@ - /* 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): Pawel Dlotko - * - * 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 -#include -#include -#include - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff -#include -#include -#include - -using namespace std; - -int main( int argc , char** argv ) -{ - cout << "This program computes persistent homology, by using Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > b( argv[1] ); - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > - , Field_Zp - > pcoh(b,true); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - - - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 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): Pawel Dlotko + * + * 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 +#include +#include +#include + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + +int main( int argc , char** argv ) +{ + clock_t beginOfProgram = clock(); + + cout << "This program computes persistent homology, by using Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > b( argv[1] ); + + cerr << "Here \n"; + + clock_t endCreateBitmap = clock(); + double elapsed_secsCreateBitmap = double(endCreateBitmap - beginOfProgram) / CLOCKS_PER_SEC; + cerr << "Time of creation of bitmap : " << elapsed_secsCreateBitmap << endl; + + + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base >, Field_Zp > pcoh(b,true); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + pcoh.compute_persistent_cohomology( min_persistence ); + + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + clock_t endOfProgram = clock(); + double elapsed_secsOfProgram = double(endOfProgram - beginOfProgram) / CLOCKS_PER_SEC; + cerr << "Overall execution time : " << elapsed_secsOfProgram << endl; + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index 26796e9d..fbd1b28b 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -13,3 +13,5 @@ add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp ) target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) +add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) +target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp new file mode 100644 index 00000000..fe9be33e --- /dev/null +++ b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp @@ -0,0 +1,60 @@ + + /* 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): Pawel Dlotko + * + * 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 +#include +#include +#include +#include + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; + +//standard stuff +#include +#include +#include + +using namespace std; + + +int main( int argc , char** argv ) +{ + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); + cerr << "Cubical complex created \n"; + + + Compute_persistence_with_phat< Bitmap_cubical_complex< Bitmap_cubical_complex_base > , double > phat(&b); + phat::persistence_pairs pairs = phat.compute_persistence_pairs_dualized_chunk_reduction(); + std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > persistence = phat.get_the_intervals( pairs ); + writeBettiNumbersAndPersistenceIntervalsToFile( "phat_persistence" , persistence ); + + return 0; +} -- cgit v1.2.3 From 3be6acc35255b52a60a254fa101aec5b11173b6d Mon Sep 17 00:00:00 2001 From: pdlotko Date: Mon, 8 Feb 2016 15:10:49 +0000 Subject: Adding changes suggested by Marc. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1007 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2462c084e3269a3d44813619f44852d3c8d6e163 --- src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp index fe9be33e..f552a094 100644 --- a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp +++ b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp @@ -52,7 +52,7 @@ int main( int argc , char** argv ) Compute_persistence_with_phat< Bitmap_cubical_complex< Bitmap_cubical_complex_base > , double > phat(&b); - phat::persistence_pairs pairs = phat.compute_persistence_pairs_dualized_chunk_reduction(); + phat::persistence_pairs pairs = phat.compute_persistence_pairs_standard_reduction(); std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > persistence = phat.get_the_intervals( pairs ); writeBettiNumbersAndPersistenceIntervalsToFile( "phat_persistence" , persistence ); -- cgit v1.2.3 From 84399987baac2817e58bf9f5e18ded6aa6893b0f Mon Sep 17 00:00:00 2001 From: pdlotko Date: Tue, 9 Feb 2016 13:26:47 +0000 Subject: adding missing partsy git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1008 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f6de1ee4317763b50233f9a7212bdbf6587ee686 --- .../doc/Gudhi_Cubical_Complex_doc.h | 41 +- src/Bitmap_cubical_complex/doc/exampleBitmap.png | Bin 9594 -> 2549 bytes .../include/gudhi/Bitmap_cubical_complex.h | 28 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 114 +++++- ...cal_complex_periodic_boundary_conditions_base.h | 451 +++++++++++---------- .../include/gudhi/Compute_persistence_with_phat.h | 242 +++++++++++ .../gudhi/phat/algorithms/chunk_reduction.h | 240 +++++++++++ .../include/gudhi/phat/algorithms/row_reduction.h | 55 +++ .../gudhi/phat/algorithms/standard_reduction.h | 45 ++ .../gudhi/phat/algorithms/twist_reduction.h | 50 +++ .../include/gudhi/phat/boundary_matrix.h | 336 +++++++++++++++ .../include/gudhi/phat/compute_persistence_pairs.h | 69 ++++ .../include/gudhi/phat/helpers/dualize.h | 63 +++ .../include/gudhi/phat/helpers/misc.h | 74 ++++ .../gudhi/phat/helpers/thread_local_storage.h | 52 +++ .../include/gudhi/phat/persistence_pairs.h | 151 +++++++ .../phat/representations/abstract_pivot_column.h | 158 ++++++++ .../phat/representations/bit_tree_pivot_column.h | 169 ++++++++ .../gudhi/phat/representations/full_pivot_column.h | 81 ++++ .../phat/representations/sparse_pivot_column.h | 62 +++ .../gudhi/phat/representations/vector_list.h | 98 +++++ .../gudhi/phat/representations/vector_set.h | 100 +++++ .../gudhi/phat/representations/vector_vector.h | 93 +++++ src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 12 +- 24 files changed, 2532 insertions(+), 252 deletions(-) create mode 100644 src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h create mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index 1a6310fb..c06678a1 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -38,20 +38,18 @@ namespace Cubical_complex *Cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. * -* An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerated, while the second one is \a degenerated interval. A boundary of a elementary -*interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerated elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerated elementary interval. An elementary cube \f$ C \f$ is a +* An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerate, while the second one is \a degenerate interval. A boundary of a elementary +*interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerate elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An elementary cube \f$ C \f$ is a -*product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. Embedding dimension of a cube is n, the number of elementary intervals (degenerated or not) in the product. A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the -*number of non degenerated elementary intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained in the following way: +*product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. Embedding dimension of a cube is n, the number of elementary intervals (degenerate or not) in the product. A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the +*number of non degenerate elementary intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained in the following way: *\f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f] *A cubical complex \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex \f$\mathcal{K}\f$ is maximal if it is not in *a boundary of any other cube in \f$\mathcal{K}\f$. A \a support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension of \f$C\f$). * *Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may be a set of two elements). * -*For further details and theory of cubical complexes, please consult \cite kaczynski2004computational . -* -*as well as the following paper \cite peikert2012topological . +*For further details and theory of cubical complexes, please consult \cite kaczynski2004computational as well as the following paper \cite peikert2012topological . * *\section datastructure Data structure. * @@ -73,7 +71,8 @@ namespace Cubical_complex *In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors *that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. *Currently one input from a text file is used. It uses a format used already in Perseus software (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. -*Below we are providing a description of the format. +*Below we are providing a description of the format. The first line contains a number d begin the dimension of the bitmap (2 in the example below). Next d lines are the numbers of +*top dimensional cubes in each dimensions (3 and 3 in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8 20 4 7 6 5 in the example below). * * *\image html "exampleBitmap.png" "Example of a input data." @@ -84,6 +83,29 @@ namespace Cubical_complex 3 3 1 +4 +6 +8 +20 +4 +7 +6 +5 +\endverbatim + +\section Periodic boundary conditions +Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times I_n \f$ be a box +that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary conditions in the direction i, means that the left and the right side of a complex +\f$ \mathcal{K} \f$ are considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed in all directions, then complex +\f$ \mathcal{K} \f$ became n-dimensional torus. One can use various constructors from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical +complex with periodic boundary conditions. One can also use Perseus style input files. To indicate periodic boundary conditions in a given direction, then number of top dimensional cells +in this direction have to be multiplied by -1. For instance: + +*\verbatim +2 +-3 +3 +1 2 3 8 @@ -94,6 +116,9 @@ namespace Cubical_complex 5 \endverbatim +Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. + + */ /** @} */ // end defgroup cubical_complex diff --git a/src/Bitmap_cubical_complex/doc/exampleBitmap.png b/src/Bitmap_cubical_complex/doc/exampleBitmap.png index f8207473..069c6eb2 100644 Binary files a/src/Bitmap_cubical_complex/doc/exampleBitmap.png and b/src/Bitmap_cubical_complex/doc/exampleBitmap.png differ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 63edcadd..82ea8672 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -1,4 +1,4 @@ - /* This file is part of the Gudhi Library. The Gudhi library +/* This file is part of the Gudhi Library. The Gudhi library * (Geometric Understanding in Higher Dimensions) is a generic C++ * library for computational topology. * @@ -65,7 +65,8 @@ public: **/ Bitmap_cubical_complex( const char* perseus_style_file ): T(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) - { + { + //clock_t begin = clock(); if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) { @@ -74,7 +75,8 @@ public: //we initialize this only once, in each constructor, when the bitmap is constructed. //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. - this->initialize_simplex_associated_to_key(); + this->initialize_simplex_associated_to_key(); + //cerr << "Time of running Bitmap_cubical_complex( const char* perseus_style_file ) constructor : " << double(clock() - begin) / CLOCKS_PER_SEC << endl; } @@ -115,7 +117,8 @@ public: //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. this->initialize_simplex_associated_to_key(); - } + } + //*********************************************// //Other 'easy' functions @@ -328,6 +331,15 @@ public: **/ Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) { + /* + std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); + Boundary_simplex_range result( bdry.size() ); + for ( size_t i = 0 ; i != bdry.size() ; ++i ) + { + result[i] = this->simplex_associated_to_key[ bdry[i] ]; + } + return result; + */ return this->get_boundary_of_a_cell(sh); } @@ -500,7 +512,13 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() std::iota (std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); std::sort( simplex_associated_to_key.begin() , simplex_associated_to_key.end() , - is_before_in_filtration(this) ); + is_before_in_filtration(this) ); + + //we still need to deal here with a key_associated_to_simplex: + for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) + { + this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; + } } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 600f250d..22b703a9 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include "Bitmap_cubical_complex/counter.h" @@ -68,7 +69,9 @@ public: /** *Default constructor **/ - Bitmap_cubical_complex_base(){} + Bitmap_cubical_complex_base() + { + } /** * There are a few constructors of a Bitmap_cubical_complex_base class. * First one, that takes vector, creates an empty bitmap of a dimension equal @@ -110,7 +113,7 @@ public: * non-negative integers pointing to the * positions of (co)boundary element of the input cell. **/ - inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + virtual inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; /** * In the case of get_dimension_of_a_cell function, the output is a non-negative integer * indicating the dimension of a cell. @@ -140,7 +143,7 @@ public: /** * Returns number of all cubes in the data structure. **/ - inline unsigned size_of_bitmap()const + inline unsigned size()const { return this->data.size(); } @@ -149,7 +152,19 @@ public: * Writing to stream operator. **/ template - friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + + + /** + * Functions that put the input data to bins. + **/ + void put_data_toBins( size_t number_of_bins ); + void put_data_toBins( T diameter_of_bin ); + + /** + * Functions to find min and max values of filtration. + **/ + std::pair< T ,T > min_max_filtration(); //ITERATORS @@ -157,22 +172,41 @@ public: * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ - typedef typename std::vector< T >::iterator all_cells_iterator; - all_cells_iterator all_cells_begin()const + typedef typename std::vector< T >::iterator all_cells_iterator; + + /** + * Function returning an iterator to the first cell of the bitmap. + **/ + all_cells_iterator all_cells_begin() { return this->data.begin(); - } + } + + /** + * Function returning an iterator to the last cell of the bitmap. + **/ all_cells_iterator all_cells_end()const { return this->data.end(); } - - typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + /** + * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). + **/ + typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + + /** + * Function returning a constant iterator to the first cell of the bitmap. + **/ all_cells_const_iterator all_cells_const_begin()const { return this->data.begin(); - } + } + + /** + * Function returning a constant iterator to the last cell of the bitmap. + **/ all_cells_const_iterator all_cells_const_end()const { return this->data.end(); @@ -269,12 +303,20 @@ public: protected: std::vector< size_t > counter; Bitmap_cubical_complex_base& b; - }; + }; + + /** + * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell cell of the bitmap. + **/ Top_dimensional_cells_iterator top_dimensional_cells_begin() { Top_dimensional_cells_iterator a(*this); return a; - } + } + + /** + * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell cell of the bitmap. + **/ Top_dimensional_cells_iterator top_dimensional_cells_end() { Top_dimensional_cells_iterator a(*this); @@ -351,6 +393,50 @@ protected: }; +template +void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) +{ + bool bdg = false; + + std::pair< T ,T > min_max = this->min_max_filtration(); + T dx = (min_max.second-min_max.first)/(T)number_of_bins; + + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) +{ + bool bdg = false; + std::pair< T ,T > min_max = this->min_max_filtration(); + + size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() +{ + std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( this->data[i] < min_max.first )min_max.first = this->data[i]; + if ( this->data[i] > min_max.second )min_max.second = this->data[i]; + } + return min_max; +} template @@ -422,7 +508,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu unsigned dimensionOfData; inFiltration >> dimensionOfData; - if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;} + if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;getchar();} std::vector sizes; sizes.reserve( dimensionOfData ); diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 28911ea8..38c218dc 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -1,120 +1,120 @@ -#pragma once -#include -#include "Bitmap_cubical_complex_base.h" - +#pragma once +#include +#include "Bitmap_cubical_complex_base.h" + using namespace std; namespace Gudhi { namespace Cubical_complex -{ - -//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures -//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the -//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base - -template -class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base -{ -public: - //constructors that take an extra parameter: - Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); - - //overwritten methods co compute boundary and coboundary - virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; - std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; - //inline unsigned get_dimension_of_a_cell( size_t cell )const; - -protected: - std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; +{ + +//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures +//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the +//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base + +template +class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base +{ +public: + //constructors that take an extra parameter: + Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); + + //overwritten methods co compute boundary and coboundary + virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + //inline unsigned get_dimension_of_a_cell( size_t cell )const; + +protected: + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; void set_up_containers( const std::vector& sizes ) - { + { unsigned multiplier = 1; for ( size_t i = 0 ; i != sizes.size() ; ++i ) { this->sizes.push_back(sizes[i]); this->multipliers.push_back(multiplier); - - if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) - { - multiplier *= 2*sizes[i]; - } - else - { - multiplier *= 2*sizes[i]+1; + + if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) + { + multiplier *= 2*sizes[i]; + } + else + { + multiplier *= 2*sizes[i]+1; } } //std::reverse( this->sizes.begin() , this->sizes.end() ); this->data = std::vector(multiplier,std::numeric_limits::max()); this->total_number_of_cells = multiplier; - } - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ); - void construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); -}; - -template -void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( dimensions ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) - { - *it = topDimensionalCells[i]; - ++i; - } - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) -{ - //for Perseus style files: - bool dbg = false; - + } + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ); + void construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); +}; + +template +void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( dimensions ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = topDimensionalCells[i]; + ++i; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) +{ + + //for Perseus style files: + bool dbg = false; ifstream inFiltration; inFiltration.open( perseus_style_file ); unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); - - std::vector sizes; + inFiltration >> dimensionOfData; + + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); + + std::vector sizes; sizes.reserve( dimensionOfData ); for ( size_t i = 0 ; i != dimensionOfData ; ++i ) { int size_in_this_dimension; - inFiltration >> size_in_this_dimension; - if ( size_in_this_dimension < 0 ) - { - this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; + inFiltration >> size_in_this_dimension; + if ( size_in_this_dimension < 0 ) + { + this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; } sizes.push_back( abs(size_in_this_dimension) ); } - this->set_up_containers( sizes ); - + this->set_up_containers( sizes ); + typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); it = this->top_dimensional_cells_begin(); while ( !inFiltration.eof() ) { double filtrationLevel; - inFiltration >> filtrationLevel; - if ( inFiltration.eof() )break; + inFiltration >> filtrationLevel; + if ( inFiltration.eof() )break; if ( dbg ) { @@ -128,124 +128,137 @@ Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_comp ++it; } inFiltration.close(); - this->impose_lower_star_filtration(); - - /* - char* filename = (char*)perseus_style_file; - //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; - ifstream file( filename , ios::binary | ios::ate ); - unsigned realSizeOfFile = file.tellg(); - file.close(); - realSizeOfFile = realSizeOfFile/sizeof(T); - - unsigned w, h, d; - - w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); - - T* slice = new T[w*h*d]; - if (slice == NULL) - { - cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; - exit(EXIT_FAILURE); - } - - FILE* fp; - if ((fp=fopen( filename, "rb" )) == NULL ) - { - cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; - exit(1); - } - fread( slice,4,w*h*d,fp ); - fclose(fp); - std::vector data(slice,slice+w*h*d); - delete[] slice; - std::vector< unsigned > sizes; - sizes.push_back(w); - sizes.push_back(w); - sizes.push_back(w); - - std::vector< bool > directions; - directions.push_back( true ); - directions.push_back( true ); - directions.push_back( true ); - Bitmap_cubical_complex_periodic_boundary_conditions_base b( sizes, data, directions ); - *this = b; - */ -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ) -{ - std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - - - - - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - -//***********************Methods************************// - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const -{ - bool dbg = false; - if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} - + this->impose_lower_star_filtration(); + +/* + char* filename = (char*)perseus_style_file; + //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; + ifstream file( filename , ios::binary | ios::ate ); + unsigned realSizeOfFile = file.tellg(); + file.close(); + realSizeOfFile = realSizeOfFile/sizeof(T); + + unsigned w, h, d; + + w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); + + T* slice = new T[w*h*d]; + if (slice == NULL) + { + cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; + exit(EXIT_FAILURE); + } + + FILE* fp; + if ((fp=fopen( filename, "rb" )) == NULL ) + { + cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; + exit(1); + } + + clock_t read_begin = clock(); + fread( slice,4,w*h*d,fp ); + fclose(fp); + cerr << "Time of reading the file : " << double(clock() - read_begin) / CLOCKS_PER_SEC << endl; + + + clock_t begin_creation_bitap = clock(); + std::vector data(slice,slice+w*h*d); + delete[] slice; + std::vector< unsigned > sizes; + sizes.push_back(w); + sizes.push_back(w); + sizes.push_back(w); + + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->set_up_containers( sizes ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = data[i]; + ++i; + } + this->impose_lower_star_filtration(); + cerr << "Time of creation of a bitmap : " << double(clock() - begin_creation_bitap ) / CLOCKS_PER_SEC << endl; +*/ +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ) +{ + std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + + + + + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + +//***********************Methods************************// + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const +{ + bool dbg = false; + if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} + std::vector< size_t > boundary_elements; size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { - unsigned position = cell1/this->multipliers[i-1]; - //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. + unsigned position = cell1/this->multipliers[i-1]; + //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. if ( position%2 == 1 ) - { - //if there are no periodic boundary conditions in this direction, we do not have to do anything. - if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //cerr << "A\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. - if ( position != 2*this->sizes[ i-1 ]-1 ) - { - //cerr << "B\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //cerr << "C\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} - } + { + //if there are no periodic boundary conditions in this direction, we do not have to do anything. + if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //cerr << "A\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. + if ( position != 2*this->sizes[ i-1 ]-1 ) + { + //cerr << "B\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //cerr << "C\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} + } } } cell1 = cell1%this->multipliers[i-1]; } - return boundary_elements; -} - + return boundary_elements; +} + template std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const { @@ -254,12 +267,12 @@ std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_basemultipliers.size() ; i != 0 ; --i ) { - unsigned position = cell1/this->multipliers[i-1]; - //if the cell has zero length in this direction, then it will have cbd in this direction. + unsigned position = cell1/this->multipliers[i-1]; + //if the cell has zero length in this direction, then it will have cbd in this direction. if ( position%2 == 0 ) - { - if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { + { + if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { //no periodic boundary conditions in this direction if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) { @@ -268,31 +281,31 @@ std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_basesizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) { coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - } - else - { - //we want to have periodic boundary conditions in this direction - if ( counter[i-1] != 0 ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - else - { - //in this case counter[i-1] == 0. - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); - } + } } - } + else + { + //we want to have periodic boundary conditions in this direction + if ( counter[i-1] != 0 ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + else + { + //in this case counter[i-1] == 0. + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); + } + } + } cell1 = cell1%this->multipliers[i-1]; } return coboundary_elements; -} - - - -}//Cubical_complex -}//namespace Gudhi +} + + + +}//Cubical_complex +}//namespace Gudhi diff --git a/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h b/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h new file mode 100644 index 00000000..9f4ada45 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h @@ -0,0 +1,242 @@ +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 . + */ + +#pragma once + + +#include "phat/compute_persistence_pairs.h" +#include "phat/representations/vector_vector.h" +#include "phat/algorithms/standard_reduction.h" +#include "phat/algorithms/chunk_reduction.h" +#include "phat/algorithms/row_reduction.h" +#include "phat/algorithms/twist_reduction.h" + + +namespace Gudhi +{ + + +//the only aim of this class is to have a ability to compute persistence with phat. +template +void writeBettiNumbersAndPersistenceIntervalsToFile( char* prefix , std::pair< std::vector > , std::vector< std::vector< std::pair > > > resutsFromPhat ) +{ + std::ostringstream filenameStr; + filenameStr << prefix << "_bettiNumbers"; + std::string str = filenameStr.str(); + const char* filename = str.c_str(); + ofstream out; + out.open( filename ); + for ( size_t dim = 0 ; dim != resutsFromPhat.first.size() ; ++dim ) + { + out << "Dimension : " << dim << endl; + for ( size_t i = 0 ; i != resutsFromPhat.first[dim].size() ; ++i ) + { + out << resutsFromPhat.first[dim][i] << endl; + } + out << endl; + } + out.close(); + + + cerr << "Write persistence to file \n"; + for ( size_t dim = 0 ; dim != resutsFromPhat.second.size() ; ++dim ) + { + cerr << "resutsFromPhat.second[dim].size() : " << resutsFromPhat.second[dim].size() << endl; + if ( resutsFromPhat.second[dim].size() == 0 )continue; + std::ostringstream filenameStr; + filenameStr << prefix << "_persistence_" << dim; + std::string str = filenameStr.str(); + const char* filename = str.c_str(); + ofstream out1; + out1.open( filename ); + for ( size_t i = 0 ; i != resutsFromPhat.second[dim].size() ; ++i ) + { + out1 << resutsFromPhat.second[dim][i].first << " " << resutsFromPhat.second[dim][i].second << endl; + } + out1.close(); + } +}//writeBettiNumbersAndPersistenceIntervalsToFile + + +template +class Compute_persistence_with_phat +{ +public: + Compute_persistence_with_phat( T* data_structure_ ); + std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > get_the_intervals( phat::persistence_pairs pairs ); + + phat::persistence_pairs compute_persistence_pairs_dualized_chunk_reduction(); + phat::persistence_pairs compute_persistence_pairs_twist_reduction(); + phat::persistence_pairs compute_persistence_pairs_standard_reduction(); + //phat::persistence_pairs compute_persistence_pairs_spectral_sequence_reduction(); +private: + void print_bd_matrix(); + phat::boundary_matrix< phat::vector_vector > boundary_matrix; + T* data_structure; +}; + +template +void Compute_persistence_with_phat::print_bd_matrix() +{ + std::cout << "The boundary matrix has " << this->boundary_matrix.get_num_cols() << " columns: " << std::endl; + for( phat::index col_idx = 0; col_idx < this->boundary_matrix.get_num_cols(); col_idx++ ) { + std::cout << "Colum " << col_idx << " represents a cell of dimension " << (int)this->boundary_matrix.get_dim( col_idx ) << ". "; + if( !this->boundary_matrix.is_empty( col_idx ) ) { + std::vector< phat::index > temp_col; + this->boundary_matrix.get_col( col_idx, temp_col ); + std::cout << "Its boundary consists of the cells"; + for( phat::index idx = 0; idx < (phat::index)temp_col.size(); idx++ ) + std::cout << " " << temp_col[ idx ]; + } + std::cout << std::endl; + } +} + +template +phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_dualized_chunk_reduction() +{ + phat::persistence_pairs pairs; + phat::compute_persistence_pairs_dualized< phat::chunk_reduction >( pairs, this->boundary_matrix ); + return pairs; +} + +template +phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_twist_reduction() +{ + phat::persistence_pairs pairs; + phat::compute_persistence_pairs< phat::twist_reduction >( pairs, this->boundary_matrix ); + return pairs; +} + +template +phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_standard_reduction() +{ + phat::persistence_pairs pairs; + phat::compute_persistence_pairs< phat::standard_reduction >( pairs, this->boundary_matrix ); + return pairs; +} + +//template +//phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_spectral_sequence_reduction() +//{ +// phat::persistence_pairs pairs; +// phat::compute_persistence_pairs< phat::spectral_sequence_reduction >( pairs, this->boundary_matrix ); +// return pairs; +//} + +template +Compute_persistence_with_phat::Compute_persistence_with_phat( T* data_structure_ ):data_structure( data_structure_ ) +{ + bool dbg = false; + this->boundary_matrix.set_num_cols( this->data_structure->num_simplices() ); + + //setting up the dimensions of cells: + for ( size_t i = 0 ; i != this->data_structure->num_simplices() ; ++i ) + { + this->boundary_matrix.set_dim( i, this->data_structure->dimension( this->data_structure->simplex(i) ) ); + } + + + //now it is time to set up the boundary matrix: + typename T::Filtration_simplex_range range = this->data_structure->filtration_simplex_range(); + std::vector< phat::index > temp_col; + for ( typename T::Filtration_simplex_iterator it = range.begin() ; it != range.end() ; ++it ) + { + typename T::Boundary_simplex_range boundary_range = this->data_structure->boundary_simplex_range( *it ); + for ( typename T::Boundary_simplex_iterator bd = boundary_range.begin() ; bd != boundary_range.end() ; ++bd ) + { + temp_col.push_back( this->data_structure->key( *bd ) ); + } + //we do not know if the boundary elements are sorted according to filtration, that is why I am enforcing it here: + this->boundary_matrix.set_col( this->data_structure->key( *it ) , temp_col ); + temp_col.clear(); + } +} + +template +std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > Compute_persistence_with_phat::get_the_intervals( phat::persistence_pairs pairs ) +{ + bool dbg = false; + //in order to find the birth times of the infinite homology classes, we need to know which elements are not paired. To search for them, we will use this vector: + std::vector isTheElementPaired( this->data_structure->num_simplices() , false ); + + //now it is time to recover the finite persistence pairs and the Betti numbers: + std::vector< std::vector< std::pair > > finitePersistencePairs( this->data_structure->dimension() ); + for( phat::index idx = 0; idx < pairs.get_num_pairs(); idx++ ) + { + typename T::Simplex_key positionOfBeginOfInterval = pairs.get_pair( idx ).first; + typename T::Simplex_key positionOfEndOfInterval = pairs.get_pair( idx ).second; + + typename T::Simplex_handle first_simplex = this->data_structure->simplex(positionOfBeginOfInterval); + typename T::Simplex_handle second_simplex = this->data_structure->simplex(positionOfEndOfInterval); + + typename T::Filtration_value valueFirst = this->data_structure->filtration( first_simplex ); + typename T::Filtration_value valueSecond = this->data_structure->filtration( second_simplex ); + + if ( valueFirst > valueSecond ){std::swap( valueFirst , valueSecond );} + + unsigned dimFirst = this->data_structure->dimension(first_simplex); + unsigned dimSecond = this->data_structure->dimension(second_simplex); + unsigned dim = std::min( dimFirst , dimSecond ); + + + //we are ignoring trivial barcodes + if ( valueFirst != valueSecond ) + { + finitePersistencePairs[ dim ].push_back( std::make_pair(valueFirst , valueSecond) ); + if ( dbg ){cerr << "Adding barcode : " << valueFirst << "," << valueSecond << endl;} + } + + //isTheElementPaired[ positionOfBeginOfIntervalInBitmap ] = true; + //isTheElementPaired[ positionOfEndOfIntervalInBitmap ] = true; + isTheElementPaired[ pairs.get_pair( idx ).first ] = true; + isTheElementPaired[ pairs.get_pair( idx ).second ] = true; + } + + + std::vector< std::vector > birthTimesOfInfinitePersistnceClasses(this->data_structure->dimension()+1 ); + for ( size_t i = 0 ; i != this->data_structure->dimension()+1 ; ++i ) + { + std::vector v; + birthTimesOfInfinitePersistnceClasses[i] = v; + } + for ( size_t i = 0 ; i != isTheElementPaired.size() ; ++i ) + { + if ( isTheElementPaired[i] == false ) + { + //i-th element is not paired, therefore it gives an infinite class + typename T::Simplex_handle simplex = this->data_structure->simplex(i); + birthTimesOfInfinitePersistnceClasses[ this->data_structure->dimension( simplex ) ].push_back( this->data_structure->filtration(simplex) ); + } + } + + //sorting finite persistence pairs: + for ( size_t dim = 0 ; dim != finitePersistencePairs.size() ; ++dim ) + { + std::sort( finitePersistencePairs[dim].begin() , finitePersistencePairs[dim].end() ); + } + return std::make_pair( birthTimesOfInfinitePersistnceClasses , finitePersistencePairs ); +}//Compute_persistence_with_phat + + + +}//namespace Gudhi diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h new file mode 100644 index 00000000..352392a8 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h @@ -0,0 +1,240 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../boundary_matrix.h" + +namespace phat { + class chunk_reduction { + public: + enum column_type { GLOBAL + , LOCAL_POSITIVE + , LOCAL_NEGATIVE }; + + public: + template< typename Representation > + void operator() ( boundary_matrix< Representation >& boundary_matrix ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + const dimension max_dim = boundary_matrix.get_max_dim(); + + std::vector< index > lowest_one_lookup( nr_columns, -1 ); + std::vector < column_type > column_type( nr_columns, GLOBAL ); + std::vector< char > is_active( nr_columns, false ); + + std::vector chunk_boundaries; + _get_chunks( boundary_matrix, chunk_boundaries ); + + // Phase 1: Reduce chunks locally -- 1st pass + #pragma omp parallel for schedule( guided, 1 ) + for( index chunk_id = 0; chunk_id < (index) chunk_boundaries.size() - 2; chunk_id += 2 ) + _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, max_dim, + chunk_boundaries[chunk_id], chunk_boundaries[chunk_id+2] - 1 ); + boundary_matrix.sync(); + + // Phase 1: Reduce chunks locally -- 2nd pass + #pragma omp parallel for schedule( guided, 1 ) + for( index chunk_id = 1; chunk_id < (index) chunk_boundaries.size() - 2; chunk_id += 2 ) + _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, max_dim, + chunk_boundaries[chunk_id], chunk_boundaries[chunk_id+2] - 1 ); + boundary_matrix.sync(); + + // get global columns + std::vector< index > global_columns; + for( index cur_col_idx = 0; cur_col_idx < nr_columns; cur_col_idx++ ) + if( column_type[ cur_col_idx ] == GLOBAL ) + global_columns.push_back( cur_col_idx ); + + // get active columns + #pragma omp parallel for + for( index idx = 0; idx < (index)global_columns.size(); idx++ ) + is_active[ global_columns[ idx ] ] = true; + _get_active_columns( boundary_matrix, lowest_one_lookup, column_type, global_columns, is_active ); + + // Phase 2+3: Simplify columns and reduce them + for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) { + // Phase 2: Simplify columns + std::vector< index > temp_col; + #pragma omp parallel for schedule( guided, 1 ), private( temp_col ) + for( index idx = 0; idx < (index)global_columns.size(); idx++ ) + if( boundary_matrix.get_dim( global_columns[ idx ] ) == cur_dim ) + _global_column_simplification( global_columns[ idx ], boundary_matrix, lowest_one_lookup, column_type, is_active, temp_col ); + boundary_matrix.sync(); + + // Phase 3: Reduce columns + for( index idx = 0; idx < (index)global_columns.size(); idx++ ) { + index cur_col = global_columns[ idx ]; + if( boundary_matrix.get_dim( cur_col ) == cur_dim && column_type[ cur_col ] == GLOBAL ) { + index lowest_one = boundary_matrix.get_max_index( cur_col ); + while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { + boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); + lowest_one = boundary_matrix.get_max_index( cur_col ); + } + if( lowest_one != -1 ) { + lowest_one_lookup[ lowest_one ] = cur_col; + boundary_matrix.clear( lowest_one ); + } + } + } + } + + boundary_matrix.sync(); + } + + protected: + template< typename Representation > + void _get_chunks( const boundary_matrix< Representation >& boundary_matrix + , std::vector< index >& chunk_boundaries) + { + chunk_boundaries.clear(); + std::vector temp_chunk_boundaries; + const index nr_columns = boundary_matrix.get_num_cols(); + + // size of chuks = sqrt(N) + const index chunk_size = (index) sqrt( (float)nr_columns ); + + // size of chunks = N / num_threads + //const index chunk_size = nr_columns / omp_get_max_threads(); + + for ( index cur_col = 0; cur_col < nr_columns; cur_col++ ) + if( cur_col % chunk_size == 0 ) + temp_chunk_boundaries.push_back( cur_col ); + temp_chunk_boundaries.push_back( nr_columns ); + + // subdivide chunks for interleaved 2 pass appraoch + for( index chunk_id = 0; chunk_id < (index) temp_chunk_boundaries.size(); chunk_id ++ ) { + chunk_boundaries.push_back( temp_chunk_boundaries[ chunk_id ] ); + if( chunk_id < (index) temp_chunk_boundaries.size() - 1 ) { + index midPoint = ( temp_chunk_boundaries[ chunk_id ] + temp_chunk_boundaries[ chunk_id + 1 ] ) / 2; + chunk_boundaries.push_back( midPoint ); + } + } + } + + template< typename Representation > + void _local_chunk_reduction( boundary_matrix< Representation >& boundary_matrix + , std::vector& lowest_one_lookup + , std::vector< column_type >& column_type + , const dimension max_dim + , const index chunk_begin + , const index chunk_end ) { + for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) { + for( index cur_col = chunk_begin; cur_col <= chunk_end; cur_col++ ) { + if( column_type[ cur_col ] == GLOBAL && boundary_matrix.get_dim( cur_col ) == cur_dim ) { + index lowest_one = boundary_matrix.get_max_index( cur_col ); + while( lowest_one != -1 && lowest_one >= chunk_begin && lowest_one_lookup[ lowest_one ] != -1 ) { + boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); + lowest_one = boundary_matrix.get_max_index( cur_col ); + } + if( lowest_one >= chunk_begin ) { + lowest_one_lookup[ lowest_one ] = cur_col; + column_type[ cur_col ] = LOCAL_NEGATIVE; + column_type[ lowest_one ] = LOCAL_POSITIVE; + boundary_matrix.clear( lowest_one ); + } + } + } + } + } + + template< typename Representation > + void _get_active_columns( const boundary_matrix< Representation >& boundary_matrix + , const std::vector< index >& lowest_one_lookup + , const std::vector< column_type >& column_type + , const std::vector< index >& global_columns + , std::vector< char >& is_active ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + std::vector< char > finished( nr_columns, false ); + + std::vector< std::pair < index, index > > stack; + std::vector< index > cur_col_values; + #pragma omp parallel for schedule( guided, 1 ), private( stack, cur_col_values ) + for( index idx = 0; idx < (index)global_columns.size(); idx++ ) { + bool pop_next = false; + index start_col = global_columns[ idx ]; + stack.push_back( std::pair< index, index >( start_col, -1 ) ); + while( !stack.empty() ) { + index cur_col = stack.back().first; + index prev_col = stack.back().second; + if( pop_next ) { + stack.pop_back(); + pop_next = false; + if( prev_col != -1 ) { + if( is_active[ cur_col ] ) { + is_active[ prev_col ] = true; + } + if( prev_col == stack.back().first ) { + finished[ prev_col ] = true; + pop_next = true; + } + } + } else { + pop_next = true; + boundary_matrix.get_col( cur_col, cur_col_values ); + for( index idx = 0; idx < (index) cur_col_values.size(); idx++ ) { + index cur_row = cur_col_values[ idx ]; + if( ( column_type[ cur_row ] == GLOBAL ) ) { + is_active[ cur_col ] = true; + } else if( column_type[ cur_row ] == LOCAL_POSITIVE ) { + index next_col = lowest_one_lookup[ cur_row ]; + if( next_col != cur_col && !finished[ cur_col ] ) { + stack.push_back( std::make_pair( next_col, cur_col ) ); + pop_next = false; + } + } + } + } + } + } + } + + template< typename Representation > + void _global_column_simplification( const index col_idx + , boundary_matrix< Representation >& boundary_matrix + , const std::vector< index >& lowest_one_lookup + , const std::vector< column_type >& column_type + , const std::vector< char >& is_active + , std::vector< index >& temp_col ) + { + temp_col.clear(); + while( !boundary_matrix.is_empty( col_idx ) ) { + index cur_row = boundary_matrix.get_max_index( col_idx ); + switch( column_type[ cur_row ] ) { + case GLOBAL: + temp_col.push_back( cur_row ); + boundary_matrix.remove_max( col_idx ); + break; + case LOCAL_NEGATIVE: + boundary_matrix.remove_max( col_idx ); + break; + case LOCAL_POSITIVE: + if( is_active[ lowest_one_lookup[ cur_row ] ] ) + boundary_matrix.add_to( lowest_one_lookup[ cur_row ], col_idx ); + else + boundary_matrix.remove_max( col_idx ); + break; + } + } + std::reverse( temp_col.begin(), temp_col.end() ); + boundary_matrix.set_col( col_idx, temp_col ); + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h new file mode 100644 index 00000000..2047cafd --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h @@ -0,0 +1,55 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../boundary_matrix.h" + +namespace phat { + class row_reduction { + public: + template< typename Representation > + void operator() ( boundary_matrix< Representation >& boundary_matrix ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + std::vector< std::vector< index > > lowest_one_lookup( nr_columns ); + + for( index cur_col = nr_columns - 1; cur_col >= 0; cur_col-- ) { + if( !boundary_matrix.is_empty( cur_col ) ) + lowest_one_lookup[ boundary_matrix.get_max_index( cur_col ) ].push_back( cur_col ); + + if( !lowest_one_lookup[ cur_col ].empty() ) { + boundary_matrix.clear( cur_col ); + std::vector< index >& cols_with_cur_lowest = lowest_one_lookup[ cur_col ]; + index source = *min_element( cols_with_cur_lowest.begin(), cols_with_cur_lowest.end() ); + for( index idx = 0; idx < (index)cols_with_cur_lowest.size(); idx++ ) { + index target = cols_with_cur_lowest[ idx ]; + if( target != source && !boundary_matrix.is_empty( target ) ) { + boundary_matrix.add_to( source, target ); + if( !boundary_matrix.is_empty( target ) ) { + index lowest_one_of_target = boundary_matrix.get_max_index( target ); + lowest_one_lookup[ lowest_one_of_target ].push_back( target ); + } + } + } + } + } + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h new file mode 100644 index 00000000..b2c91a85 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h @@ -0,0 +1,45 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../boundary_matrix.h" + +namespace phat { + class standard_reduction { + public: + template< typename Representation > + void operator() ( boundary_matrix< Representation >& boundary_matrix ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + std::vector< index > lowest_one_lookup( nr_columns, -1 ); + + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + index lowest_one = boundary_matrix.get_max_index( cur_col ); + while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { + boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); + lowest_one = boundary_matrix.get_max_index( cur_col ); + } + if( lowest_one != -1 ) { + lowest_one_lookup[ lowest_one ] = cur_col; + } + } + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h new file mode 100644 index 00000000..1bdd8de2 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h @@ -0,0 +1,50 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../boundary_matrix.h" + +namespace phat { + class twist_reduction { + public: + template< typename Representation > + void operator () ( boundary_matrix< Representation >& boundary_matrix ) { + + const index nr_columns = boundary_matrix.get_num_cols(); + std::vector< index > lowest_one_lookup( nr_columns, -1 ); + + for( index cur_dim = boundary_matrix.get_max_dim(); cur_dim >= 1 ; cur_dim-- ) { + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + if( boundary_matrix.get_dim( cur_col ) == cur_dim ) { + index lowest_one = boundary_matrix.get_max_index( cur_col ); + while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { + boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); + lowest_one = boundary_matrix.get_max_index( cur_col ); + } + if( lowest_one != -1 ) { + lowest_one_lookup[ lowest_one ] = cur_col; + boundary_matrix.clear( lowest_one ); + } + } + } + } + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h b/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h new file mode 100644 index 00000000..941537da --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h @@ -0,0 +1,336 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "helpers/misc.h" +#include "representations/bit_tree_pivot_column.h" + +// interface class for the main data structure -- implementations of the interface can be found in ./representations +namespace phat { + template< class Representation = bit_tree_pivot_column > + class boundary_matrix + { + + protected: + Representation rep; + + // interface functions -- actual implementation and complexity depends on chosen @Representation template + public: + // get overall number of columns in boundary_matrix + index get_num_cols() const { return rep._get_num_cols(); } + + // set overall number of columns in boundary_matrix + void set_num_cols( index nr_of_columns ) { rep._set_num_cols( nr_of_columns ); } + + // get dimension of given index + dimension get_dim( index idx ) const { return rep._get_dim( idx ); } + + // set dimension of given index + void set_dim( index idx, dimension dim ) { rep._set_dim( idx, dim ); } + + // replaces content of @col with boundary of given index + void get_col( index idx, column& col ) const { rep._get_col( idx, col ); } + + // set column @idx to the values contained in @col + void set_col( index idx, const column& col ) { rep._set_col( idx, col ); } + + // true iff boundary of given column is empty + bool is_empty( index idx ) const { return rep._is_empty( idx ); } + + // largest index of given column (new name for lowestOne()) + index get_max_index( index idx ) const { return rep._get_max_index( idx ); } + + // removes maximal index from given column + void remove_max( index idx ) { rep._remove_max( idx ); } + + // adds column @source to column @target' + void add_to( index source, index target ) { rep._add_to( source, target ); } + + // clears given column + void clear( index idx ) { rep._clear( idx ); } + + // syncronizes all internal data structures -- has to be called before and after any multithreaded access! + void sync() { rep._sync(); } + + // info functions -- independent of chosen 'Representation' + public: + // maximal dimension + dimension get_max_dim() const { + dimension cur_max_dim = 0; + for( index idx = 0; idx < get_num_cols(); idx++ ) + cur_max_dim = get_dim( idx ) > cur_max_dim ? get_dim( idx ) : cur_max_dim; + return cur_max_dim; + } + + // number of nonzero rows for given column @idx + index get_num_rows( index idx ) const { + column cur_col; + get_col( idx, cur_col ); + return cur_col.size(); + } + + // maximal number of nonzero rows of all columns + index get_max_col_entries() const { + index max_col_entries = -1; + const index nr_of_columns = get_num_cols(); + for( index idx = 0; idx < nr_of_columns; idx++ ) + max_col_entries = get_num_rows( idx ) > max_col_entries ? get_num_rows( idx ) : max_col_entries; + return max_col_entries; + } + + // maximal number of nonzero cols of all rows + index get_max_row_entries() const { + size_t max_row_entries = 0; + const index nr_of_columns = get_num_cols(); + std::vector< std::vector< index > > transposed_matrix( nr_of_columns ); + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + get_col( cur_col, temp_col ); + for( index idx = 0; idx < (index)temp_col.size(); idx++) + transposed_matrix[ temp_col[ idx ] ].push_back( cur_col ); + } + for( index idx = 0; idx < nr_of_columns; idx++ ) + max_row_entries = transposed_matrix[ idx ].size() > max_row_entries ? transposed_matrix[ idx ].size() : max_row_entries; + return max_row_entries; + } + + // overall number of entries in the matrix + index get_num_entries() const { + index number_of_nonzero_entries = 0; + const index nr_of_columns = get_num_cols(); + for( index idx = 0; idx < nr_of_columns; idx++ ) + number_of_nonzero_entries += get_num_rows( idx ); + return number_of_nonzero_entries; + } + + // operators / constructors + public: + boundary_matrix() {}; + + template< class OtherRepresentation > + boundary_matrix( const boundary_matrix< OtherRepresentation >& other ) { + *this = other; + } + + template< typename OtherRepresentation > + bool operator==( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const { + const index number_of_columns = this->get_num_cols(); + + if( number_of_columns != other_boundary_matrix.get_num_cols() ) + return false; + + column temp_col; + column other_temp_col; + for( index idx = 0; idx < number_of_columns; idx++ ) { + this->get_col( idx, temp_col ); + other_boundary_matrix.get_col( idx, other_temp_col ); + if( temp_col != other_temp_col || this->get_dim( idx ) != other_boundary_matrix.get_dim( idx ) ) + return false; + } + return true; + } + + template< typename OtherRepresentation > + bool operator!=( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const { + return !( *this == other_boundary_matrix ); + } + + template< typename OtherRepresentation > + boundary_matrix< Representation >& operator=( const boundary_matrix< OtherRepresentation >& other ) + { + const index nr_of_columns = other.get_num_cols(); + this->set_num_cols( nr_of_columns ); + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + this->set_dim( cur_col, other.get_dim( cur_col ) ); + other.get_col( cur_col, temp_col ); + this->set_col( cur_col, temp_col ); + } + + // by convention, always return *this + return *this; + } + + // I/O -- independent of chosen 'Representation' + public: + + // initializes boundary_matrix from (vector, vector) pair -- untested + template< typename index_type, typename dimemsion_type > + void load_vector_vector( const std::vector< std::vector< index_type > >& input_matrix, const std::vector< dimemsion_type >& input_dims ) { + const index nr_of_columns = (index)input_matrix.size(); + this->set_num_cols( nr_of_columns ); + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + this->set_dim( cur_col, (dimension)input_dims[ cur_col ] ); + + index num_rows = input_matrix[ cur_col ].size(); + temp_col.resize( num_rows ); + for( index cur_row = 0; cur_row < num_rows; cur_row++ ) + temp_col[ cur_row ] = (index)input_matrix[ cur_col ][ cur_row ]; + this->set_col( cur_col, temp_col ); + } + } + + template< typename index_type, typename dimemsion_type > + void save_vector_vector( std::vector< std::vector< index_type > >& output_matrix, std::vector< dimemsion_type >& output_dims ) { + const index nr_of_columns = get_num_cols(); + output_matrix.resize( nr_of_columns ); + output_dims.resize( nr_of_columns ); + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + output_dims[ cur_col ] = (dimemsion_type)get_dim( cur_col ); + get_col( cur_col, temp_col ); + index num_rows = temp_col.size(); + output_matrix[ cur_col ].clear(); + output_matrix[ cur_col ].resize( num_rows ); + for( index cur_row = 0; cur_row < num_rows; cur_row++ ) + output_matrix[ cur_col ][ cur_row ] = (index_type)temp_col[ cur_row ]; + } + } + + // Loads the boundary_matrix from given file in ascii format + // Format: each line represents a column, first number is dimension, other numbers are the content of the column. + // Ignores empty lines and lines starting with a '#'. + bool load_ascii( std::string filename ) { + // first count number of columns: + std::string cur_line; + std::ifstream dummy( filename .c_str() ); + if( dummy.fail() ) + return false; + + index number_of_columns = 0; + while( getline( dummy, cur_line ) ) { + cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1); + if( cur_line != "" && cur_line[ 0 ] != '#' ) + number_of_columns++; + + } + this->set_num_cols( number_of_columns ); + dummy.close(); + + std::ifstream input_stream( filename.c_str() ); + if( input_stream.fail() ) + return false; + + column temp_col; + index cur_col = -1; + while( getline( input_stream, cur_line ) ) { + cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1); + if( cur_line != "" && cur_line[ 0 ] != '#' ) { + cur_col++; + std::stringstream ss( cur_line ); + + int64_t temp_dim; + ss >> temp_dim; + this->set_dim( cur_col, (dimension) temp_dim ); + + int64_t temp_index; + temp_col.clear(); + while( ss.good() ) { + ss >> temp_index; + temp_col.push_back( (index)temp_index ); + } + std::sort( temp_col.begin(), temp_col.end() ); + this->set_col( cur_col, temp_col ); + } + } + + input_stream.close(); + return true; + } + + // Saves the boundary_matrix to given file in ascii format + // Format: each line represents a column, first number is dimension, other numbers are the content of the column + bool save_ascii( std::string filename ) { + std::ofstream output_stream( filename.c_str() ); + if( output_stream.fail() ) + return false; + + const index nr_columns = this->get_num_cols(); + column tempCol; + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + output_stream << (int64_t)this->get_dim( cur_col ); + this->get_col( cur_col, tempCol ); + for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size(); cur_row_idx++ ) + output_stream << " " << tempCol[ cur_row_idx ]; + output_stream << std::endl; + } + + output_stream.close(); + return true; + } + + // Loads boundary_matrix from given file + // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ... + bool load_binary( std::string filename ) { + std::ifstream input_stream( filename.c_str(), std::ios_base::binary | std::ios_base::in ); + if( input_stream.fail() ) + return false; + + int64_t nr_columns; + input_stream.read( (char*)&nr_columns, sizeof( int64_t ) ); + this->set_num_cols( (index)nr_columns ); + + column temp_col; + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + int64_t cur_dim; + input_stream.read( (char*)&cur_dim, sizeof( int64_t ) ); + this->set_dim( cur_col, (dimension) cur_dim ); + int64_t nr_rows; + input_stream.read( (char*)&nr_rows, sizeof( int64_t ) ); + temp_col.resize( (std::size_t)nr_rows ); + for( index idx = 0; idx < nr_rows; idx++ ) { + int64_t cur_row; + input_stream.read( (char*)&cur_row, sizeof( int64_t ) ); + temp_col[ idx ] = (index)cur_row; + } + this->set_col( cur_col, temp_col ); + } + + input_stream.close(); + return true; + } + + // Saves the boundary_matrix to given file in binary format + // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ... + bool save_binary( std::string filename ) { + std::ofstream output_stream( filename.c_str(), std::ios_base::binary | std::ios_base::out ); + if( output_stream.fail() ) + return false; + + const int64_t nr_columns = this->get_num_cols(); + output_stream.write( (char*)&nr_columns, sizeof( int64_t ) ); + column tempCol; + for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { + int64_t cur_dim = this->get_dim( cur_col ); + output_stream.write( (char*)&cur_dim, sizeof( int64_t ) ); + this->get_col( cur_col, tempCol ); + int64_t cur_nr_rows = tempCol.size(); + output_stream.write( (char*)&cur_nr_rows, sizeof( int64_t ) ); + for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size(); cur_row_idx++ ) { + int64_t cur_row = tempCol[ cur_row_idx ]; + output_stream.write( (char*)&cur_row, sizeof( int64_t ) ); + } + } + + output_stream.close(); + return true; + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h b/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h new file mode 100644 index 00000000..f5b04d5a --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h @@ -0,0 +1,69 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "persistence_pairs.h" +#include "boundary_matrix.h" +#include "helpers/dualize.h" +#include "algorithms/twist_reduction.h" + +namespace phat { + + template< typename ReductionAlgorithm, typename Representation > + void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { + ReductionAlgorithm reduce; + reduce( boundary_matrix ); + pairs.clear(); + for( index idx = 0; idx < boundary_matrix.get_num_cols(); idx++ ) { + if( !boundary_matrix.is_empty( idx ) ) { + index birth = boundary_matrix.get_max_index( idx ); + index death = idx; + pairs.append_pair( birth, death ); + } + } + } + + template< typename ReductionAlgorithm, typename Representation > + void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { + ReductionAlgorithm reduce; + const index nr_columns = boundary_matrix.get_num_cols(); + dualize( boundary_matrix ); + reduce( boundary_matrix ); + pairs.clear(); + for( index idx = 0; idx < nr_columns; idx++ ) { + if( !boundary_matrix.is_empty( idx ) ) { + index death = nr_columns - 1 - boundary_matrix.get_max_index( idx ); + index birth = nr_columns - 1 - idx; + pairs.append_pair( birth, death ); + } + } + } + + template< typename Representation > + void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { + phat::compute_persistence_pairs< twist_reduction >( pairs, boundary_matrix ); + } + + + template< typename Representation > + void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { + compute_persistence_pairs_dualized< twist_reduction >( pairs, boundary_matrix ); + } + +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h new file mode 100644 index 00000000..60caa05c --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h @@ -0,0 +1,63 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "misc.h" +#include "../boundary_matrix.h" + +namespace phat { + template< typename Representation > + void dualize( boundary_matrix< Representation >& boundary_matrix ) { + + std::vector< dimension > dual_dims; + std::vector< std::vector< index > > dual_matrix; + + index nr_of_columns = boundary_matrix.get_num_cols(); + dual_matrix.resize( nr_of_columns ); + dual_dims.resize( nr_of_columns ); + + std::vector< index > dual_sizes( nr_of_columns, 0 ); + + column temp_col; + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + boundary_matrix.get_col( cur_col, temp_col ); + for( index idx = 0; idx < (index)temp_col.size(); idx++) + dual_sizes[ nr_of_columns - 1 - temp_col[ idx ] ]++; + } + + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + dual_matrix[cur_col].reserve(dual_sizes[cur_col]); + } + + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { + boundary_matrix.get_col( cur_col, temp_col ); + for( index idx = 0; idx < (index)temp_col.size(); idx++) + dual_matrix[ nr_of_columns - 1 - temp_col[ idx ] ].push_back( nr_of_columns - 1 - cur_col ); + } + + const dimension max_dim = boundary_matrix.get_max_dim(); + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) + dual_dims[ nr_of_columns - 1 - cur_col ] = max_dim - boundary_matrix.get_dim( cur_col ); + + for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) + std::reverse( dual_matrix[ cur_col ].begin(), dual_matrix[ cur_col ].end() ); + + boundary_matrix.load_vector_vector( dual_matrix, dual_dims ); + } +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h new file mode 100644 index 00000000..abbf8d53 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h @@ -0,0 +1,74 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +// STL includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// VS2008 and below unfortunately do not support stdint.h +#if defined(_MSC_VER)&& _MSC_VER < 1600 + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; +#else + #include +#endif + +// basic types. index can be changed to int32_t to save memory on small instances +namespace phat { + typedef int64_t index; + typedef int8_t dimension; + typedef std::vector< index > column; +} + +// OpenMP (proxy) functions +#if defined _OPENMP + #include +#else + #define omp_get_thread_num() 0 + #define omp_get_max_threads() 1 + #define omp_get_num_threads() 1 + void omp_set_num_threads( int ) {}; + #include + #define omp_get_wtime() (float)clock() / (float)CLOCKS_PER_SEC +#endif + +#include "thread_local_storage.h" + + + diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h new file mode 100644 index 00000000..06e95c20 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h @@ -0,0 +1,52 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "misc.h" + +// should ideally be equal to the cache line size of the CPU +#define PHAT_TLS_SPACING_FACTOR 64 + +// ThreadLocalStorage with some spacing to avoid "false sharing" (see wikipedia) +template< typename T > +class thread_local_storage +{ +public: + + thread_local_storage() : per_thread_storage( omp_get_max_threads() * PHAT_TLS_SPACING_FACTOR ) {}; + + T& operator()() { + return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ]; + } + + const T& operator()() const { + return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ]; + } + + T& operator[]( int tid ) { + return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ]; + } + + const T& operator[]( int tid ) const { + return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ]; + } + +protected: + std::vector< T > per_thread_storage; +}; diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h b/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h new file mode 100644 index 00000000..f8006353 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h @@ -0,0 +1,151 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "helpers/misc.h" + +namespace phat { + class persistence_pairs { + + protected: + std::vector< std::pair< index, index > > pairs; + + public: + index get_num_pairs() const { + return (index)pairs.size(); + } + + void append_pair( index birth, index death ) { + pairs.push_back( std::make_pair( birth, death ) ); + } + + std::pair< index, index > get_pair( index idx ) const { + return pairs[ idx ]; + } + + void clear() { + pairs.clear(); + } + + void sort() { + std::sort( pairs.begin(), pairs.end() ); + } + + // Loads the persistence pairs from given file in asci format + // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ... + bool load_ascii( std::string filename ) { + std::ifstream input_stream( filename.c_str() ); + if( input_stream.fail() ) + return false; + + int64_t nr_pairs; + input_stream >> nr_pairs; + pairs.clear(); + for( index idx = 0; idx < nr_pairs; idx++ ) { + int64_t birth; + input_stream >> birth; + int64_t death; + input_stream >> death; + append_pair( (index)birth, (index)death ); + } + + input_stream.close(); + return true; + } + + // Saves the persistence pairs to given file in binary format + // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ... + bool save_ascii( std::string filename ) { + std::ofstream output_stream( filename.c_str() ); + if( output_stream.fail() ) + return false; + + this->sort(); + output_stream << get_num_pairs() << std::endl; + for( std::size_t idx = 0; idx < pairs.size(); idx++ ) { + output_stream << pairs[idx].first << " " << pairs[idx].second << std::endl; + } + + output_stream.close(); + return true; + } + + // Loads the persistence pairs from given file in binary format + // Format: nr_pairs % birth1 % death1 % birth2 % death2 ... + bool load_binary( std::string filename ) { + std::ifstream input_stream( filename.c_str(), std::ios_base::binary | std::ios_base::in ); + if( input_stream.fail() ) + return false; + + int64_t nr_pairs; + input_stream.read( (char*)&nr_pairs, sizeof( int64_t ) ); + for( index idx = 0; idx < nr_pairs; idx++ ) { + int64_t birth; + input_stream.read( (char*)&birth, sizeof( int64_t ) ); + int64_t death; + input_stream.read( (char*)&death, sizeof( int64_t ) ); + append_pair( (index)birth, (index)death ); + } + + input_stream.close(); + return true; + } + + // Saves the persistence pairs to given file in binary format + // Format: nr_pairs % birth1 % death1 % birth2 % death2 ... + bool save_binary( std::string filename ) { + std::ofstream output_stream( filename.c_str(), std::ios_base::binary | std::ios_base::out ); + if( output_stream.fail() ) + return false; + + this->sort(); + int64_t nr_pairs = get_num_pairs(); + output_stream.write( (char*)&nr_pairs, sizeof( int64_t ) ); + for( std::size_t idx = 0; idx < pairs.size(); idx++ ) { + int64_t birth = pairs[ idx ].first; + output_stream.write( (char*)&birth, sizeof( int64_t ) ); + int64_t death = pairs[ idx ].second; + output_stream.write( (char*)&death, sizeof( int64_t ) ); + } + + output_stream.close(); + return true; + } + + bool operator==( persistence_pairs& other_pairs ) { + this->sort(); + other_pairs.sort(); + if( pairs.size() != (std::size_t)other_pairs.get_num_pairs() ) + return false; + + for( index idx = 0; idx < (index)pairs.size(); idx++ ) + if( get_pair( idx ) != other_pairs.get_pair( idx ) ) + return false; + + return true; + } + + bool operator!=( persistence_pairs& other_pairs ) { + return !( *this == other_pairs ); + } + }; + + + +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h new file mode 100644 index 00000000..41104108 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h @@ -0,0 +1,158 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../representations/vector_vector.h" + +namespace phat { + + // Note: We could even make the rep generic in the underlying Const representation + // But I cannot imagine that anything else than vector> would + // make sense + template< typename PivotColumn > + class abstract_pivot_column : public vector_vector { + public: + + protected: + typedef vector_vector Base; + typedef PivotColumn pivot_column; + + // For parallization purposes, it could be more than one full column + mutable thread_local_storage< pivot_column > _pivot_columns; + mutable thread_local_storage< index > pos_of_pivot_columns; + + pivot_column& get_pivot_column() const { + return _pivot_columns(); + } + + bool is_represented_by_pivot_column( index idx ) const { + return pos_of_pivot_columns() == idx; + } + + void unset_pos_of_pivot_column() { + index idx = pos_of_pivot_columns(); + if( idx != -1 ) { + _pivot_columns().get_column_and_clear( this->matrix[ idx ] ); + } + pos_of_pivot_columns() = -1; + } + + void represent_by_pivot_column( index idx ) { + pos_of_pivot_columns() = idx; + get_pivot_column().add_column( matrix[ idx ] ); + } + + public: + + void _set_num_cols( index nr_of_columns ) { + #pragma omp parallel for + for( int tid = 0; tid < omp_get_num_threads(); tid++ ) { + _pivot_columns[ tid ].init( nr_of_columns ); + pos_of_pivot_columns[ tid ] = -1; + } + Base::_set_num_cols( nr_of_columns ); + } + // replaces(!) content of 'col' with boundary of given index + void _get_col( index idx, column& col ) const { + col.clear(); + if( is_represented_by_pivot_column( idx ) ) { + pivot_column& pivot_column = get_pivot_column(); + pivot_column.get_column_and_clear( col ); + pivot_column.add_column( col ); + } else { + Base::_get_col( idx, col ); + } + } + + // true iff boundary of given idx is empty + bool _is_empty( index idx ) const { + return is_represented_by_pivot_column( idx ) ? get_pivot_column().empty() : Base::_is_empty( idx ); + } + + // largest row index of given column idx (new name for lowestOne()) + index _get_max_index( index idx ) const { + if( is_represented_by_pivot_column( idx ) ) { + pivot_column& pivot_column = get_pivot_column(); + if( pivot_column.empty() ) { + return -1; + } else { + return pivot_column.max_index(); + } + } else { + return Base::_get_max_index( idx ); + } + } + + // adds column 'source' to column 'target' + void _add_to( index source, index target ) { + if( !is_represented_by_pivot_column( target ) ) { + unset_pos_of_pivot_column(); + represent_by_pivot_column( target ); + } + get_pivot_column().add_column( matrix[source] ); + } + + // clears given column + void _clear( index idx ) { + if( is_represented_by_pivot_column( idx ) ) { + column dummy; + get_pivot_column().get_column_and_clear(dummy); + } else { + Base::_clear( idx ); + } + } + + void _set_col( index idx, const column& col ) { + if( is_represented_by_pivot_column( idx ) ) { + column dummy; + pivot_column& pivot_column = get_pivot_column(); + pivot_column.get_column_and_clear( dummy ); + pivot_column.add_column( col ); + } else { + Base::_set_col( idx, col ); + } + } + + // removes the maximal index of a column + void _remove_max( index idx ) { + _toggle( idx, _get_max_index( idx ) ); + } + + //// toggles given index pair + void _toggle( index col_idx, index row_idx ) { + if( !is_represented_by_pivot_column( col_idx ) ) { + unset_pos_of_pivot_column(); + represent_by_pivot_column( col_idx ); + } + get_pivot_column().add_index( row_idx ); + } + + // syncronizes all data structures (essential for openmp stuff) + // has to be called before and after any multithreaded access! + void _sync() { + #pragma omp parallel for + for( int tid = 0; tid < omp_get_num_threads(); tid++ ) + unset_pos_of_pivot_column(); + } + + }; +} + + diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h new file mode 100644 index 00000000..34366d6a --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h @@ -0,0 +1,169 @@ +/* Copyright 2013 IST Austria + Contributed by: Hubert Wagner + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" +#include "../representations/abstract_pivot_column.h" + +namespace phat { + + // This is a bitset indexed with a 64-ary tree. Each node in the index + // has 64 bits; i-th bit says that the i-th subtree is non-empty. + // Supports practically O(1), inplace, zero-allocation: insert, remove, max_element + // and clear in O(number of ones in the bitset). + // 'add_index' is still the real bottleneck in practice. + class bit_tree_column + { + size_t offset; // data[i + offset] = ith block of the data-bitset + typedef uint64_t block_type; + std::vector< block_type > data; + + // this static is not a problem with OMP, it's initialized just after program starts + static const size_t debrujin_magic_table[64]; + + enum { block_size_in_bits = 64 }; + enum { block_shift = 6 }; + + // Some magic: http://graphics.stanford.edu/~seander/bithacks.html + // Gets the position of the rightmost bit of 'x'. 0 means the most significant bit. + // (-x)&x isolates the rightmost bit. + // The whole method is much faster than calling log2i, and very comparable to using ScanBitForward/Reverse intrinsic, + // which should be one CPU instruction, but is not portable. + size_t rightmost_pos(const block_type value) const + { + return 64 - 1 - debrujin_magic_table[((value & (-(int64_t)value))*0x07EDD5E59A4E28C2) >> 58]; + } + + public: + + void init(index num_cols) + { + int64_t n = 1; // in case of overflow + int64_t bottom_blocks_needed = (num_cols+block_size_in_bits-1)/block_size_in_bits; + int64_t upper_blocks = 1; + + // How many blocks/nodes of index needed to index the whole bitset? + while(n * block_size_in_bits < bottom_blocks_needed) + { + n *= block_size_in_bits; + upper_blocks += n; + } + + offset = upper_blocks; + data.resize(upper_blocks + bottom_blocks_needed, 0); + } + + index max_index() const + { + if (!data[0]) + return -1; + + const size_t size = data.size(); + size_t n = 0; + + while(true) + { + const block_type val = data[n]; + const size_t index = rightmost_pos(val); + const size_t newn = (n << block_shift) + index + 1; + + if (newn >= size) + { + const size_t bottom_index = n - offset; + return (bottom_index << block_shift) + index; + } + + n = newn; + } + + return -1; + } + + bool empty() const + { + return data[0] == 0; + } + + void add_index(const size_t entry) + { + const block_type ONE = 1; + const block_type block_modulo_mask = ((ONE << block_shift) - 1); + size_t index_in_level = entry >> block_shift; + size_t address = index_in_level + offset; + size_t index_in_block = entry & block_modulo_mask; + + block_type mask = (ONE << (block_size_in_bits - index_in_block - 1)); + + while(true) + { + data[address]^=mask; + + // First we check if we reached the root. + // Also, if anyone else was in this block, we don't need to update the path up. + if (!address || (data[address] & ~mask)) + return; + + index_in_block = index_in_level & block_modulo_mask; + index_in_level >>= block_shift; + --address; + address >>= block_shift; + mask = (ONE << (block_size_in_bits - index_in_block - 1)); + } + } + + void get_column_and_clear(column &out) + { + out.clear(); + while(true) + { + index mx = this->max_index(); + if (mx == -1) + break; + out.push_back(mx); + add_index(mx); + } + + std::reverse(out.begin(), out.end()); + } + + void add_column(const column &col) + { + for (size_t i = 0; i < col.size(); ++i) + { + add_index(col[i]); + } + } + + bool empty() { + return !data[0]; + } + }; + + const size_t bit_tree_column::debrujin_magic_table[64] = { + 63, 0, 58, 1, 59, 47, 53, 2, + 60, 39, 48, 27, 54, 33, 42, 3, + 61, 51, 37, 40, 49, 18, 28, 20, + 55, 30, 34, 11, 43, 14, 22, 4, + 62, 57, 46, 52, 38, 26, 32, 41, + 50, 36, 17, 19, 29, 10, 13, 21, + 56, 45, 25, 31, 35, 16, 9, 12, + 44, 24, 15, 8, 23, 7, 6, 5}; + + typedef abstract_pivot_column bit_tree_pivot_column; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h new file mode 100644 index 00000000..9e0c348d --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h @@ -0,0 +1,81 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include +#include + +namespace phat { + class full_column { + + protected: + std::priority_queue< index > m_history; + std::vector< char > m_isInHistory; + std::vector< char > m_data; + + public: + void init( const index total_size ) { + m_data.resize( total_size, false ); + m_isInHistory.resize( total_size, false ); + } + + void add_column( const column& col ) { + for( index idx = 0; idx < (index) col.size(); idx++ ) { + add_index( col[ idx ] ); + } + } + void add_index( const index idx ) { + if( !m_isInHistory[ idx ] ) { + m_history.push( idx ); + m_isInHistory[ idx ] = true; + } + + m_data[ idx ] = !m_data[ idx ]; + } + + index max_index() { + while( m_history.size() > 0 ) { + index topIndex = m_history.top(); + if( m_data[ topIndex ] ) { + return topIndex; + } else { + m_history.pop(); + m_isInHistory[ topIndex ] = false; + } + } + + return -1; + } + + void get_column_and_clear( column& col ) { + col.clear(); + while( !empty() ) { + col.push_back( max_index() ); + add_index( max_index() ); + } + std::reverse( col.begin(), col.end() ); + } + + bool empty() { + return (max_index() == -1); + } + }; + + typedef abstract_pivot_column< full_column > full_pivot_column; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h new file mode 100644 index 00000000..c851a2b5 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h @@ -0,0 +1,62 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include +#include + +namespace phat { + class sparse_column { + + protected: + std::set< index > m_data; + + public: + void init( const index total_size ) { + m_data.clear(); + } + + void add_column( const column& col ) { + for( index idx = 0; idx < (index) col.size(); idx++ ) + add_index( col[ idx ] ); + } + + void add_index( const index idx ) { + std::pair< std::set< index >::iterator, bool > result = m_data.insert( idx ); + if( result.second == false ) + m_data.erase( result.first ); + } + + index max_index() { + return m_data.empty() ? -1 : *m_data.rbegin(); + } + + void get_column_and_clear( column& col ) { + col.clear(); + col.assign( m_data.begin(), m_data.end() ); + m_data.clear(); + } + + bool empty() { + return m_data.empty(); + } + }; + + typedef abstract_pivot_column< sparse_column > sparse_pivot_column; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h new file mode 100644 index 00000000..38e3090c --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h @@ -0,0 +1,98 @@ +/* Copyright 2013 IST Austria + Contributed by: Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include + +namespace phat { + class vector_list { + + protected: + typedef std::list< index > internal_column; + std::vector< dimension > dims; + std::vector< internal_column > matrix; + + public: + // overall number of cells in boundary_matrix + index _get_num_cols() const { + return (index)matrix.size(); + } + void _set_num_cols( index nr_of_columns ) { + dims.resize( nr_of_columns ); + matrix.resize( nr_of_columns ); + } + + // dimension of given index + dimension _get_dim( index idx ) const { + return dims[ idx ]; + } + void _set_dim( index idx, dimension dim ) { + dims[ idx ] = dim; + } + + // replaces(!) content of 'col' with boundary of given index + void _get_col( index idx, column& col ) const { + col.clear(); + col.reserve( matrix[idx].size() ); + std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) ); + } + + void _set_col( index idx, const column& col ) { + matrix[ idx ].clear(); + matrix[ idx ].resize( col.size() ); + std::copy (col.begin(), col.end(), matrix[ idx ].begin() ); + } + + // true iff boundary of given idx is empty + bool _is_empty( index idx ) const { + return matrix[ idx ].empty(); + } + + // largest row index of given column idx (new name for lowestOne()) + index _get_max_index( index idx ) const { + return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin(); + } + + // removes the maximal index of a column + void _remove_max( index idx ) { + internal_column::iterator it = matrix[ idx ].end(); + it--; + matrix[ idx ].erase( it ); + } + + // clears given column + void _clear( index idx ) { + matrix[ idx ].clear(); + } + + // syncronizes all data structures (essential for openmp stuff) + void _sync() {} + + // adds column 'source' to column 'target' + void _add_to( index source, index target ) { + internal_column& source_col = matrix[ source ]; + internal_column& target_col = matrix[ target ]; + internal_column temp_col; + target_col.swap( temp_col ); + std::set_symmetric_difference( temp_col.begin(), temp_col.end(), + source_col.begin(), source_col.end(), + std::back_inserter( target_col ) ); + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h new file mode 100644 index 00000000..dadf1b34 --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h @@ -0,0 +1,100 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include + +namespace phat { + class vector_set { + + protected: + typedef std::set< index > internal_column; + std::vector< dimension > dims; + std::vector< internal_column > matrix; + + public: + // overall number of cells in boundary_matrix + index _get_num_cols() const { + return (index)matrix.size(); + } + void _set_num_cols( index nr_of_columns ) { + dims.resize( nr_of_columns ); + matrix.resize( nr_of_columns ); + } + + // dimension of given index + dimension _get_dim( index idx ) const { + return dims[ idx ]; + } + void _set_dim( index idx, dimension dim ) { + dims[ idx ] = dim; + } + + // replaces(!) content of 'col' with boundary of given index + void _get_col( index idx, column& col ) const { + col.clear(); + col.reserve( matrix[idx].size() ); + std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) ); + } + void _set_col( index idx, const column& col ) { + matrix[ idx ].clear(); + matrix[ idx ].insert( col.begin(), col.end() ); + } + + // true iff boundary of given idx is empty + bool _is_empty( index idx ) const { + return matrix[ idx ].empty(); + } + + // largest row index of given column idx (new name for lowestOne()) + index _get_max_index( index idx ) const { + return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin(); + } + + // removes the maximal index of a column + void _remove_max( index idx ) { + internal_column::iterator it = matrix[ idx ].end(); + it--; + matrix[ idx ].erase( it ); + } + + // clears given column + void _clear( index idx ) { + matrix[ idx ].clear(); + } + + // syncronizes all data structures (essential for openmp stuff) + void _sync() {} + + // adds column 'source' to column 'target' + void _add_to( index source, index target ) { + for( internal_column::iterator it = matrix[ source ].begin(); it != matrix[ source ].end(); it++ ) + _toggle( target, *it ); + } + + //// toggles given index pair + void _toggle( index col_idx, index row_idx ) { + internal_column& col = matrix[ col_idx ]; + std::pair< internal_column::iterator, bool > result = col.insert( row_idx ); + if( !result.second ) { + col.erase( result.first ); + } + } + }; +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h new file mode 100644 index 00000000..efe8de4d --- /dev/null +++ b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h @@ -0,0 +1,93 @@ +/* Copyright 2013 IST Austria + Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus + + This file is part of PHAT. + + PHAT is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + PHAT 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PHAT. If not, see . */ + +#pragma once + +#include "../helpers/misc.h" + +namespace phat { + class vector_vector { + + protected: + std::vector< dimension > dims; + std::vector< column > matrix; + + thread_local_storage< column > temp_column_buffer; + + public: + // overall number of cells in boundary_matrix + index _get_num_cols() const { + return (index)matrix.size(); + } + void _set_num_cols( index nr_of_columns ) { + dims.resize( nr_of_columns ); + matrix.resize( nr_of_columns ); + } + + // dimension of given index + dimension _get_dim( index idx ) const { + return dims[ idx ]; + } + void _set_dim( index idx, dimension dim ) { + dims[ idx ] = dim; + } + + // replaces(!) content of 'col' with boundary of given index + void _get_col( index idx, column& col ) const { + col = matrix[ idx ]; + } + void _set_col( index idx, const column& col ) { + matrix[ idx ] = col; + } + + // true iff boundary of given idx is empty + bool _is_empty( index idx ) const { + return matrix[ idx ].empty(); + } + + // largest row index of given column idx (new name for lowestOne()) + index _get_max_index( index idx ) const { + return matrix[ idx ].empty() ? -1 : matrix[ idx ].back(); + } + + // removes the maximal index of a column + void _remove_max( index idx ) { + matrix[ idx ].pop_back(); + } + + // clears given column + void _clear( index idx ) { + matrix[ idx ].clear(); + } + + // syncronizes all data structures (essential for openmp stuff) + void _sync() {} + + // adds column 'source' to column 'target' + void _add_to( index source, index target ) { + column& source_col = matrix[ source ]; + column& target_col = matrix[ target ]; + column& temp_col = temp_column_buffer(); + temp_col.clear(); + std::set_symmetric_difference( target_col.begin(), target_col.end(), + source_col.begin(), source_col.end(), + std::back_inserter( temp_col ) ); + target_col.swap( temp_col ); + } + }; +} diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 4235761f..968483a3 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -310,7 +310,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { dimensions.push_back(3); Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + for (size_t i = 0; i != increasing.size(); ++i) { std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { BOOST_CHECK(boundaries[i][j] == bd[j]); @@ -423,7 +423,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { coboundaryElements.push_back(41); coboundaryElements.push_back(47); size_t number = 0; - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + for (size_t i = 0; i != increasing.size(); ++i) { std::vector< size_t > bd = increasing.get_coboundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { BOOST_CHECK(coboundaryElements[number] == bd[j]); @@ -502,7 +502,7 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { dim.push_back(1); dim.push_back(0); - for (size_t i = 0; i != increasing.size_of_bitmap(); ++i) { + for (size_t i = 0; i != increasing.size(); ++i) { BOOST_CHECK(increasing.get_dimension_of_a_cell(i) == dim[i]); } } @@ -726,7 +726,7 @@ BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) { boundaries.push_back( boundary14 ); boundaries.push_back( boundary15 ); - for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) { + for (size_t i = 0; i != cmplx.size(); ++i) { std::vector< size_t > bd = cmplx.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { BOOST_CHECK(boundaries[i][j] == bd[j]); @@ -826,7 +826,7 @@ BOOST_AUTO_TEST_CASE(coboudary_operator_2d_bitmap_with_periodic_bcond) { coboundaries.push_back( coboundary14 ); coboundaries.push_back( coboundary15 ); - for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) { + for (size_t i = 0; i != cmplx.size(); ++i) { std::vector< size_t > cbd = cmplx.get_coboundary_of_a_cell(i); for (size_t j = 0; j != cbd.size(); ++j) { BOOST_CHECK(coboundaries[i][j] == cbd[j]); @@ -879,7 +879,7 @@ BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) { filtration.push_back(3);//15 - for (size_t i = 0; i != cmplx.size_of_bitmap(); ++i) + for (size_t i = 0; i != cmplx.size(); ++i) { BOOST_CHECK( filtration[i] == cmplx.get_cell_data(i) ); } -- cgit v1.2.3 From 904e931e2938ed3a5b526711b073c957b938ae63 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 9 Feb 2016 14:04:23 +0000 Subject: Doxygen fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1009 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 490dcfd0ca24df97b9bf7735fa167ef844d49b71 --- .../doc/Gudhi_Cubical_Complex_doc.h | 11 +- .../include/gudhi/Bitmap_cubical_complex.h | 117 +++++++++++---------- 2 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index c06678a1..00b39f01 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -36,7 +36,7 @@ namespace Cubical_complex * @{ * -*Cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. +*Bitmap_cubical_complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. * * An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerate, while the second one is \a degenerate interval. A boundary of a elementary *interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerate elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An elementary cube \f$ C \f$ is a @@ -93,7 +93,7 @@ namespace Cubical_complex 5 \endverbatim -\section Periodic boundary conditions +\section PeriodicBoundaryConditions Periodic boundary conditions Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times I_n \f$ be a box that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary conditions in the direction i, means that the left and the right side of a complex \f$ \mathcal{K} \f$ are considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed in all directions, then complex @@ -106,8 +106,8 @@ in this direction have to be multiplied by -1. For instance: -3 3 1 -2 -3 +4 +6 8 20 4 @@ -118,6 +118,9 @@ in this direction have to be multiplied by -1. For instance: Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. + * \section BitmapExamples Examples + * End user programs are available in example/Bitmap_cubical_complex folder. + */ /** @} */ // end defgroup cubical_complex diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 82ea8672..b599a0d9 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -23,7 +23,7 @@ #pragma once #include -#include "Bitmap_cubical_complex_base.h" +#include "Bitmap_cubical_complex_base.h" #include "Bitmap_cubical_complex_periodic_boundary_conditions_base.h" @@ -35,10 +35,15 @@ namespace Cubical_complex { //global variable, was used just for debugging. -const bool globalDbg = false; - +const bool globalDbg = false; + template class is_before_in_filtration; +/** + *@class Bitmap_cubical_complex + *@brief Cubical complex represented as a bitmap. + *@ingroup cubical_complex + */ template class Bitmap_cubical_complex : public T { @@ -47,8 +52,8 @@ public: //Typedefs and typenames //*********************************************// typedef size_t Simplex_key; - typedef typename T::filtration_type Filtration_value; - typedef Simplex_key Simplex_handle; + typedef typename T::filtration_type Filtration_value; + typedef Simplex_key Simplex_handle; //*********************************************// @@ -65,7 +70,7 @@ public: **/ Bitmap_cubical_complex( const char* perseus_style_file ): T(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) - { + { //clock_t begin = clock(); if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) @@ -75,7 +80,7 @@ public: //we initialize this only once, in each constructor, when the bitmap is constructed. //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. - this->initialize_simplex_associated_to_key(); + this->initialize_simplex_associated_to_key(); //cerr << "Time of running Bitmap_cubical_complex( const char* perseus_style_file ) constructor : " << double(clock() - begin) / CLOCKS_PER_SEC << endl; } @@ -97,12 +102,12 @@ public: //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. this->initialize_simplex_associated_to_key(); - } - + } + /** * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells * in the following directions and vector of element of a type T::filtration_type - * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. + * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. **/ Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ): @@ -117,7 +122,7 @@ public: //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. this->initialize_simplex_associated_to_key(); - } + } //*********************************************// @@ -135,10 +140,10 @@ public: * Returns a Simplex_handle to a cube that do not exist in this complex. **/ static Simplex_handle null_simplex() - { + { if ( globalDbg ){cerr << "Simplex_handle null_simplex()\n";} return std::numeric_limits::max(); - } + } /** @@ -184,10 +189,10 @@ public: **/ Simplex_key key(Simplex_handle sh)const { - if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) - { - return this->key_associated_to_simplex[sh]; + if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} + if ( sh != std::numeric_limits::max() ) + { + return this->key_associated_to_simplex[sh]; } return this->null_key(); } @@ -197,10 +202,10 @@ public: **/ Simplex_handle simplex(Simplex_key key) { - if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} - if ( key != std::numeric_limits::max() ) - { - return this->simplex_associated_to_key[ key ]; + if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} + if ( key != std::numeric_limits::max() ) + { + return this->simplex_associated_to_key[ key ]; } return null_simplex(); } @@ -210,8 +215,8 @@ public: **/ void assign_key(Simplex_handle sh, Simplex_key key) { - if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} - if ( key == std::numeric_limits::max() ) return; + if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} + if ( key == std::numeric_limits::max() ) return; this->key_associated_to_simplex[sh] = key; this->simplex_associated_to_key[key] = sh; } @@ -231,10 +236,10 @@ public: /** * Boundary_simplex_range class provides ranges for boundary iterators. - **/ - typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; - typedef typename std::vector< Simplex_handle > Boundary_simplex_range; - + **/ + typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; + typedef typename std::vector< Simplex_handle > Boundary_simplex_range; + /** @@ -301,8 +306,8 @@ public: { //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. - public: - typedef Filtration_simplex_iterator const_iterator; + public: + typedef Filtration_simplex_iterator const_iterator; typedef Filtration_simplex_iterator iterator; Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; Filtration_simplex_iterator begin() @@ -328,19 +333,19 @@ public: /** * boundary_simplex_range creates an object of a Boundary_simplex_range class * that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) - { - /* - std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); - Boundary_simplex_range result( bdry.size() ); - for ( size_t i = 0 ; i != bdry.size() ; ++i ) - { - result[i] = this->simplex_associated_to_key[ bdry[i] ]; - } - return result; - */ - return this->get_boundary_of_a_cell(sh); + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) + { + /* + std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); + Boundary_simplex_range result( bdry.size() ); + for ( size_t i = 0 ; i != bdry.size() ; ++i ) + { + result[i] = this->simplex_associated_to_key[ bdry[i] ]; + } + return result; + */ + return this->get_boundary_of_a_cell(sh); } /** @@ -463,8 +468,8 @@ public: { //Range over the simplices of the complex in the order of the filtration. //.begin() and .end() return type Filtration_simplex_iterator. - public: - typedef Skeleton_simplex_iterator const_iterator; + public: + typedef Skeleton_simplex_iterator const_iterator; typedef Skeleton_simplex_iterator iterator; Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; Skeleton_simplex_iterator begin() @@ -500,28 +505,28 @@ protected: std::vector< size_t > key_associated_to_simplex; std::vector< size_t > simplex_associated_to_key; };//Bitmap_cubical_complex - + template void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { if ( globalDbg ) { cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; - } - this->simplex_associated_to_key = std::vector( this->data.size() ); + } + this->simplex_associated_to_key = std::vector( this->data.size() ); std::iota (std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); std::sort( simplex_associated_to_key.begin() , simplex_associated_to_key.end() , - is_before_in_filtration(this) ); - - //we still need to deal here with a key_associated_to_simplex: - for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) - { - this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; + is_before_in_filtration(this) ); + + //we still need to deal here with a key_associated_to_simplex: + for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) + { + this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; } } - - + + template class is_before_in_filtration { @@ -560,4 +565,4 @@ protected: } -} +} -- cgit v1.2.3 From 81d5f63b5107dd8229fd8b8576982d22acb9a57e Mon Sep 17 00:00:00 2001 From: pdlotko Date: Tue, 9 Feb 2016 14:35:03 +0000 Subject: Adding documentation to the bitmap cubical complex with periodic boundary conditions class. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1010 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e1d9516f57be5e824203037b74998ed897741261 --- .../include/gudhi/Bitmap_cubical_complex.h | 7 +- ...cal_complex_periodic_boundary_conditions_base.h | 666 +++++++++++---------- 2 files changed, 361 insertions(+), 312 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index b599a0d9..2ec7594d 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -37,7 +37,12 @@ namespace Cubical_complex //global variable, was used just for debugging. const bool globalDbg = false; -template class is_before_in_filtration; +template class is_before_in_filtration; + +/** +* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex__base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into +* Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex__base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. +**/ /** *@class Bitmap_cubical_complex diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 38c218dc..f0fd785f 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -1,311 +1,355 @@ -#pragma once -#include -#include "Bitmap_cubical_complex_base.h" - -using namespace std; - -namespace Gudhi -{ - -namespace Cubical_complex -{ - -//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures -//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the -//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base - -template -class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base -{ -public: - //constructors that take an extra parameter: - Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); - - //overwritten methods co compute boundary and coboundary - virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; - std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; - //inline unsigned get_dimension_of_a_cell( size_t cell )const; - -protected: - std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; - void set_up_containers( const std::vector& sizes ) - { - - unsigned multiplier = 1; - for ( size_t i = 0 ; i != sizes.size() ; ++i ) - { - this->sizes.push_back(sizes[i]); - this->multipliers.push_back(multiplier); - - if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) - { - multiplier *= 2*sizes[i]; - } - else - { - multiplier *= 2*sizes[i]+1; - } - } - //std::reverse( this->sizes.begin() , this->sizes.end() ); - this->data = std::vector(multiplier,std::numeric_limits::max()); - this->total_number_of_cells = multiplier; - } - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ); - void construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ); -}; - -template -void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( dimensions ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) - { - *it = topDimensionalCells[i]; - ++i; - } - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) -{ - - //for Perseus style files: - bool dbg = false; - ifstream inFiltration; - inFiltration.open( perseus_style_file ); - unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); - - std::vector sizes; - sizes.reserve( dimensionOfData ); - for ( size_t i = 0 ; i != dimensionOfData ; ++i ) - { - int size_in_this_dimension; - inFiltration >> size_in_this_dimension; - if ( size_in_this_dimension < 0 ) - { - this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; - } - sizes.push_back( abs(size_in_this_dimension) ); - } - this->set_up_containers( sizes ); - - typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_begin(); - - while ( !inFiltration.eof() ) - { - double filtrationLevel; - inFiltration >> filtrationLevel; - if ( inFiltration.eof() )break; - - if ( dbg ) - { - cerr << "Cell of an index : " - << it.compute_index_in_bitmap() - << " and dimension: " - << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) - << " get the value : " << filtrationLevel << endl; - } - *it = filtrationLevel; - ++it; - } - inFiltration.close(); - this->impose_lower_star_filtration(); - -/* - char* filename = (char*)perseus_style_file; - //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; - ifstream file( filename , ios::binary | ios::ate ); - unsigned realSizeOfFile = file.tellg(); - file.close(); - realSizeOfFile = realSizeOfFile/sizeof(T); - - unsigned w, h, d; - - w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); - - T* slice = new T[w*h*d]; - if (slice == NULL) - { - cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; - exit(EXIT_FAILURE); - } - - FILE* fp; - if ((fp=fopen( filename, "rb" )) == NULL ) - { - cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; - exit(1); - } - - clock_t read_begin = clock(); - fread( slice,4,w*h*d,fp ); - fclose(fp); - cerr << "Time of reading the file : " << double(clock() - read_begin) / CLOCKS_PER_SEC << endl; - - - clock_t begin_creation_bitap = clock(); - std::vector data(slice,slice+w*h*d); - delete[] slice; - std::vector< unsigned > sizes; - sizes.push_back(w); - sizes.push_back(w); - sizes.push_back(w); - - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->set_up_containers( sizes ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) - { - *it = data[i]; - ++i; - } - this->impose_lower_star_filtration(); - cerr << "Time of creation of a bitmap : " << double(clock() - begin_creation_bitap ) / CLOCKS_PER_SEC << endl; -*/ -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector sizes ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells ) -{ - std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - - - - - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( std::vector dimensions , std::vector topDimensionalCells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - -//***********************Methods************************// - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const -{ - bool dbg = false; - if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} - - std::vector< size_t > boundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. - - if ( position%2 == 1 ) - { - //if there are no periodic boundary conditions in this direction, we do not have to do anything. - if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //cerr << "A\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. - if ( position != 2*this->sizes[ i-1 ]-1 ) - { - //cerr << "B\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //cerr << "C\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} - } - } - } - cell1 = cell1%this->multipliers[i-1]; - } - return boundary_elements; -} - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const -{ - std::vector counter = this->compute_counter_for_given_cell( cell ); - std::vector< size_t > coboundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - //if the cell has zero length in this direction, then it will have cbd in this direction. - if ( position%2 == 0 ) - { - if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //no periodic boundary conditions in this direction - if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - } - if ( (counter[i-1] != 2*this->sizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) - { - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - } - else - { - //we want to have periodic boundary conditions in this direction - if ( counter[i-1] != 0 ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - else - { - //in this case counter[i-1] == 0. - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); - } - } - } - - cell1 = cell1%this->multipliers[i-1]; - } - return coboundary_elements; -} - - - -}//Cubical_complex -}//namespace Gudhi +/* 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): Pawel Dlotko + * + * Copyright (C) 2015 INRIA Sophia-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 . + */ + +#pragma once +#include +#include "Bitmap_cubical_complex_base.h" + +using namespace std; + +namespace Gudhi +{ + +namespace Cubical_complex +{ + +//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures +//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the +//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base + + +/** +* This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. +* The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. +*/ +template +class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base +{ +public: + //constructors that take an extra parameter: + /** + * Default constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; + + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of booleans. If at i-th position of this vector there is true value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction i. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the name of Perseus style file as an input. Please consult the documentation about the specification of the file. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of top dimensional cells (ordered lexicographically) and (3) vector of booleans. If at i-th position of this vector there is true value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction i. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); + + //overwritten methods co compute boundary and coboundary + /** + * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; + /** + * A version of a function that return coboundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + virtual std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; +protected: + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; + void set_up_containers( const std::vector& sizes ) + { + + unsigned multiplier = 1; + for ( size_t i = 0 ; i != sizes.size() ; ++i ) + { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + + if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) + { + multiplier *= 2*sizes[i]; + } + else + { + multiplier *= 2*sizes[i]+1; + } + } + //std::reverse( this->sizes.begin() , this->sizes.end() ); + this->data = std::vector(multiplier,std::numeric_limits::max()); + this->total_number_of_cells = multiplier; + } + Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes ); + Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells ); + void construct_complex_based_on_top_dimensional_cells( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); +}; + +template +void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers( dimensions ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = topDimensionalCells[i]; + ++i; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed(directions_in_which_periodic_b_cond_are_to_be_imposed); + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) +{ + + //for Perseus style files: + bool dbg = false; + ifstream inFiltration; + inFiltration.open( perseus_style_file ); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); + + std::vector sizes; + sizes.reserve( dimensionOfData ); + for ( size_t i = 0 ; i != dimensionOfData ; ++i ) + { + int size_in_this_dimension; + inFiltration >> size_in_this_dimension; + if ( size_in_this_dimension < 0 ) + { + this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; + } + sizes.push_back( abs(size_in_this_dimension) ); + } + this->set_up_containers( sizes ); + + typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_begin(); + + while ( !inFiltration.eof() ) + { + double filtrationLevel; + inFiltration >> filtrationLevel; + if ( inFiltration.eof() )break; + + if ( dbg ) + { + cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << endl; + } + *it = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); + +/* + char* filename = (char*)perseus_style_file; + //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; + ifstream file( filename , ios::binary | ios::ate ); + unsigned realSizeOfFile = file.tellg(); + file.close(); + realSizeOfFile = realSizeOfFile/sizeof(T); + + unsigned w, h, d; + + w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); + + T* slice = new T[w*h*d]; + if (slice == NULL) + { + cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; + exit(EXIT_FAILURE); + } + + FILE* fp; + if ((fp=fopen( filename, "rb" )) == NULL ) + { + cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; + exit(1); + } + + clock_t read_begin = clock(); + fread( slice,4,w*h*d,fp ); + fclose(fp); + cerr << "Time of reading the file : " << double(clock() - read_begin) / CLOCKS_PER_SEC << endl; + + + clock_t begin_creation_bitap = clock(); + std::vector data(slice,slice+w*h*d); + delete[] slice; + std::vector< unsigned > sizes; + sizes.push_back(w); + sizes.push_back(w); + sizes.push_back(w); + + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); + this->set_up_containers( sizes ); + + size_t i = 0; + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + { + *it = data[i]; + ++i; + } + this->impose_lower_star_filtration(); + cerr << "Time of creation of a bitmap : " << double(clock() - begin_creation_bitap ) / CLOCKS_PER_SEC << endl; + */ +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes ) +{ + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); + this->set_up_containers( sizes ); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells ) +{ + std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + + + + + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) +{ + this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); +} + +//***********************Methods************************// + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const +{ + bool dbg = false; + if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} + + std::vector< size_t > boundary_elements; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/this->multipliers[i-1]; + //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. + + if ( position%2 == 1 ) + { + //if there are no periodic boundary conditions in this direction, we do not have to do anything. + if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //cerr << "A\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. + if ( position != 2*this->sizes[ i-1 ]-1 ) + { + //cerr << "B\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} + } + else + { + //cerr << "C\n"; + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); + if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} + } + } + } + cell1 = cell1%this->multipliers[i-1]; + } + return boundary_elements; +} + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const +{ + std::vector counter = this->compute_counter_for_given_cell( cell ); + std::vector< size_t > coboundary_elements; + size_t cell1 = cell; + for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) + { + unsigned position = cell1/this->multipliers[i-1]; + //if the cell has zero length in this direction, then it will have cbd in this direction. + if ( position%2 == 0 ) + { + if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) + { + //no periodic boundary conditions in this direction + if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + } + if ( (counter[i-1] != 2*this->sizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) + { + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + } + else + { + //we want to have periodic boundary conditions in this direction + if ( counter[i-1] != 0 ) + { + coboundary_elements.push_back( cell - this->multipliers[i-1] ); + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + } + else + { + //in this case counter[i-1] == 0. + coboundary_elements.push_back( cell + this->multipliers[i-1] ); + coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); + } + } + } + + cell1 = cell1%this->multipliers[i-1]; + } + return coboundary_elements; +} + + + +}//Cubical_complex +}//namespace Gudhi -- cgit v1.2.3 From 1ed10d89ae07c069cf408de2e178962f23723c8b Mon Sep 17 00:00:00 2001 From: pdlotko Date: Sat, 13 Feb 2016 12:21:41 +0000 Subject: removing phat relaed compontns. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1021 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d0c9c23ca3f3a5b2131179949ba80659b13f7777 --- .../example/Compute_persistence_with_phat.cpp | 60 ---- .../include/gudhi/Compute_persistence_with_phat.h | 242 --------------- .../gudhi/phat/algorithms/chunk_reduction.h | 240 --------------- .../include/gudhi/phat/algorithms/row_reduction.h | 55 ---- .../gudhi/phat/algorithms/standard_reduction.h | 45 --- .../gudhi/phat/algorithms/twist_reduction.h | 50 --- .../include/gudhi/phat/boundary_matrix.h | 336 --------------------- .../include/gudhi/phat/compute_persistence_pairs.h | 69 ----- .../include/gudhi/phat/helpers/dualize.h | 63 ---- .../include/gudhi/phat/helpers/misc.h | 74 ----- .../gudhi/phat/helpers/thread_local_storage.h | 52 ---- .../include/gudhi/phat/persistence_pairs.h | 151 --------- .../phat/representations/abstract_pivot_column.h | 158 ---------- .../phat/representations/bit_tree_pivot_column.h | 169 ----------- .../gudhi/phat/representations/full_pivot_column.h | 81 ----- .../phat/representations/sparse_pivot_column.h | 62 ---- .../gudhi/phat/representations/vector_list.h | 98 ------ .../gudhi/phat/representations/vector_set.h | 100 ------ .../gudhi/phat/representations/vector_vector.h | 93 ------ 19 files changed, 2198 deletions(-) delete mode 100644 src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h delete mode 100644 src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h diff --git a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp b/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp deleted file mode 100644 index f552a094..00000000 --- a/src/Bitmap_cubical_complex/example/Compute_persistence_with_phat.cpp +++ /dev/null @@ -1,60 +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): Pawel Dlotko - * - * 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 -#include -#include -#include -#include - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; - -//standard stuff -#include -#include -#include - -using namespace std; - - -int main( int argc , char** argv ) -{ - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); - cerr << "Cubical complex created \n"; - - - Compute_persistence_with_phat< Bitmap_cubical_complex< Bitmap_cubical_complex_base > , double > phat(&b); - phat::persistence_pairs pairs = phat.compute_persistence_pairs_standard_reduction(); - std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > persistence = phat.get_the_intervals( pairs ); - writeBettiNumbersAndPersistenceIntervalsToFile( "phat_persistence" , persistence ); - - return 0; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h b/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h deleted file mode 100644 index 9f4ada45..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/Compute_persistence_with_phat.h +++ /dev/null @@ -1,242 +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): Pawel Dlotko - * - * Copyright (C) 2015 INRIA Sophia-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 . - */ - -#pragma once - - -#include "phat/compute_persistence_pairs.h" -#include "phat/representations/vector_vector.h" -#include "phat/algorithms/standard_reduction.h" -#include "phat/algorithms/chunk_reduction.h" -#include "phat/algorithms/row_reduction.h" -#include "phat/algorithms/twist_reduction.h" - - -namespace Gudhi -{ - - -//the only aim of this class is to have a ability to compute persistence with phat. -template -void writeBettiNumbersAndPersistenceIntervalsToFile( char* prefix , std::pair< std::vector > , std::vector< std::vector< std::pair > > > resutsFromPhat ) -{ - std::ostringstream filenameStr; - filenameStr << prefix << "_bettiNumbers"; - std::string str = filenameStr.str(); - const char* filename = str.c_str(); - ofstream out; - out.open( filename ); - for ( size_t dim = 0 ; dim != resutsFromPhat.first.size() ; ++dim ) - { - out << "Dimension : " << dim << endl; - for ( size_t i = 0 ; i != resutsFromPhat.first[dim].size() ; ++i ) - { - out << resutsFromPhat.first[dim][i] << endl; - } - out << endl; - } - out.close(); - - - cerr << "Write persistence to file \n"; - for ( size_t dim = 0 ; dim != resutsFromPhat.second.size() ; ++dim ) - { - cerr << "resutsFromPhat.second[dim].size() : " << resutsFromPhat.second[dim].size() << endl; - if ( resutsFromPhat.second[dim].size() == 0 )continue; - std::ostringstream filenameStr; - filenameStr << prefix << "_persistence_" << dim; - std::string str = filenameStr.str(); - const char* filename = str.c_str(); - ofstream out1; - out1.open( filename ); - for ( size_t i = 0 ; i != resutsFromPhat.second[dim].size() ; ++i ) - { - out1 << resutsFromPhat.second[dim][i].first << " " << resutsFromPhat.second[dim][i].second << endl; - } - out1.close(); - } -}//writeBettiNumbersAndPersistenceIntervalsToFile - - -template -class Compute_persistence_with_phat -{ -public: - Compute_persistence_with_phat( T* data_structure_ ); - std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > get_the_intervals( phat::persistence_pairs pairs ); - - phat::persistence_pairs compute_persistence_pairs_dualized_chunk_reduction(); - phat::persistence_pairs compute_persistence_pairs_twist_reduction(); - phat::persistence_pairs compute_persistence_pairs_standard_reduction(); - //phat::persistence_pairs compute_persistence_pairs_spectral_sequence_reduction(); -private: - void print_bd_matrix(); - phat::boundary_matrix< phat::vector_vector > boundary_matrix; - T* data_structure; -}; - -template -void Compute_persistence_with_phat::print_bd_matrix() -{ - std::cout << "The boundary matrix has " << this->boundary_matrix.get_num_cols() << " columns: " << std::endl; - for( phat::index col_idx = 0; col_idx < this->boundary_matrix.get_num_cols(); col_idx++ ) { - std::cout << "Colum " << col_idx << " represents a cell of dimension " << (int)this->boundary_matrix.get_dim( col_idx ) << ". "; - if( !this->boundary_matrix.is_empty( col_idx ) ) { - std::vector< phat::index > temp_col; - this->boundary_matrix.get_col( col_idx, temp_col ); - std::cout << "Its boundary consists of the cells"; - for( phat::index idx = 0; idx < (phat::index)temp_col.size(); idx++ ) - std::cout << " " << temp_col[ idx ]; - } - std::cout << std::endl; - } -} - -template -phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_dualized_chunk_reduction() -{ - phat::persistence_pairs pairs; - phat::compute_persistence_pairs_dualized< phat::chunk_reduction >( pairs, this->boundary_matrix ); - return pairs; -} - -template -phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_twist_reduction() -{ - phat::persistence_pairs pairs; - phat::compute_persistence_pairs< phat::twist_reduction >( pairs, this->boundary_matrix ); - return pairs; -} - -template -phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_standard_reduction() -{ - phat::persistence_pairs pairs; - phat::compute_persistence_pairs< phat::standard_reduction >( pairs, this->boundary_matrix ); - return pairs; -} - -//template -//phat::persistence_pairs Compute_persistence_with_phat::compute_persistence_pairs_spectral_sequence_reduction() -//{ -// phat::persistence_pairs pairs; -// phat::compute_persistence_pairs< phat::spectral_sequence_reduction >( pairs, this->boundary_matrix ); -// return pairs; -//} - -template -Compute_persistence_with_phat::Compute_persistence_with_phat( T* data_structure_ ):data_structure( data_structure_ ) -{ - bool dbg = false; - this->boundary_matrix.set_num_cols( this->data_structure->num_simplices() ); - - //setting up the dimensions of cells: - for ( size_t i = 0 ; i != this->data_structure->num_simplices() ; ++i ) - { - this->boundary_matrix.set_dim( i, this->data_structure->dimension( this->data_structure->simplex(i) ) ); - } - - - //now it is time to set up the boundary matrix: - typename T::Filtration_simplex_range range = this->data_structure->filtration_simplex_range(); - std::vector< phat::index > temp_col; - for ( typename T::Filtration_simplex_iterator it = range.begin() ; it != range.end() ; ++it ) - { - typename T::Boundary_simplex_range boundary_range = this->data_structure->boundary_simplex_range( *it ); - for ( typename T::Boundary_simplex_iterator bd = boundary_range.begin() ; bd != boundary_range.end() ; ++bd ) - { - temp_col.push_back( this->data_structure->key( *bd ) ); - } - //we do not know if the boundary elements are sorted according to filtration, that is why I am enforcing it here: - this->boundary_matrix.set_col( this->data_structure->key( *it ) , temp_col ); - temp_col.clear(); - } -} - -template -std::pair< std::vector< std::vector > , std::vector< std::vector< std::pair > > > Compute_persistence_with_phat::get_the_intervals( phat::persistence_pairs pairs ) -{ - bool dbg = false; - //in order to find the birth times of the infinite homology classes, we need to know which elements are not paired. To search for them, we will use this vector: - std::vector isTheElementPaired( this->data_structure->num_simplices() , false ); - - //now it is time to recover the finite persistence pairs and the Betti numbers: - std::vector< std::vector< std::pair > > finitePersistencePairs( this->data_structure->dimension() ); - for( phat::index idx = 0; idx < pairs.get_num_pairs(); idx++ ) - { - typename T::Simplex_key positionOfBeginOfInterval = pairs.get_pair( idx ).first; - typename T::Simplex_key positionOfEndOfInterval = pairs.get_pair( idx ).second; - - typename T::Simplex_handle first_simplex = this->data_structure->simplex(positionOfBeginOfInterval); - typename T::Simplex_handle second_simplex = this->data_structure->simplex(positionOfEndOfInterval); - - typename T::Filtration_value valueFirst = this->data_structure->filtration( first_simplex ); - typename T::Filtration_value valueSecond = this->data_structure->filtration( second_simplex ); - - if ( valueFirst > valueSecond ){std::swap( valueFirst , valueSecond );} - - unsigned dimFirst = this->data_structure->dimension(first_simplex); - unsigned dimSecond = this->data_structure->dimension(second_simplex); - unsigned dim = std::min( dimFirst , dimSecond ); - - - //we are ignoring trivial barcodes - if ( valueFirst != valueSecond ) - { - finitePersistencePairs[ dim ].push_back( std::make_pair(valueFirst , valueSecond) ); - if ( dbg ){cerr << "Adding barcode : " << valueFirst << "," << valueSecond << endl;} - } - - //isTheElementPaired[ positionOfBeginOfIntervalInBitmap ] = true; - //isTheElementPaired[ positionOfEndOfIntervalInBitmap ] = true; - isTheElementPaired[ pairs.get_pair( idx ).first ] = true; - isTheElementPaired[ pairs.get_pair( idx ).second ] = true; - } - - - std::vector< std::vector > birthTimesOfInfinitePersistnceClasses(this->data_structure->dimension()+1 ); - for ( size_t i = 0 ; i != this->data_structure->dimension()+1 ; ++i ) - { - std::vector v; - birthTimesOfInfinitePersistnceClasses[i] = v; - } - for ( size_t i = 0 ; i != isTheElementPaired.size() ; ++i ) - { - if ( isTheElementPaired[i] == false ) - { - //i-th element is not paired, therefore it gives an infinite class - typename T::Simplex_handle simplex = this->data_structure->simplex(i); - birthTimesOfInfinitePersistnceClasses[ this->data_structure->dimension( simplex ) ].push_back( this->data_structure->filtration(simplex) ); - } - } - - //sorting finite persistence pairs: - for ( size_t dim = 0 ; dim != finitePersistencePairs.size() ; ++dim ) - { - std::sort( finitePersistencePairs[dim].begin() , finitePersistencePairs[dim].end() ); - } - return std::make_pair( birthTimesOfInfinitePersistnceClasses , finitePersistencePairs ); -}//Compute_persistence_with_phat - - - -}//namespace Gudhi diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h deleted file mode 100644 index 352392a8..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/chunk_reduction.h +++ /dev/null @@ -1,240 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../boundary_matrix.h" - -namespace phat { - class chunk_reduction { - public: - enum column_type { GLOBAL - , LOCAL_POSITIVE - , LOCAL_NEGATIVE }; - - public: - template< typename Representation > - void operator() ( boundary_matrix< Representation >& boundary_matrix ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - const dimension max_dim = boundary_matrix.get_max_dim(); - - std::vector< index > lowest_one_lookup( nr_columns, -1 ); - std::vector < column_type > column_type( nr_columns, GLOBAL ); - std::vector< char > is_active( nr_columns, false ); - - std::vector chunk_boundaries; - _get_chunks( boundary_matrix, chunk_boundaries ); - - // Phase 1: Reduce chunks locally -- 1st pass - #pragma omp parallel for schedule( guided, 1 ) - for( index chunk_id = 0; chunk_id < (index) chunk_boundaries.size() - 2; chunk_id += 2 ) - _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, max_dim, - chunk_boundaries[chunk_id], chunk_boundaries[chunk_id+2] - 1 ); - boundary_matrix.sync(); - - // Phase 1: Reduce chunks locally -- 2nd pass - #pragma omp parallel for schedule( guided, 1 ) - for( index chunk_id = 1; chunk_id < (index) chunk_boundaries.size() - 2; chunk_id += 2 ) - _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, max_dim, - chunk_boundaries[chunk_id], chunk_boundaries[chunk_id+2] - 1 ); - boundary_matrix.sync(); - - // get global columns - std::vector< index > global_columns; - for( index cur_col_idx = 0; cur_col_idx < nr_columns; cur_col_idx++ ) - if( column_type[ cur_col_idx ] == GLOBAL ) - global_columns.push_back( cur_col_idx ); - - // get active columns - #pragma omp parallel for - for( index idx = 0; idx < (index)global_columns.size(); idx++ ) - is_active[ global_columns[ idx ] ] = true; - _get_active_columns( boundary_matrix, lowest_one_lookup, column_type, global_columns, is_active ); - - // Phase 2+3: Simplify columns and reduce them - for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) { - // Phase 2: Simplify columns - std::vector< index > temp_col; - #pragma omp parallel for schedule( guided, 1 ), private( temp_col ) - for( index idx = 0; idx < (index)global_columns.size(); idx++ ) - if( boundary_matrix.get_dim( global_columns[ idx ] ) == cur_dim ) - _global_column_simplification( global_columns[ idx ], boundary_matrix, lowest_one_lookup, column_type, is_active, temp_col ); - boundary_matrix.sync(); - - // Phase 3: Reduce columns - for( index idx = 0; idx < (index)global_columns.size(); idx++ ) { - index cur_col = global_columns[ idx ]; - if( boundary_matrix.get_dim( cur_col ) == cur_dim && column_type[ cur_col ] == GLOBAL ) { - index lowest_one = boundary_matrix.get_max_index( cur_col ); - while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { - boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); - lowest_one = boundary_matrix.get_max_index( cur_col ); - } - if( lowest_one != -1 ) { - lowest_one_lookup[ lowest_one ] = cur_col; - boundary_matrix.clear( lowest_one ); - } - } - } - } - - boundary_matrix.sync(); - } - - protected: - template< typename Representation > - void _get_chunks( const boundary_matrix< Representation >& boundary_matrix - , std::vector< index >& chunk_boundaries) - { - chunk_boundaries.clear(); - std::vector temp_chunk_boundaries; - const index nr_columns = boundary_matrix.get_num_cols(); - - // size of chuks = sqrt(N) - const index chunk_size = (index) sqrt( (float)nr_columns ); - - // size of chunks = N / num_threads - //const index chunk_size = nr_columns / omp_get_max_threads(); - - for ( index cur_col = 0; cur_col < nr_columns; cur_col++ ) - if( cur_col % chunk_size == 0 ) - temp_chunk_boundaries.push_back( cur_col ); - temp_chunk_boundaries.push_back( nr_columns ); - - // subdivide chunks for interleaved 2 pass appraoch - for( index chunk_id = 0; chunk_id < (index) temp_chunk_boundaries.size(); chunk_id ++ ) { - chunk_boundaries.push_back( temp_chunk_boundaries[ chunk_id ] ); - if( chunk_id < (index) temp_chunk_boundaries.size() - 1 ) { - index midPoint = ( temp_chunk_boundaries[ chunk_id ] + temp_chunk_boundaries[ chunk_id + 1 ] ) / 2; - chunk_boundaries.push_back( midPoint ); - } - } - } - - template< typename Representation > - void _local_chunk_reduction( boundary_matrix< Representation >& boundary_matrix - , std::vector& lowest_one_lookup - , std::vector< column_type >& column_type - , const dimension max_dim - , const index chunk_begin - , const index chunk_end ) { - for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) { - for( index cur_col = chunk_begin; cur_col <= chunk_end; cur_col++ ) { - if( column_type[ cur_col ] == GLOBAL && boundary_matrix.get_dim( cur_col ) == cur_dim ) { - index lowest_one = boundary_matrix.get_max_index( cur_col ); - while( lowest_one != -1 && lowest_one >= chunk_begin && lowest_one_lookup[ lowest_one ] != -1 ) { - boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); - lowest_one = boundary_matrix.get_max_index( cur_col ); - } - if( lowest_one >= chunk_begin ) { - lowest_one_lookup[ lowest_one ] = cur_col; - column_type[ cur_col ] = LOCAL_NEGATIVE; - column_type[ lowest_one ] = LOCAL_POSITIVE; - boundary_matrix.clear( lowest_one ); - } - } - } - } - } - - template< typename Representation > - void _get_active_columns( const boundary_matrix< Representation >& boundary_matrix - , const std::vector< index >& lowest_one_lookup - , const std::vector< column_type >& column_type - , const std::vector< index >& global_columns - , std::vector< char >& is_active ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - std::vector< char > finished( nr_columns, false ); - - std::vector< std::pair < index, index > > stack; - std::vector< index > cur_col_values; - #pragma omp parallel for schedule( guided, 1 ), private( stack, cur_col_values ) - for( index idx = 0; idx < (index)global_columns.size(); idx++ ) { - bool pop_next = false; - index start_col = global_columns[ idx ]; - stack.push_back( std::pair< index, index >( start_col, -1 ) ); - while( !stack.empty() ) { - index cur_col = stack.back().first; - index prev_col = stack.back().second; - if( pop_next ) { - stack.pop_back(); - pop_next = false; - if( prev_col != -1 ) { - if( is_active[ cur_col ] ) { - is_active[ prev_col ] = true; - } - if( prev_col == stack.back().first ) { - finished[ prev_col ] = true; - pop_next = true; - } - } - } else { - pop_next = true; - boundary_matrix.get_col( cur_col, cur_col_values ); - for( index idx = 0; idx < (index) cur_col_values.size(); idx++ ) { - index cur_row = cur_col_values[ idx ]; - if( ( column_type[ cur_row ] == GLOBAL ) ) { - is_active[ cur_col ] = true; - } else if( column_type[ cur_row ] == LOCAL_POSITIVE ) { - index next_col = lowest_one_lookup[ cur_row ]; - if( next_col != cur_col && !finished[ cur_col ] ) { - stack.push_back( std::make_pair( next_col, cur_col ) ); - pop_next = false; - } - } - } - } - } - } - } - - template< typename Representation > - void _global_column_simplification( const index col_idx - , boundary_matrix< Representation >& boundary_matrix - , const std::vector< index >& lowest_one_lookup - , const std::vector< column_type >& column_type - , const std::vector< char >& is_active - , std::vector< index >& temp_col ) - { - temp_col.clear(); - while( !boundary_matrix.is_empty( col_idx ) ) { - index cur_row = boundary_matrix.get_max_index( col_idx ); - switch( column_type[ cur_row ] ) { - case GLOBAL: - temp_col.push_back( cur_row ); - boundary_matrix.remove_max( col_idx ); - break; - case LOCAL_NEGATIVE: - boundary_matrix.remove_max( col_idx ); - break; - case LOCAL_POSITIVE: - if( is_active[ lowest_one_lookup[ cur_row ] ] ) - boundary_matrix.add_to( lowest_one_lookup[ cur_row ], col_idx ); - else - boundary_matrix.remove_max( col_idx ); - break; - } - } - std::reverse( temp_col.begin(), temp_col.end() ); - boundary_matrix.set_col( col_idx, temp_col ); - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h deleted file mode 100644 index 2047cafd..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/row_reduction.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../boundary_matrix.h" - -namespace phat { - class row_reduction { - public: - template< typename Representation > - void operator() ( boundary_matrix< Representation >& boundary_matrix ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - std::vector< std::vector< index > > lowest_one_lookup( nr_columns ); - - for( index cur_col = nr_columns - 1; cur_col >= 0; cur_col-- ) { - if( !boundary_matrix.is_empty( cur_col ) ) - lowest_one_lookup[ boundary_matrix.get_max_index( cur_col ) ].push_back( cur_col ); - - if( !lowest_one_lookup[ cur_col ].empty() ) { - boundary_matrix.clear( cur_col ); - std::vector< index >& cols_with_cur_lowest = lowest_one_lookup[ cur_col ]; - index source = *min_element( cols_with_cur_lowest.begin(), cols_with_cur_lowest.end() ); - for( index idx = 0; idx < (index)cols_with_cur_lowest.size(); idx++ ) { - index target = cols_with_cur_lowest[ idx ]; - if( target != source && !boundary_matrix.is_empty( target ) ) { - boundary_matrix.add_to( source, target ); - if( !boundary_matrix.is_empty( target ) ) { - index lowest_one_of_target = boundary_matrix.get_max_index( target ); - lowest_one_lookup[ lowest_one_of_target ].push_back( target ); - } - } - } - } - } - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h deleted file mode 100644 index b2c91a85..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/standard_reduction.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../boundary_matrix.h" - -namespace phat { - class standard_reduction { - public: - template< typename Representation > - void operator() ( boundary_matrix< Representation >& boundary_matrix ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - std::vector< index > lowest_one_lookup( nr_columns, -1 ); - - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - index lowest_one = boundary_matrix.get_max_index( cur_col ); - while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { - boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); - lowest_one = boundary_matrix.get_max_index( cur_col ); - } - if( lowest_one != -1 ) { - lowest_one_lookup[ lowest_one ] = cur_col; - } - } - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h b/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h deleted file mode 100644 index 1bdd8de2..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/algorithms/twist_reduction.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../boundary_matrix.h" - -namespace phat { - class twist_reduction { - public: - template< typename Representation > - void operator () ( boundary_matrix< Representation >& boundary_matrix ) { - - const index nr_columns = boundary_matrix.get_num_cols(); - std::vector< index > lowest_one_lookup( nr_columns, -1 ); - - for( index cur_dim = boundary_matrix.get_max_dim(); cur_dim >= 1 ; cur_dim-- ) { - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - if( boundary_matrix.get_dim( cur_col ) == cur_dim ) { - index lowest_one = boundary_matrix.get_max_index( cur_col ); - while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) { - boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col ); - lowest_one = boundary_matrix.get_max_index( cur_col ); - } - if( lowest_one != -1 ) { - lowest_one_lookup[ lowest_one ] = cur_col; - boundary_matrix.clear( lowest_one ); - } - } - } - } - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h b/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h deleted file mode 100644 index 941537da..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/boundary_matrix.h +++ /dev/null @@ -1,336 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "helpers/misc.h" -#include "representations/bit_tree_pivot_column.h" - -// interface class for the main data structure -- implementations of the interface can be found in ./representations -namespace phat { - template< class Representation = bit_tree_pivot_column > - class boundary_matrix - { - - protected: - Representation rep; - - // interface functions -- actual implementation and complexity depends on chosen @Representation template - public: - // get overall number of columns in boundary_matrix - index get_num_cols() const { return rep._get_num_cols(); } - - // set overall number of columns in boundary_matrix - void set_num_cols( index nr_of_columns ) { rep._set_num_cols( nr_of_columns ); } - - // get dimension of given index - dimension get_dim( index idx ) const { return rep._get_dim( idx ); } - - // set dimension of given index - void set_dim( index idx, dimension dim ) { rep._set_dim( idx, dim ); } - - // replaces content of @col with boundary of given index - void get_col( index idx, column& col ) const { rep._get_col( idx, col ); } - - // set column @idx to the values contained in @col - void set_col( index idx, const column& col ) { rep._set_col( idx, col ); } - - // true iff boundary of given column is empty - bool is_empty( index idx ) const { return rep._is_empty( idx ); } - - // largest index of given column (new name for lowestOne()) - index get_max_index( index idx ) const { return rep._get_max_index( idx ); } - - // removes maximal index from given column - void remove_max( index idx ) { rep._remove_max( idx ); } - - // adds column @source to column @target' - void add_to( index source, index target ) { rep._add_to( source, target ); } - - // clears given column - void clear( index idx ) { rep._clear( idx ); } - - // syncronizes all internal data structures -- has to be called before and after any multithreaded access! - void sync() { rep._sync(); } - - // info functions -- independent of chosen 'Representation' - public: - // maximal dimension - dimension get_max_dim() const { - dimension cur_max_dim = 0; - for( index idx = 0; idx < get_num_cols(); idx++ ) - cur_max_dim = get_dim( idx ) > cur_max_dim ? get_dim( idx ) : cur_max_dim; - return cur_max_dim; - } - - // number of nonzero rows for given column @idx - index get_num_rows( index idx ) const { - column cur_col; - get_col( idx, cur_col ); - return cur_col.size(); - } - - // maximal number of nonzero rows of all columns - index get_max_col_entries() const { - index max_col_entries = -1; - const index nr_of_columns = get_num_cols(); - for( index idx = 0; idx < nr_of_columns; idx++ ) - max_col_entries = get_num_rows( idx ) > max_col_entries ? get_num_rows( idx ) : max_col_entries; - return max_col_entries; - } - - // maximal number of nonzero cols of all rows - index get_max_row_entries() const { - size_t max_row_entries = 0; - const index nr_of_columns = get_num_cols(); - std::vector< std::vector< index > > transposed_matrix( nr_of_columns ); - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - get_col( cur_col, temp_col ); - for( index idx = 0; idx < (index)temp_col.size(); idx++) - transposed_matrix[ temp_col[ idx ] ].push_back( cur_col ); - } - for( index idx = 0; idx < nr_of_columns; idx++ ) - max_row_entries = transposed_matrix[ idx ].size() > max_row_entries ? transposed_matrix[ idx ].size() : max_row_entries; - return max_row_entries; - } - - // overall number of entries in the matrix - index get_num_entries() const { - index number_of_nonzero_entries = 0; - const index nr_of_columns = get_num_cols(); - for( index idx = 0; idx < nr_of_columns; idx++ ) - number_of_nonzero_entries += get_num_rows( idx ); - return number_of_nonzero_entries; - } - - // operators / constructors - public: - boundary_matrix() {}; - - template< class OtherRepresentation > - boundary_matrix( const boundary_matrix< OtherRepresentation >& other ) { - *this = other; - } - - template< typename OtherRepresentation > - bool operator==( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const { - const index number_of_columns = this->get_num_cols(); - - if( number_of_columns != other_boundary_matrix.get_num_cols() ) - return false; - - column temp_col; - column other_temp_col; - for( index idx = 0; idx < number_of_columns; idx++ ) { - this->get_col( idx, temp_col ); - other_boundary_matrix.get_col( idx, other_temp_col ); - if( temp_col != other_temp_col || this->get_dim( idx ) != other_boundary_matrix.get_dim( idx ) ) - return false; - } - return true; - } - - template< typename OtherRepresentation > - bool operator!=( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const { - return !( *this == other_boundary_matrix ); - } - - template< typename OtherRepresentation > - boundary_matrix< Representation >& operator=( const boundary_matrix< OtherRepresentation >& other ) - { - const index nr_of_columns = other.get_num_cols(); - this->set_num_cols( nr_of_columns ); - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - this->set_dim( cur_col, other.get_dim( cur_col ) ); - other.get_col( cur_col, temp_col ); - this->set_col( cur_col, temp_col ); - } - - // by convention, always return *this - return *this; - } - - // I/O -- independent of chosen 'Representation' - public: - - // initializes boundary_matrix from (vector, vector) pair -- untested - template< typename index_type, typename dimemsion_type > - void load_vector_vector( const std::vector< std::vector< index_type > >& input_matrix, const std::vector< dimemsion_type >& input_dims ) { - const index nr_of_columns = (index)input_matrix.size(); - this->set_num_cols( nr_of_columns ); - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - this->set_dim( cur_col, (dimension)input_dims[ cur_col ] ); - - index num_rows = input_matrix[ cur_col ].size(); - temp_col.resize( num_rows ); - for( index cur_row = 0; cur_row < num_rows; cur_row++ ) - temp_col[ cur_row ] = (index)input_matrix[ cur_col ][ cur_row ]; - this->set_col( cur_col, temp_col ); - } - } - - template< typename index_type, typename dimemsion_type > - void save_vector_vector( std::vector< std::vector< index_type > >& output_matrix, std::vector< dimemsion_type >& output_dims ) { - const index nr_of_columns = get_num_cols(); - output_matrix.resize( nr_of_columns ); - output_dims.resize( nr_of_columns ); - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - output_dims[ cur_col ] = (dimemsion_type)get_dim( cur_col ); - get_col( cur_col, temp_col ); - index num_rows = temp_col.size(); - output_matrix[ cur_col ].clear(); - output_matrix[ cur_col ].resize( num_rows ); - for( index cur_row = 0; cur_row < num_rows; cur_row++ ) - output_matrix[ cur_col ][ cur_row ] = (index_type)temp_col[ cur_row ]; - } - } - - // Loads the boundary_matrix from given file in ascii format - // Format: each line represents a column, first number is dimension, other numbers are the content of the column. - // Ignores empty lines and lines starting with a '#'. - bool load_ascii( std::string filename ) { - // first count number of columns: - std::string cur_line; - std::ifstream dummy( filename .c_str() ); - if( dummy.fail() ) - return false; - - index number_of_columns = 0; - while( getline( dummy, cur_line ) ) { - cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1); - if( cur_line != "" && cur_line[ 0 ] != '#' ) - number_of_columns++; - - } - this->set_num_cols( number_of_columns ); - dummy.close(); - - std::ifstream input_stream( filename.c_str() ); - if( input_stream.fail() ) - return false; - - column temp_col; - index cur_col = -1; - while( getline( input_stream, cur_line ) ) { - cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1); - if( cur_line != "" && cur_line[ 0 ] != '#' ) { - cur_col++; - std::stringstream ss( cur_line ); - - int64_t temp_dim; - ss >> temp_dim; - this->set_dim( cur_col, (dimension) temp_dim ); - - int64_t temp_index; - temp_col.clear(); - while( ss.good() ) { - ss >> temp_index; - temp_col.push_back( (index)temp_index ); - } - std::sort( temp_col.begin(), temp_col.end() ); - this->set_col( cur_col, temp_col ); - } - } - - input_stream.close(); - return true; - } - - // Saves the boundary_matrix to given file in ascii format - // Format: each line represents a column, first number is dimension, other numbers are the content of the column - bool save_ascii( std::string filename ) { - std::ofstream output_stream( filename.c_str() ); - if( output_stream.fail() ) - return false; - - const index nr_columns = this->get_num_cols(); - column tempCol; - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - output_stream << (int64_t)this->get_dim( cur_col ); - this->get_col( cur_col, tempCol ); - for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size(); cur_row_idx++ ) - output_stream << " " << tempCol[ cur_row_idx ]; - output_stream << std::endl; - } - - output_stream.close(); - return true; - } - - // Loads boundary_matrix from given file - // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ... - bool load_binary( std::string filename ) { - std::ifstream input_stream( filename.c_str(), std::ios_base::binary | std::ios_base::in ); - if( input_stream.fail() ) - return false; - - int64_t nr_columns; - input_stream.read( (char*)&nr_columns, sizeof( int64_t ) ); - this->set_num_cols( (index)nr_columns ); - - column temp_col; - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - int64_t cur_dim; - input_stream.read( (char*)&cur_dim, sizeof( int64_t ) ); - this->set_dim( cur_col, (dimension) cur_dim ); - int64_t nr_rows; - input_stream.read( (char*)&nr_rows, sizeof( int64_t ) ); - temp_col.resize( (std::size_t)nr_rows ); - for( index idx = 0; idx < nr_rows; idx++ ) { - int64_t cur_row; - input_stream.read( (char*)&cur_row, sizeof( int64_t ) ); - temp_col[ idx ] = (index)cur_row; - } - this->set_col( cur_col, temp_col ); - } - - input_stream.close(); - return true; - } - - // Saves the boundary_matrix to given file in binary format - // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ... - bool save_binary( std::string filename ) { - std::ofstream output_stream( filename.c_str(), std::ios_base::binary | std::ios_base::out ); - if( output_stream.fail() ) - return false; - - const int64_t nr_columns = this->get_num_cols(); - output_stream.write( (char*)&nr_columns, sizeof( int64_t ) ); - column tempCol; - for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) { - int64_t cur_dim = this->get_dim( cur_col ); - output_stream.write( (char*)&cur_dim, sizeof( int64_t ) ); - this->get_col( cur_col, tempCol ); - int64_t cur_nr_rows = tempCol.size(); - output_stream.write( (char*)&cur_nr_rows, sizeof( int64_t ) ); - for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size(); cur_row_idx++ ) { - int64_t cur_row = tempCol[ cur_row_idx ]; - output_stream.write( (char*)&cur_row, sizeof( int64_t ) ); - } - } - - output_stream.close(); - return true; - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h b/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h deleted file mode 100644 index f5b04d5a..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/compute_persistence_pairs.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "persistence_pairs.h" -#include "boundary_matrix.h" -#include "helpers/dualize.h" -#include "algorithms/twist_reduction.h" - -namespace phat { - - template< typename ReductionAlgorithm, typename Representation > - void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { - ReductionAlgorithm reduce; - reduce( boundary_matrix ); - pairs.clear(); - for( index idx = 0; idx < boundary_matrix.get_num_cols(); idx++ ) { - if( !boundary_matrix.is_empty( idx ) ) { - index birth = boundary_matrix.get_max_index( idx ); - index death = idx; - pairs.append_pair( birth, death ); - } - } - } - - template< typename ReductionAlgorithm, typename Representation > - void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { - ReductionAlgorithm reduce; - const index nr_columns = boundary_matrix.get_num_cols(); - dualize( boundary_matrix ); - reduce( boundary_matrix ); - pairs.clear(); - for( index idx = 0; idx < nr_columns; idx++ ) { - if( !boundary_matrix.is_empty( idx ) ) { - index death = nr_columns - 1 - boundary_matrix.get_max_index( idx ); - index birth = nr_columns - 1 - idx; - pairs.append_pair( birth, death ); - } - } - } - - template< typename Representation > - void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { - phat::compute_persistence_pairs< twist_reduction >( pairs, boundary_matrix ); - } - - - template< typename Representation > - void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) { - compute_persistence_pairs_dualized< twist_reduction >( pairs, boundary_matrix ); - } - -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h deleted file mode 100644 index 60caa05c..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/dualize.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "misc.h" -#include "../boundary_matrix.h" - -namespace phat { - template< typename Representation > - void dualize( boundary_matrix< Representation >& boundary_matrix ) { - - std::vector< dimension > dual_dims; - std::vector< std::vector< index > > dual_matrix; - - index nr_of_columns = boundary_matrix.get_num_cols(); - dual_matrix.resize( nr_of_columns ); - dual_dims.resize( nr_of_columns ); - - std::vector< index > dual_sizes( nr_of_columns, 0 ); - - column temp_col; - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - boundary_matrix.get_col( cur_col, temp_col ); - for( index idx = 0; idx < (index)temp_col.size(); idx++) - dual_sizes[ nr_of_columns - 1 - temp_col[ idx ] ]++; - } - - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - dual_matrix[cur_col].reserve(dual_sizes[cur_col]); - } - - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) { - boundary_matrix.get_col( cur_col, temp_col ); - for( index idx = 0; idx < (index)temp_col.size(); idx++) - dual_matrix[ nr_of_columns - 1 - temp_col[ idx ] ].push_back( nr_of_columns - 1 - cur_col ); - } - - const dimension max_dim = boundary_matrix.get_max_dim(); - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) - dual_dims[ nr_of_columns - 1 - cur_col ] = max_dim - boundary_matrix.get_dim( cur_col ); - - for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) - std::reverse( dual_matrix[ cur_col ].begin(), dual_matrix[ cur_col ].end() ); - - boundary_matrix.load_vector_vector( dual_matrix, dual_dims ); - } -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h deleted file mode 100644 index abbf8d53..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/misc.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -// STL includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// VS2008 and below unfortunately do not support stdint.h -#if defined(_MSC_VER)&& _MSC_VER < 1600 - typedef __int8 int8_t; - typedef unsigned __int8 uint8_t; - typedef __int16 int16_t; - typedef unsigned __int16 uint16_t; - typedef __int32 int32_t; - typedef unsigned __int32 uint32_t; - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -#else - #include -#endif - -// basic types. index can be changed to int32_t to save memory on small instances -namespace phat { - typedef int64_t index; - typedef int8_t dimension; - typedef std::vector< index > column; -} - -// OpenMP (proxy) functions -#if defined _OPENMP - #include -#else - #define omp_get_thread_num() 0 - #define omp_get_max_threads() 1 - #define omp_get_num_threads() 1 - void omp_set_num_threads( int ) {}; - #include - #define omp_get_wtime() (float)clock() / (float)CLOCKS_PER_SEC -#endif - -#include "thread_local_storage.h" - - - diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h b/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h deleted file mode 100644 index 06e95c20..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/helpers/thread_local_storage.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "misc.h" - -// should ideally be equal to the cache line size of the CPU -#define PHAT_TLS_SPACING_FACTOR 64 - -// ThreadLocalStorage with some spacing to avoid "false sharing" (see wikipedia) -template< typename T > -class thread_local_storage -{ -public: - - thread_local_storage() : per_thread_storage( omp_get_max_threads() * PHAT_TLS_SPACING_FACTOR ) {}; - - T& operator()() { - return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ]; - } - - const T& operator()() const { - return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ]; - } - - T& operator[]( int tid ) { - return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ]; - } - - const T& operator[]( int tid ) const { - return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ]; - } - -protected: - std::vector< T > per_thread_storage; -}; diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h b/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h deleted file mode 100644 index f8006353..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/persistence_pairs.h +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "helpers/misc.h" - -namespace phat { - class persistence_pairs { - - protected: - std::vector< std::pair< index, index > > pairs; - - public: - index get_num_pairs() const { - return (index)pairs.size(); - } - - void append_pair( index birth, index death ) { - pairs.push_back( std::make_pair( birth, death ) ); - } - - std::pair< index, index > get_pair( index idx ) const { - return pairs[ idx ]; - } - - void clear() { - pairs.clear(); - } - - void sort() { - std::sort( pairs.begin(), pairs.end() ); - } - - // Loads the persistence pairs from given file in asci format - // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ... - bool load_ascii( std::string filename ) { - std::ifstream input_stream( filename.c_str() ); - if( input_stream.fail() ) - return false; - - int64_t nr_pairs; - input_stream >> nr_pairs; - pairs.clear(); - for( index idx = 0; idx < nr_pairs; idx++ ) { - int64_t birth; - input_stream >> birth; - int64_t death; - input_stream >> death; - append_pair( (index)birth, (index)death ); - } - - input_stream.close(); - return true; - } - - // Saves the persistence pairs to given file in binary format - // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ... - bool save_ascii( std::string filename ) { - std::ofstream output_stream( filename.c_str() ); - if( output_stream.fail() ) - return false; - - this->sort(); - output_stream << get_num_pairs() << std::endl; - for( std::size_t idx = 0; idx < pairs.size(); idx++ ) { - output_stream << pairs[idx].first << " " << pairs[idx].second << std::endl; - } - - output_stream.close(); - return true; - } - - // Loads the persistence pairs from given file in binary format - // Format: nr_pairs % birth1 % death1 % birth2 % death2 ... - bool load_binary( std::string filename ) { - std::ifstream input_stream( filename.c_str(), std::ios_base::binary | std::ios_base::in ); - if( input_stream.fail() ) - return false; - - int64_t nr_pairs; - input_stream.read( (char*)&nr_pairs, sizeof( int64_t ) ); - for( index idx = 0; idx < nr_pairs; idx++ ) { - int64_t birth; - input_stream.read( (char*)&birth, sizeof( int64_t ) ); - int64_t death; - input_stream.read( (char*)&death, sizeof( int64_t ) ); - append_pair( (index)birth, (index)death ); - } - - input_stream.close(); - return true; - } - - // Saves the persistence pairs to given file in binary format - // Format: nr_pairs % birth1 % death1 % birth2 % death2 ... - bool save_binary( std::string filename ) { - std::ofstream output_stream( filename.c_str(), std::ios_base::binary | std::ios_base::out ); - if( output_stream.fail() ) - return false; - - this->sort(); - int64_t nr_pairs = get_num_pairs(); - output_stream.write( (char*)&nr_pairs, sizeof( int64_t ) ); - for( std::size_t idx = 0; idx < pairs.size(); idx++ ) { - int64_t birth = pairs[ idx ].first; - output_stream.write( (char*)&birth, sizeof( int64_t ) ); - int64_t death = pairs[ idx ].second; - output_stream.write( (char*)&death, sizeof( int64_t ) ); - } - - output_stream.close(); - return true; - } - - bool operator==( persistence_pairs& other_pairs ) { - this->sort(); - other_pairs.sort(); - if( pairs.size() != (std::size_t)other_pairs.get_num_pairs() ) - return false; - - for( index idx = 0; idx < (index)pairs.size(); idx++ ) - if( get_pair( idx ) != other_pairs.get_pair( idx ) ) - return false; - - return true; - } - - bool operator!=( persistence_pairs& other_pairs ) { - return !( *this == other_pairs ); - } - }; - - - -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h deleted file mode 100644 index 41104108..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/abstract_pivot_column.h +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../representations/vector_vector.h" - -namespace phat { - - // Note: We could even make the rep generic in the underlying Const representation - // But I cannot imagine that anything else than vector> would - // make sense - template< typename PivotColumn > - class abstract_pivot_column : public vector_vector { - public: - - protected: - typedef vector_vector Base; - typedef PivotColumn pivot_column; - - // For parallization purposes, it could be more than one full column - mutable thread_local_storage< pivot_column > _pivot_columns; - mutable thread_local_storage< index > pos_of_pivot_columns; - - pivot_column& get_pivot_column() const { - return _pivot_columns(); - } - - bool is_represented_by_pivot_column( index idx ) const { - return pos_of_pivot_columns() == idx; - } - - void unset_pos_of_pivot_column() { - index idx = pos_of_pivot_columns(); - if( idx != -1 ) { - _pivot_columns().get_column_and_clear( this->matrix[ idx ] ); - } - pos_of_pivot_columns() = -1; - } - - void represent_by_pivot_column( index idx ) { - pos_of_pivot_columns() = idx; - get_pivot_column().add_column( matrix[ idx ] ); - } - - public: - - void _set_num_cols( index nr_of_columns ) { - #pragma omp parallel for - for( int tid = 0; tid < omp_get_num_threads(); tid++ ) { - _pivot_columns[ tid ].init( nr_of_columns ); - pos_of_pivot_columns[ tid ] = -1; - } - Base::_set_num_cols( nr_of_columns ); - } - // replaces(!) content of 'col' with boundary of given index - void _get_col( index idx, column& col ) const { - col.clear(); - if( is_represented_by_pivot_column( idx ) ) { - pivot_column& pivot_column = get_pivot_column(); - pivot_column.get_column_and_clear( col ); - pivot_column.add_column( col ); - } else { - Base::_get_col( idx, col ); - } - } - - // true iff boundary of given idx is empty - bool _is_empty( index idx ) const { - return is_represented_by_pivot_column( idx ) ? get_pivot_column().empty() : Base::_is_empty( idx ); - } - - // largest row index of given column idx (new name for lowestOne()) - index _get_max_index( index idx ) const { - if( is_represented_by_pivot_column( idx ) ) { - pivot_column& pivot_column = get_pivot_column(); - if( pivot_column.empty() ) { - return -1; - } else { - return pivot_column.max_index(); - } - } else { - return Base::_get_max_index( idx ); - } - } - - // adds column 'source' to column 'target' - void _add_to( index source, index target ) { - if( !is_represented_by_pivot_column( target ) ) { - unset_pos_of_pivot_column(); - represent_by_pivot_column( target ); - } - get_pivot_column().add_column( matrix[source] ); - } - - // clears given column - void _clear( index idx ) { - if( is_represented_by_pivot_column( idx ) ) { - column dummy; - get_pivot_column().get_column_and_clear(dummy); - } else { - Base::_clear( idx ); - } - } - - void _set_col( index idx, const column& col ) { - if( is_represented_by_pivot_column( idx ) ) { - column dummy; - pivot_column& pivot_column = get_pivot_column(); - pivot_column.get_column_and_clear( dummy ); - pivot_column.add_column( col ); - } else { - Base::_set_col( idx, col ); - } - } - - // removes the maximal index of a column - void _remove_max( index idx ) { - _toggle( idx, _get_max_index( idx ) ); - } - - //// toggles given index pair - void _toggle( index col_idx, index row_idx ) { - if( !is_represented_by_pivot_column( col_idx ) ) { - unset_pos_of_pivot_column(); - represent_by_pivot_column( col_idx ); - } - get_pivot_column().add_index( row_idx ); - } - - // syncronizes all data structures (essential for openmp stuff) - // has to be called before and after any multithreaded access! - void _sync() { - #pragma omp parallel for - for( int tid = 0; tid < omp_get_num_threads(); tid++ ) - unset_pos_of_pivot_column(); - } - - }; -} - - diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h deleted file mode 100644 index 34366d6a..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/bit_tree_pivot_column.h +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Hubert Wagner - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" -#include "../representations/abstract_pivot_column.h" - -namespace phat { - - // This is a bitset indexed with a 64-ary tree. Each node in the index - // has 64 bits; i-th bit says that the i-th subtree is non-empty. - // Supports practically O(1), inplace, zero-allocation: insert, remove, max_element - // and clear in O(number of ones in the bitset). - // 'add_index' is still the real bottleneck in practice. - class bit_tree_column - { - size_t offset; // data[i + offset] = ith block of the data-bitset - typedef uint64_t block_type; - std::vector< block_type > data; - - // this static is not a problem with OMP, it's initialized just after program starts - static const size_t debrujin_magic_table[64]; - - enum { block_size_in_bits = 64 }; - enum { block_shift = 6 }; - - // Some magic: http://graphics.stanford.edu/~seander/bithacks.html - // Gets the position of the rightmost bit of 'x'. 0 means the most significant bit. - // (-x)&x isolates the rightmost bit. - // The whole method is much faster than calling log2i, and very comparable to using ScanBitForward/Reverse intrinsic, - // which should be one CPU instruction, but is not portable. - size_t rightmost_pos(const block_type value) const - { - return 64 - 1 - debrujin_magic_table[((value & (-(int64_t)value))*0x07EDD5E59A4E28C2) >> 58]; - } - - public: - - void init(index num_cols) - { - int64_t n = 1; // in case of overflow - int64_t bottom_blocks_needed = (num_cols+block_size_in_bits-1)/block_size_in_bits; - int64_t upper_blocks = 1; - - // How many blocks/nodes of index needed to index the whole bitset? - while(n * block_size_in_bits < bottom_blocks_needed) - { - n *= block_size_in_bits; - upper_blocks += n; - } - - offset = upper_blocks; - data.resize(upper_blocks + bottom_blocks_needed, 0); - } - - index max_index() const - { - if (!data[0]) - return -1; - - const size_t size = data.size(); - size_t n = 0; - - while(true) - { - const block_type val = data[n]; - const size_t index = rightmost_pos(val); - const size_t newn = (n << block_shift) + index + 1; - - if (newn >= size) - { - const size_t bottom_index = n - offset; - return (bottom_index << block_shift) + index; - } - - n = newn; - } - - return -1; - } - - bool empty() const - { - return data[0] == 0; - } - - void add_index(const size_t entry) - { - const block_type ONE = 1; - const block_type block_modulo_mask = ((ONE << block_shift) - 1); - size_t index_in_level = entry >> block_shift; - size_t address = index_in_level + offset; - size_t index_in_block = entry & block_modulo_mask; - - block_type mask = (ONE << (block_size_in_bits - index_in_block - 1)); - - while(true) - { - data[address]^=mask; - - // First we check if we reached the root. - // Also, if anyone else was in this block, we don't need to update the path up. - if (!address || (data[address] & ~mask)) - return; - - index_in_block = index_in_level & block_modulo_mask; - index_in_level >>= block_shift; - --address; - address >>= block_shift; - mask = (ONE << (block_size_in_bits - index_in_block - 1)); - } - } - - void get_column_and_clear(column &out) - { - out.clear(); - while(true) - { - index mx = this->max_index(); - if (mx == -1) - break; - out.push_back(mx); - add_index(mx); - } - - std::reverse(out.begin(), out.end()); - } - - void add_column(const column &col) - { - for (size_t i = 0; i < col.size(); ++i) - { - add_index(col[i]); - } - } - - bool empty() { - return !data[0]; - } - }; - - const size_t bit_tree_column::debrujin_magic_table[64] = { - 63, 0, 58, 1, 59, 47, 53, 2, - 60, 39, 48, 27, 54, 33, 42, 3, - 61, 51, 37, 40, 49, 18, 28, 20, - 55, 30, 34, 11, 43, 14, 22, 4, - 62, 57, 46, 52, 38, 26, 32, 41, - 50, 36, 17, 19, 29, 10, 13, 21, - 56, 45, 25, 31, 35, 16, 9, 12, - 44, 24, 15, 8, 23, 7, 6, 5}; - - typedef abstract_pivot_column bit_tree_pivot_column; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h deleted file mode 100644 index 9e0c348d..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/full_pivot_column.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include -#include - -namespace phat { - class full_column { - - protected: - std::priority_queue< index > m_history; - std::vector< char > m_isInHistory; - std::vector< char > m_data; - - public: - void init( const index total_size ) { - m_data.resize( total_size, false ); - m_isInHistory.resize( total_size, false ); - } - - void add_column( const column& col ) { - for( index idx = 0; idx < (index) col.size(); idx++ ) { - add_index( col[ idx ] ); - } - } - void add_index( const index idx ) { - if( !m_isInHistory[ idx ] ) { - m_history.push( idx ); - m_isInHistory[ idx ] = true; - } - - m_data[ idx ] = !m_data[ idx ]; - } - - index max_index() { - while( m_history.size() > 0 ) { - index topIndex = m_history.top(); - if( m_data[ topIndex ] ) { - return topIndex; - } else { - m_history.pop(); - m_isInHistory[ topIndex ] = false; - } - } - - return -1; - } - - void get_column_and_clear( column& col ) { - col.clear(); - while( !empty() ) { - col.push_back( max_index() ); - add_index( max_index() ); - } - std::reverse( col.begin(), col.end() ); - } - - bool empty() { - return (max_index() == -1); - } - }; - - typedef abstract_pivot_column< full_column > full_pivot_column; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h deleted file mode 100644 index c851a2b5..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/sparse_pivot_column.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include -#include - -namespace phat { - class sparse_column { - - protected: - std::set< index > m_data; - - public: - void init( const index total_size ) { - m_data.clear(); - } - - void add_column( const column& col ) { - for( index idx = 0; idx < (index) col.size(); idx++ ) - add_index( col[ idx ] ); - } - - void add_index( const index idx ) { - std::pair< std::set< index >::iterator, bool > result = m_data.insert( idx ); - if( result.second == false ) - m_data.erase( result.first ); - } - - index max_index() { - return m_data.empty() ? -1 : *m_data.rbegin(); - } - - void get_column_and_clear( column& col ) { - col.clear(); - col.assign( m_data.begin(), m_data.end() ); - m_data.clear(); - } - - bool empty() { - return m_data.empty(); - } - }; - - typedef abstract_pivot_column< sparse_column > sparse_pivot_column; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h deleted file mode 100644 index 38e3090c..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_list.h +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include - -namespace phat { - class vector_list { - - protected: - typedef std::list< index > internal_column; - std::vector< dimension > dims; - std::vector< internal_column > matrix; - - public: - // overall number of cells in boundary_matrix - index _get_num_cols() const { - return (index)matrix.size(); - } - void _set_num_cols( index nr_of_columns ) { - dims.resize( nr_of_columns ); - matrix.resize( nr_of_columns ); - } - - // dimension of given index - dimension _get_dim( index idx ) const { - return dims[ idx ]; - } - void _set_dim( index idx, dimension dim ) { - dims[ idx ] = dim; - } - - // replaces(!) content of 'col' with boundary of given index - void _get_col( index idx, column& col ) const { - col.clear(); - col.reserve( matrix[idx].size() ); - std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) ); - } - - void _set_col( index idx, const column& col ) { - matrix[ idx ].clear(); - matrix[ idx ].resize( col.size() ); - std::copy (col.begin(), col.end(), matrix[ idx ].begin() ); - } - - // true iff boundary of given idx is empty - bool _is_empty( index idx ) const { - return matrix[ idx ].empty(); - } - - // largest row index of given column idx (new name for lowestOne()) - index _get_max_index( index idx ) const { - return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin(); - } - - // removes the maximal index of a column - void _remove_max( index idx ) { - internal_column::iterator it = matrix[ idx ].end(); - it--; - matrix[ idx ].erase( it ); - } - - // clears given column - void _clear( index idx ) { - matrix[ idx ].clear(); - } - - // syncronizes all data structures (essential for openmp stuff) - void _sync() {} - - // adds column 'source' to column 'target' - void _add_to( index source, index target ) { - internal_column& source_col = matrix[ source ]; - internal_column& target_col = matrix[ target ]; - internal_column temp_col; - target_col.swap( temp_col ); - std::set_symmetric_difference( temp_col.begin(), temp_col.end(), - source_col.begin(), source_col.end(), - std::back_inserter( target_col ) ); - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h deleted file mode 100644 index dadf1b34..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_set.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include - -namespace phat { - class vector_set { - - protected: - typedef std::set< index > internal_column; - std::vector< dimension > dims; - std::vector< internal_column > matrix; - - public: - // overall number of cells in boundary_matrix - index _get_num_cols() const { - return (index)matrix.size(); - } - void _set_num_cols( index nr_of_columns ) { - dims.resize( nr_of_columns ); - matrix.resize( nr_of_columns ); - } - - // dimension of given index - dimension _get_dim( index idx ) const { - return dims[ idx ]; - } - void _set_dim( index idx, dimension dim ) { - dims[ idx ] = dim; - } - - // replaces(!) content of 'col' with boundary of given index - void _get_col( index idx, column& col ) const { - col.clear(); - col.reserve( matrix[idx].size() ); - std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) ); - } - void _set_col( index idx, const column& col ) { - matrix[ idx ].clear(); - matrix[ idx ].insert( col.begin(), col.end() ); - } - - // true iff boundary of given idx is empty - bool _is_empty( index idx ) const { - return matrix[ idx ].empty(); - } - - // largest row index of given column idx (new name for lowestOne()) - index _get_max_index( index idx ) const { - return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin(); - } - - // removes the maximal index of a column - void _remove_max( index idx ) { - internal_column::iterator it = matrix[ idx ].end(); - it--; - matrix[ idx ].erase( it ); - } - - // clears given column - void _clear( index idx ) { - matrix[ idx ].clear(); - } - - // syncronizes all data structures (essential for openmp stuff) - void _sync() {} - - // adds column 'source' to column 'target' - void _add_to( index source, index target ) { - for( internal_column::iterator it = matrix[ source ].begin(); it != matrix[ source ].end(); it++ ) - _toggle( target, *it ); - } - - //// toggles given index pair - void _toggle( index col_idx, index row_idx ) { - internal_column& col = matrix[ col_idx ]; - std::pair< internal_column::iterator, bool > result = col.insert( row_idx ); - if( !result.second ) { - col.erase( result.first ); - } - } - }; -} diff --git a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h b/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h deleted file mode 100644 index efe8de4d..00000000 --- a/src/Bitmap_cubical_complex/include/gudhi/phat/representations/vector_vector.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright 2013 IST Austria - Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus - - This file is part of PHAT. - - PHAT is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PHAT 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PHAT. If not, see . */ - -#pragma once - -#include "../helpers/misc.h" - -namespace phat { - class vector_vector { - - protected: - std::vector< dimension > dims; - std::vector< column > matrix; - - thread_local_storage< column > temp_column_buffer; - - public: - // overall number of cells in boundary_matrix - index _get_num_cols() const { - return (index)matrix.size(); - } - void _set_num_cols( index nr_of_columns ) { - dims.resize( nr_of_columns ); - matrix.resize( nr_of_columns ); - } - - // dimension of given index - dimension _get_dim( index idx ) const { - return dims[ idx ]; - } - void _set_dim( index idx, dimension dim ) { - dims[ idx ] = dim; - } - - // replaces(!) content of 'col' with boundary of given index - void _get_col( index idx, column& col ) const { - col = matrix[ idx ]; - } - void _set_col( index idx, const column& col ) { - matrix[ idx ] = col; - } - - // true iff boundary of given idx is empty - bool _is_empty( index idx ) const { - return matrix[ idx ].empty(); - } - - // largest row index of given column idx (new name for lowestOne()) - index _get_max_index( index idx ) const { - return matrix[ idx ].empty() ? -1 : matrix[ idx ].back(); - } - - // removes the maximal index of a column - void _remove_max( index idx ) { - matrix[ idx ].pop_back(); - } - - // clears given column - void _clear( index idx ) { - matrix[ idx ].clear(); - } - - // syncronizes all data structures (essential for openmp stuff) - void _sync() {} - - // adds column 'source' to column 'target' - void _add_to( index source, index target ) { - column& source_col = matrix[ source ]; - column& target_col = matrix[ target ]; - column& temp_col = temp_column_buffer(); - temp_col.clear(); - std::set_symmetric_difference( target_col.begin(), target_col.end(), - source_col.begin(), source_col.end(), - std::back_inserter( temp_col ) ); - target_col.swap( temp_col ); - } - }; -} -- cgit v1.2.3 From ff41ff166c9ea66fcc1187056053e43bf7d7be8f Mon Sep 17 00:00:00 2001 From: glisse Date: Mon, 15 Feb 2016 11:51:20 +0000 Subject: typo git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1022 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d6068c0b757949d2e404ba99812ae7a0b8a8908d --- src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 2ec7594d..70f19e03 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -40,8 +40,8 @@ const bool globalDbg = false; template class is_before_in_filtration; /** -* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex__base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into -* Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex__base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. +* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into +* Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex_base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. **/ /** -- cgit v1.2.3 From 4d68901d74817ce356b701b38b083059954d7493 Mon Sep 17 00:00:00 2001 From: glisse Date: Sat, 20 Feb 2016 10:57:52 +0000 Subject: Details in the doc of alpha-complex. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1033 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7cc1b51ef8e93ee987710a8ea2ed4ac98638f099 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index b109956d..0987e0e7 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -39,13 +39,13 @@ namespace alphacomplex { * Alpha_complex is a simplicial complex * constructed from the finite cells of a Delaunay Triangulation. * - * 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. + * 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 square value are not inserted into - * the simplex. + * All simplices that have a filtration value strictly greater than a given alpha squared value are not inserted into + * the complex. * - * \image html "alpha_complex_representation.png" "Alpha simplicial complex representation" + * \image html "alpha_complex_representation.png" "Alpha-complex representation" * * Alpha_complex is constructing a `Simplex_tree` using Delaunay Triangulation @@ -54,7 +54,7 @@ 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 parameter. * * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. * @@ -129,14 +129,13 @@ namespace alphacomplex { * * \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()`). + * 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()`. * * \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. + * The simplex tree is pruned from the given maximum alpha squared value (cf. `Simplex_tree::prune_above_filtration()`). + * In the following example, the value is given by the user as argument of the program. * * * \section offexample Example from OFF file -- cgit v1.2.3 -- cgit v1.2.3 From 1967dc923b9bb24edd52a848b7991539779dbe8b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 9 Mar 2016 07:01:55 +0000 Subject: Add header and footer to generated documentation in order to fit with the web site. Add a package overview on top page. Remove text that was redundant with the web site. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1035 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 95d6c0e2f0ed8389620c27c03e37d441f93787ee --- CMakeGUDHIVersion.txt | 2 +- .../doc/sphere_contraction_representation.png | Bin 0 -> 44839 bytes src/Contraction/include/gudhi/Edge_contraction.h | 2 +- src/Doxyfile | 26 +- .../include/gudhi/Persistent_cohomology.h | 9 - .../doc/Simplex_tree_representation.png | Bin 0 -> 39217 bytes src/Simplex_tree/include/gudhi/Simplex_tree.h | 1 + src/common/doc/footer.html | 29 + src/common/doc/header.html | 82 ++ src/common/doc/main_page.h | 109 +- src/common/doc/stylesheet.css | 1367 ++++++++++++++++++++ 11 files changed, 1580 insertions(+), 47 deletions(-) create mode 100644 src/Contraction/doc/sphere_contraction_representation.png create mode 100644 src/Simplex_tree/doc/Simplex_tree_representation.png create mode 100644 src/common/doc/footer.html create mode 100644 src/common/doc/header.html create mode 100644 src/common/doc/stylesheet.css diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index 19d10535..20767813 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -1,5 +1,5 @@ set (GUDHI_MAJOR_VERSION 1) -set (GUDHI_MINOR_VERSION 2) +set (GUDHI_MINOR_VERSION 3) set (GUDHI_PATCH_VERSION 0) set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION}) diff --git a/src/Contraction/doc/sphere_contraction_representation.png b/src/Contraction/doc/sphere_contraction_representation.png new file mode 100644 index 00000000..edf37bf3 Binary files /dev/null and b/src/Contraction/doc/sphere_contraction_representation.png differ diff --git a/src/Contraction/include/gudhi/Edge_contraction.h b/src/Contraction/include/gudhi/Edge_contraction.h index ee3e3de1..73236db9 100644 --- a/src/Contraction/include/gudhi/Edge_contraction.h +++ b/src/Contraction/include/gudhi/Edge_contraction.h @@ -46,7 +46,7 @@ namespace contraction { The purpose of this package is to offer a user-friendly interface for edge contraction simplification of huge simplicial complexes. It uses the \ref skbl data-structure whose size remains small during simplification of most used geometrical complexes of topological data analysis such as the Rips or the Delaunay complexes. In practice, the -size of this data-structure is even uch lower than the total number of simplices. +size of this data-structure is even much lower than the total number of simplices. The edge contraction operation consists in identifying two vertices of a simplicial complex. A lot of algorithms have been developed in computer graphics that allows to reduce efficiently the size of 2-dimensional simplicial complexes diff --git a/src/Doxyfile b/src/Doxyfile index faa0d3fe..25f4f1ac 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -32,19 +32,19 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "Gudhi" +PROJECT_NAME = "GUDHI" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "1.2.0" +PROJECT_NUMBER = "1.3.0" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = +PROJECT_BRIEF = "C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding." # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels @@ -580,27 +580,27 @@ STRICT_PROTO_MATCHING = NO # documentation. # The default value is: YES. -GENERATE_TODOLIST = YES +GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. -GENERATE_TESTLIST = YES +GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. -GENERATE_BUGLIST = YES +GENERATE_BUGLIST = NO # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. -GENERATE_DEPRECATEDLIST= YES +GENERATE_DEPRECATEDLIST= NO # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond @@ -834,7 +834,9 @@ EXAMPLE_RECURSIVE = NO IMAGE_PATH = doc/Skeleton_blocker/ \ doc/common/ \ - doc/Contraction/ + doc/Contraction/ \ + doc/Simplex_tree/ \ + doc/Persistent_cohomology/ \ # The INPUT_FILTER tag can be used to specify a program that doxygen should @@ -1039,7 +1041,7 @@ HTML_FILE_EXTENSION = .html # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_HEADER = +HTML_HEADER = doc/common/header.html # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard @@ -1049,7 +1051,7 @@ HTML_HEADER = # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_FOOTER = +HTML_FOOTER = doc/common/footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of @@ -1061,7 +1063,7 @@ HTML_FOOTER = # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_STYLESHEET = +HTML_STYLESHEET = doc/common/stylesheet.css # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets @@ -1544,7 +1546,7 @@ EXTRA_SEARCH_MAPPINGS = # If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output. # The default value is: YES. -GENERATE_LATEX = YES +GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index 643b810c..3c331f0f 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -63,15 +63,6 @@ namespace persistent_cohomology { composed of three elements: topological spaces, their homology groups and an evolution scheme. - The theory of homology consists in attaching to a topological space a sequence of - (homology) groups, - capturing global topological features - like connected components, holes, cavities, etc. Persistent homology studies the evolution - -- birth, life and death -- of - these features when the topological space is changing. Consequently, the theory is essentially - composed of three elements: - topological spaces, their homology groups and an evolution scheme. -
Topological Spaces:
Topological spaces are represented by simplicial complexes. Let \f$V = \{1, \cdots ,|V|\}\f$ be a set of vertices. diff --git a/src/Simplex_tree/doc/Simplex_tree_representation.png b/src/Simplex_tree/doc/Simplex_tree_representation.png new file mode 100644 index 00000000..9d401520 Binary files /dev/null and b/src/Simplex_tree/doc/Simplex_tree_representation.png differ diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 096270ee..53f6fec7 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -68,6 +68,7 @@ namespace Gudhi { The simplex tree is an efficient and flexible data structure for representing general (filtered) simplicial complexes. The data structure is described in \cite boissonnatmariasimplextreealgorithmica + \image html "Simplex_tree_representation.png" "Simplex tree representation" The second one is the Hasse_complex. The Hasse complex is a data structure representing explicitly all co-dimension 1 incidence relations in a complex. It is consequently faster diff --git a/src/common/doc/footer.html b/src/common/doc/footer.html new file mode 100644 index 00000000..7b4cdc5c --- /dev/null +++ b/src/common/doc/footer.html @@ -0,0 +1,29 @@ + + + + + + + +
+ $projectname + Version $projectnumber + - $projectbrief + + + + $generatedby + + doxygen $doxygenversion + +
+ + + + + + diff --git a/src/common/doc/header.html b/src/common/doc/header.html new file mode 100644 index 00000000..c958390c --- /dev/null +++ b/src/common/doc/header.html @@ -0,0 +1,82 @@ + + + + + + + + +$projectname: $title +$title + + + + + + +$treeview +$search +$mathjax + +$extrastylesheet + + + + + + + +
+ + +
+ + + + + + + + + + +
$searchbox
+
+ + diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 41b8ba1e..5661c969 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -1,15 +1,14 @@ /*! \mainpage + * \tableofcontents * \image html "Gudhi_banner.jpg" "" width=20cm * * \section Introduction Introduction * The Gudhi library (Geometric Understanding in Higher Dimensions) is a generic open source C++ library for * Computational Topology and Topological Data Analysis * (TDA). - * The GUDHI library is developed as part of the - * GUDHI project supported by the European - * Research Council. The GUDHI library intends to help the development of new algorithmic solutions in TDA and their - * transfer to applications. It provides robust, efficient, flexible and easy to use implementations of - * state-of-the-art algorithms and data structures. + * The GUDHI library intends to help the development of new algorithmic solutions in TDA and their transfer to + * applications. It provides robust, efficient, flexible and easy to use implementations of state-of-the-art + * algorithms and data structures. * * The current release of the GUDHI library includes: * @@ -20,24 +19,86 @@ * All data-structures are generic and several of their aspects can be parameterized via template classes. * We refer to \cite gudhilibrary_ICMS14 for a detailed description of the design of the library. * - * The library is available here - * and the documentation is available at this - * webpage. - * - * The library comes with data sets, \ref demos and \ref testsuites. - * - * Gudhi is also accessible though the - * R package TDA - * (Statistical Tools for Topological Data Analysis). - * - * The development of the GUDHI library is steered by an Editorial Board composed of: - * - * \li - * Jean-Daniel Boissonnat | INRIA Sophia Antipolis - Méditerranée - * \li Marc Glisse | INRIA Saclay - Ile de France - * \li Clément Jamin | INRIA Sophia Antipolis - Méditerranée - * \li Vincent Rouvreau | INRIA Saclay - Ile de France - * + \section DataStructures Data structures + \subsection SimplexTreeDataStructure Simplex tree + \image html "Simplex_tree_representation.png" "Simplex tree representation" + + + + + +
+ Introduced in: GUDHI 1.0.0
+ Copyright: GPL v3
+
+ Clément Maria
+ The simplex tree is an efficient and flexible + data structure for representing general (filtered) simplicial complexes. The data structure + is described in \cite boissonnatmariasimplextreealgorithmica .
+ User manual: \ref simplex_tree - Reference manual: Gudhi::Simplex_tree +
+ \subsection SkeletonBlockerDataStructure Skeleton blocker + \image html "ds_representation.png" "Skeleton blocker representation" + + + + + +
+ Introduced in: GUDHI 1.1.0
+ Copyright: GPL v3
+
+ David Salinas
+ The Skeleton-Blocker data-structure proposes a light encoding for simplicial complexes by storing only an *implicit* + representation of its simplices \cite socg_blockers_2011,\cite blockers2012. Intuitively, it just stores the + 1-skeleton of a simplicial complex with a graph and the set of its "missing faces" that is very small in practice. + This data-structure handles all simplicial complexes operations such as simplex enumeration or simplex removal but + operations that are particularly efficient are operations that do not require simplex enumeration such as edge + iteration, link computation or simplex contraction.
+ User manual: \ref skbl - Reference manual: Gudhi::skbl::Skeleton_blocker_complex +
+ + \section Toolbox Toolbox + \subsection PersistentCohomologyToolbox Persistent Cohomology + \image html "barcode_poch.png" "Persistent Cohomology represented as a barcode" + + + + + +
+ Introduced in: GUDHI 1.0.0
+ Copyright: GPL v3
+
+ Clément Maria
+ The theory of homology consists in attaching to a topological space a sequence of (homology) groups, capturing + global topological features like connected components, holes, cavities, etc. Persistent homology studies the + evolution -- birth, life and death -- of these features when the topological space is changing. Consequently, the + theory is essentially composed of three elements: topological spaces, their homology groups and an evolution + scheme. + Computation of persistent cohomology using the algorithm of \cite DBLP:journals/dcg/SilvaMV11 and + \cite DBLP:journals/corr/abs-1208-5018 and the Compressed Annotation Matrix implementation of + \cite DBLP:conf/esa/BoissonnatDM13 .
+ User manual: \ref persistent_cohomology +
+ \subsection ContractionToolbox Contraction + \image html "sphere_contraction_representation.png" "Sphere contraction example" + + + + + +
+ Introduced in: GUDHI 1.1.0
+ Copyright: GPL v3
+
+ David Salinas
+ The purpose of this package is to offer a user-friendly interface for edge contraction simplification of huge + simplicial complexes. It uses the \ref skbl data-structure whose size remains small during simplification of most + used geometrical complexes of topological data analysis such as the Rips or the Delaunay complexes. In practice, + the size of this data-structure is even much lower than the total number of simplices.
+ User manual: \ref contr +
*/ /*! \page installation Gudhi installation @@ -47,7 +108,7 @@ * * \section compiling Compiling * The library uses c++11 and requires Boost with version 1.48.0 or - * more recent. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2013. + * more recent. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015. * * \subsection gmp GMP: * The multi-field persistent homology algorithm requires GMP which is a free library for arbitrary-precision diff --git a/src/common/doc/stylesheet.css b/src/common/doc/stylesheet.css new file mode 100644 index 00000000..1df177a4 --- /dev/null +++ b/src/common/doc/stylesheet.css @@ -0,0 +1,1367 @@ +/* The standard CSS for doxygen 1.8.6 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 4px 6px; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view when not used as main index */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + border: 0px none; + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 60% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 80% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + -- cgit v1.2.3 From 5478241247f6fb7bcbc57f86050205e4fa8c2737 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 9 Mar 2016 10:53:36 +0000 Subject: Add of persistence doc image for package overview git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1036 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ab1ca8902d6e5651cdfd9957d9b261b6874bae8d --- src/Persistent_cohomology/doc/3DTorus_poch.png | Bin 0 -> 33733 bytes src/common/doc/main_page.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/Persistent_cohomology/doc/3DTorus_poch.png diff --git a/src/Persistent_cohomology/doc/3DTorus_poch.png b/src/Persistent_cohomology/doc/3DTorus_poch.png new file mode 100644 index 00000000..293c1b8c Binary files /dev/null and b/src/Persistent_cohomology/doc/3DTorus_poch.png differ diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 5661c969..35313409 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -60,7 +60,7 @@ \section Toolbox Toolbox \subsection PersistentCohomologyToolbox Persistent Cohomology - \image html "barcode_poch.png" "Persistent Cohomology represented as a barcode" + \image html "3DTorus_poch.png" "Rips Persistent Cohomology on a 3D Torus"
-- 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(-) 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 df8cf1a75bceb3411e98281585045fb0f5609939 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 10:29:38 +0000 Subject: Boost flat_map erase on an iterator is most efficient git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1040 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1b20d31e129b9aa7f2d884aa935a53959a288650 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 2 +- src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 3569b323..1c4587c0 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1229,7 +1229,7 @@ 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->erase(sh->first); + child->erase(sh); } 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()); 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 8942d92c..1eca7f6f 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,8 +116,8 @@ class Simplex_tree_siblings { return members_.size(); } - void erase(const Vertex_handle vh) { - members_.erase(vh); + void erase(const Dictionary_it iterator) { + members_.erase(iterator); } Simplex_tree_siblings * oncles_; -- cgit v1.2.3 From 558d908404cdc2e1f5111fd9ee236cd55ab7790a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 11:00:11 +0000 Subject: Use GUDHI_CHECK on null_simplex instead of "if" git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1041 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 783218b56e34ef53fbca5bb52e8a467504c0eddc --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 1c4587c0..813e7924 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -451,12 +451,12 @@ class Simplex_tree { } /** \brief Sets the filtration value of a simplex. - * - * No action if called on the null_simplex*/ + * \warning In debug mode, the exception std::invalid_argument is thrown if sh is a null_simplex. + */ void assign_filtration(Simplex_handle sh, Filtration_value fv) { - if (sh != null_simplex()) { - sh->second.assign_filtration(fv); - } + GUDHI_CHECK(sh == null_simplex(), + std::invalid_argument ("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex")); + sh->second.assign_filtration(fv); } /** \brief Returns an upper bound of the filtration values of the simplices. */ -- cgit v1.2.3 From 5389d8969d8386bb4c74dbef4b7c7992e9130f13 Mon Sep 17 00:00:00 2001 From: pdlotko Date: Mon, 14 Mar 2016 12:59:53 +0000 Subject: Answers to Marc's comments. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1042 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 481841d609bae68df85a93527e6d3cc20f1b06e2 --- .../example/Bitmap_cubical_complex.cpp | 146 ++++----- src/Bitmap_cubical_complex/example/CMakeLists.txt | 4 +- .../include/gudhi/Bitmap_cubical_complex.h | 8 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 355 ++++++++++++--------- ...cal_complex_periodic_boundary_conditions_base.h | 10 + 5 files changed, 288 insertions(+), 235 deletions(-) diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index 39a55f24..4c30ee85 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -1,73 +1,73 @@ - /* 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): Pawel Dlotko - * - * 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 -#include -#include - - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff -#include -#include -#include - -using namespace std; - - -int main( int argc , char** argv ) -{ - cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - - - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 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): Pawel Dlotko + * + * 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 +#include +#include +#include + + +using namespace Gudhi; +using namespace Gudhi::Cubical_complex; +using namespace Gudhi::persistent_cohomology; + +//standard stuff +#include +#include +#include + +using namespace std; + + +int main( int argc , char** argv ) +{ + cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbered in \ +the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ +of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ +lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + + int p = 2; + double min_persistence = 0; + + if ( argc != 2 ) + { + cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; + return 1; + } + + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); + + // Compute the persistence diagram of the complex + persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); + pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + + pcoh.compute_persistent_cohomology( min_persistence ); + + stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out((char*)ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; +} diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index fbd1b28b..14c94e8e 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -13,5 +13,5 @@ add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp ) target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) -add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) -target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file +#add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) +#target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 70f19e03..4dd295e7 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include "Bitmap_cubical_complex_base.h" #include "Bitmap_cubical_complex_periodic_boundary_conditions_base.h" @@ -127,7 +128,12 @@ public: //If the user decide to change some elements of the bitmap, then this procedure need //to be called again. this->initialize_simplex_associated_to_key(); - } + } + + /** + * Destructor of the Bitmap_cubical_complex class. + **/ + virtual ~Bitmap_cubical_complex(){} //*********************************************// diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 22b703a9..807be335 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -23,13 +23,14 @@ #pragma once #include +#include #include #include #include #include #include #include -#include +#include #include #include "Bitmap_cubical_complex/counter.h" @@ -43,7 +44,11 @@ namespace Cubical_complex { - +/** + *@class Bitmap_cubical_complex_base + *@brief Cubical complex represented as a bitmap, class with basic implementation. + *@ingroup cubical_complex + */ /** * This is a class implementing a basic bitmap data structure to store cubical complexes. * It implements only the most basic subroutines. @@ -64,13 +69,13 @@ namespace Cubical_complex template class Bitmap_cubical_complex_base { -public: - typedef T filtration_type; - /** - *Default constructor - **/ - Bitmap_cubical_complex_base() - { +public: + typedef T filtration_type; + /** + *Default constructor + **/ + Bitmap_cubical_complex_base() + { } /** * There are a few constructors of a Bitmap_cubical_complex_base class. @@ -92,6 +97,11 @@ public: **/ Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells ); + /** + * Destructor of the Bitmap_cubical_complex_base class. + **/ + virtual ~Bitmap_cubical_complex_base(){} + /** * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell * and get_cell_data are the basic @@ -152,18 +162,27 @@ public: * Writing to stream operator. **/ template - friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); - - + friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + + /** - * Functions that put the input data to bins. + * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) + * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. **/ void put_data_toBins( size_t number_of_bins ); - void put_data_toBins( T diameter_of_bin ); - + + /** + * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is + * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex + * before and after using such a function will be bounded by the parameter diameter_of_bin. + **/ + void put_data_toBins( T diameter_of_bin ); + /** * Functions to find min and max values of filtration. - **/ + **/ std::pair< T ,T > min_max_filtration(); //ITERATORS @@ -172,42 +191,60 @@ public: * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ - typedef typename std::vector< T >::iterator all_cells_iterator; - + typedef typename std::vector< T >::iterator all_cells_iterator; + + /** - * Function returning an iterator to the first cell of the bitmap. + * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). **/ - all_cells_iterator all_cells_begin() + typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + + /** + * Function returning a constant iterator to the first cell of the bitmap. + **/ + all_cells_const_iterator all_cells_const_begin()const { return this->data.begin(); - } - - /** - * Function returning an iterator to the last cell of the bitmap. + } + + + /** + * Function returning a constant iterator to the last cell of the bitmap. **/ - all_cells_iterator all_cells_end()const + all_cells_const_iterator all_cells_const_end()const { return this->data.end(); } /** - * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. - * in lexicographical order). + * Function returning an iterator to the first cell of the bitmap. **/ - typedef typename std::vector< T >::const_iterator all_cells_const_iterator; - + all_cells_iterator all_cells_begin() + { + return this->data.begin(); + } + /** * Function returning a constant iterator to the first cell of the bitmap. **/ - all_cells_const_iterator all_cells_const_begin()const + all_cells_const_iterator all_cells_begin() const { return this->data.begin(); - } - + } + + /** + * Function returning an iterator to the last cell of the bitmap. + **/ + all_cells_iterator all_cells_end() + { + return this->data.end(); + } + /** * Function returning a constant iterator to the last cell of the bitmap. **/ - all_cells_const_iterator all_cells_const_end()const + all_cells_const_iterator all_cells_end() const { return this->data.end(); } @@ -303,8 +340,8 @@ public: protected: std::vector< size_t > counter; Bitmap_cubical_complex_base& b; - }; - + }; + /** * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell cell of the bitmap. **/ @@ -312,8 +349,8 @@ public: { Top_dimensional_cells_iterator a(*this); return a; - } - + } + /** * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell cell of the bitmap. **/ @@ -333,11 +370,11 @@ public: //****************************************************************************************************************// //****************************************************************************************************************// //****************************************************************************************************************// - - -inline size_t number_cells()const -{ - return this->total_number_of_cells; + + +inline size_t number_cells()const +{ + return this->total_number_of_cells; } //****************************************************************************************************************// @@ -375,7 +412,7 @@ protected: std::vector compute_counter_for_given_cell( size_t cell )const { - std::vector counter; + std::vector counter; counter.reserve( this->sizes.size() ); for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) { @@ -384,59 +421,59 @@ protected: } std::reverse( counter.begin() , counter.end() ); return counter; - } - void read_perseus_style_file( const char* perseus_style_file ); - void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); - Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); - Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); + } + void read_perseus_style_file( const char* perseus_style_file ); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); + Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); + Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ); }; -template -void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) -{ - bool bdg = false; - - std::pair< T ,T > min_max = this->min_max_filtration(); - T dx = (min_max.second-min_max.first)/(T)number_of_bins; - - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - template -void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) -{ - bool bdg = false; - std::pair< T ,T > min_max = this->min_max_filtration(); - - size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - -template -std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() -{ - std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( this->data[i] < min_max.first )min_max.first = this->data[i]; - if ( this->data[i] > min_max.second )min_max.second = this->data[i]; - } - return min_max; -} +void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) +{ + bool bdg = false; + + std::pair< T ,T > min_max = this->min_max_filtration(); + T dx = (min_max.second-min_max.first)/(T)number_of_bins; + + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) +{ + bool bdg = false; + std::pair< T ,T > min_max = this->min_max_filtration(); + + size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() +{ + std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( this->data[i] < min_max.first )min_max.first = this->data[i]; + if ( this->data[i] > min_max.second )min_max.second = this->data[i]; + } + return min_max; +} template @@ -457,10 +494,10 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base { this->set_up_containers( sizes ); } - -template -void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) -{ + +template +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) +{ this->set_up_containers( sizes_in_following_directions ); size_t number_of_top_dimensional_elements = 1; @@ -489,19 +526,19 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells (*it) = top_dimensional_cells[index]; ++index; } - this->impose_lower_star_filtration(); -} + this->impose_lower_star_filtration(); +} template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base ( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) { this->setup_bitmap_based_on_top_dimensional_cells_list( sizes_in_following_directions , top_dimensional_cells ); -} - -template -void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) -{ +} + +template +void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) +{ bool dbg = false; ifstream inFiltration, inIds; inFiltration.open( perseus_style_file ); @@ -510,7 +547,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;getchar();} - std::vector sizes; + std::vector sizes; sizes.reserve( dimensionOfData ); for ( size_t i = 0 ; i != dimensionOfData ; ++i ) { @@ -541,31 +578,31 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu ++it; } inFiltration.close(); - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->read_perseus_style_file( perseus_style_file ); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->set_up_containers( sizes ); -} - -template + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->read_perseus_style_file( perseus_style_file ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->set_up_containers( sizes ); +} + +template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); } template @@ -578,29 +615,29 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const { - std::vector< size_t > boundary_elements; - - //Speed traded of for memory. Check if it is better in practice. - boundary_elements.reserve( this->dimension()*2 ); + std::vector< size_t > boundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + boundary_elements.reserve( this->dimension()*2 ); size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 1 ) - { - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + { + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); } cell1 = cell1%this->multipliers[i-1]; } return boundary_elements; -} +} + + + - - - template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { @@ -625,8 +662,8 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( cell1 = cell1%this->multipliers[i-1]; } return coboundary_elements; -} - +} + @@ -675,14 +712,14 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() //this vector will be used to check which elements have already been taken care of //in imposing lower star filtration: std::vector is_this_cell_considered( this->data.size() , false ); - - size_t size_to_reserve = 1; - for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) - { - size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); - } - - std::vector indices_to_consider; + + size_t size_to_reserve = 1; + for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) + { + size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); + } + + std::vector indices_to_consider; indices_to_consider.reserve( size_to_reserve ); //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. @@ -708,20 +745,20 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) - { - if ( dbg ) - { - cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; - getchar(); - + { + if ( dbg ) + { + cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; + getchar(); + } if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) { - this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; - if ( dbg ) - { - cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; - getchar(); + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + if ( dbg ) + { + cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; + getchar(); } } if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) @@ -760,4 +797,4 @@ bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , ch } -} +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index f0fd785f..8c1254db 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -37,6 +37,11 @@ namespace Cubical_complex //right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base +/** + *@class Bitmap_cubical_complex_periodic_boundary_conditions_base + *@brief Cubical complex with periodic boundary conditions represented as a bitmap. + *@ingroup cubical_complex + */ /** * This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. * The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. @@ -64,6 +69,11 @@ public: */ Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); + /** + * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class. + **/ + virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base(){} + //overwritten methods co compute boundary and coboundary /** * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. -- cgit v1.2.3 From 07fe71e2301f95fd0008bfc91e72f07b4f0d9bb6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 13:42:22 +0000 Subject: No more use of threshold_ for prune_above_filtration because threshold may be not up to date git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1043 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b17d8ef63bc173b4c4b6b0bde31f97d85672a754 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 48 +++++++++++------------- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 35 +++++------------ 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 813e7924..92f4576d 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1174,7 +1174,6 @@ class Simplex_tree { 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. @@ -1182,33 +1181,30 @@ class Simplex_tree { void prune_above_filtration(Filtration_value filtration) { // 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()) { - initialize_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() > threshold_); - 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 - if (simplex_list_to_removed.size() > 0) - 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 + if (simplex_list_to_removed.size() > 0) + initialize_filtration(); } } diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index cd6746a6..ff8993b3 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -989,7 +989,7 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { // Constructs a copy at this state for further test purpose typeST st_pruned = st; - st_pruned.initialize_filtration(); // reset + st_pruned.initialize_filtration(); // reset st.insert_simplex_and_subfaces({3, 0}, 3.0); st.insert_simplex_and_subfaces({2, 1, 0}, 4.0); @@ -1021,12 +1021,11 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { 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 - std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; + std::cout << "The complex contains " << st.num_simplices() << " simplices"; std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; for (auto f_simplex : st.filtration_simplex_range()) { @@ -1039,47 +1038,33 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { // 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); // Display the Simplex_tree - std::cout << "The complex pruned at 2.5 contains " << st.num_simplices() << " simplices" << std::endl; + 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 << "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; - } - st_pruned.set_filtration(2.0); st.prune_above_filtration(2.0); + + std::cout << "The complex pruned at 2.0 contains " << st.num_simplices() << " simplices"; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + BOOST_CHECK(st == st_pruned); typeST st_empty; + st_empty.set_filtration(6.0); // For equality reason // FIXME st_empty.set_dimension(3); st.prune_above_filtration(0.0); - // Display the Simplex_tree - std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices" << std::endl; + // 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 << "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; - } 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); } -- cgit v1.2.3 From 77243b4c6ad09f1f60122191414fc5fb2e2cc865 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 15:08:30 +0000 Subject: Remove Options::store_filtration check is true in prune_above_filtration function in order to let the user empty the tree To empty the tree, call initialize_filtration() and prune_above_filtration(-1) Add a UT to test this case git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1044 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: bb4a916fb547c6312f2138d355903ef87525e9c4 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 49 +++++++++++------------- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 40 ++++++++++++++++++- 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 92f4576d..ac5fbe79 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1179,33 +1179,30 @@ class Simplex_tree { * call `initialize_filtration()` to recompute it. */ void prune_above_filtration(Filtration_value filtration) { - // No action if filtration is not stored - if (Options::store_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 - if (simplex_list_to_removed.size() > 0) - initialize_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 + if (simplex_list_to_removed.size() > 0) + initialize_filtration(); } /** \brief Remove a maximal simplex. diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index ff8993b3..b8c1cc35 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -985,7 +985,6 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { 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; @@ -1053,7 +1052,6 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { BOOST_CHECK(st == st_pruned); typeST st_empty; - st_empty.set_filtration(6.0); // For equality reason // FIXME st_empty.set_dimension(3); st.prune_above_filtration(0.0); @@ -1068,3 +1066,41 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { st.prune_above_filtration(-1.0); BOOST_CHECK(st == st_empty); } + +BOOST_AUTO_TEST_CASE(mini_prune_above_filtration) { + std::cout << "********************************************************************" << std::endl; + std::cout << "MINI PRUNE ABOVE FILTRATION" << std::endl; + typedef Simplex_tree typeST; + typeST st; + + // FIXME + st.set_dimension(3); + + st.insert_simplex_and_subfaces({0, 1, 6, 7}); + st.insert_simplex_and_subfaces({3, 4, 5}); + st.insert_simplex_and_subfaces({3, 0}); + st.insert_simplex_and_subfaces({2, 1, 0}); + + // st: + // 1 6 + // o---o + // /X\7/ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 + + st.initialize_filtration(); + + // Display the Simplex_tree + std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; + BOOST_CHECK(st.num_simplices() == 27); + + // Test case to the limit + st.prune_above_filtration(-1.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 50d0b9006eaefa4aa41eba336206afd5ad700324 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 15:20:59 +0000 Subject: Remove temporary get_persistence function git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1045 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c7503904a243d5f642b9efcbc65df856590e11fc --- src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index 19417ace..643b810c 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -722,14 +722,6 @@ class Persistent_cohomology { } } - void get_persistence(std::vector>& persistence) { - cmp_intervals_by_length cmp(cpx_); - std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp); - for (auto pair : persistent_pairs_) { - persistence.push_back(std::make_pair(cpx_->filtration(get<0>(pair)), cpx_->filtration(get<1>(pair)))); - } - } - void write_output_diagram(std::string diagram_name) { std::ofstream diagram_out(diagram_name.c_str()); cmp_intervals_by_length cmp(cpx_); -- 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 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(-) 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 6996f2a16a1fdaa0d0faee1c559855fbea25b6c1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 16 Mar 2016 08:49:20 +0000 Subject: Compil issue git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1048 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4fcfc1498408eb98a12ed5d48e620dc38d4c442d --- src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp index f81951ce..01497c7c 100644 --- a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp @@ -132,7 +132,7 @@ int main(int argc, char * const argv[]) { int coeff_field_characteristic = atoi(argv[2]); Filtration_value min_persistence = 0.0; - returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); + int returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); if ((returnedScanValue == EOF) || (min_persistence < -1.0)) { std::cerr << "Error: " << argv[3] << " is not correct\n"; usage(argv[0]); -- cgit v1.2.3 From d133f17dede836cee1dfff47d2e00532573b9ead Mon Sep 17 00:00:00 2001 From: pdlotko Date: Thu, 17 Mar 2016 08:43:58 +0000 Subject: cleanning up the stuff with iterators in Bitmap_cubical_complex_base.h class. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1049 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9630d6df6a2ecdb51ab25150454a563cd928b09a --- .../example/Random_bitmap_cubical_complex.cpp | 7 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 515 +++++++++++++-------- ...cal_complex_periodic_boundary_conditions_base.h | 4 +- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 183 +++++++- 4 files changed, 500 insertions(+), 209 deletions(-) diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index 97347162..8b7f6a04 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -70,11 +70,12 @@ The program will create random cubical complex of that sizes and compute persist for ( size_t i = 0 ; i != multipliers ; ++i ) { data.push_back( rand()/(double)RAND_MAX ); - } - + } + Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( sizes , data ); + + - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( sizes , data ); // Compute the persistence diagram of the complex diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 807be335..6d2b705c 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include #include #include @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include "Bitmap_cubical_complex/counter.h" @@ -69,13 +69,13 @@ namespace Cubical_complex template class Bitmap_cubical_complex_base { -public: - typedef T filtration_type; - /** - *Default constructor - **/ - Bitmap_cubical_complex_base() - { +public: + typedef T filtration_type; + /** + *Default constructor + **/ + Bitmap_cubical_complex_base() + { } /** * There are a few constructors of a Bitmap_cubical_complex_base class. @@ -96,11 +96,11 @@ public: * together with vector of filtration values of top dimensional cells. **/ Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells ); - + /** * Destructor of the Bitmap_cubical_complex_base class. - **/ - virtual ~Bitmap_cubical_complex_base(){} + **/ + virtual ~Bitmap_cubical_complex_base(){} /** * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell @@ -130,7 +130,9 @@ public: **/ inline unsigned get_dimension_of_a_cell( size_t cell )const; /** - * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. + * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. This allows reading and changing the value of filtration. + * Note that if the value of a filtration is changed, the code do not check if we have a filtration or not. i.e. it do not check if the value of a filtration of a cell is + * not smaller than the value of a filtration of its boundary and not greater than the value of its coboundary. **/ inline T& get_cell_data( size_t cell ); @@ -162,27 +164,27 @@ public: * Writing to stream operator. **/ template - friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); - - + friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); + + /** - * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) + * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. **/ - void put_data_toBins( size_t number_of_bins ); - + void put_data_toBins( size_t number_of_bins ); + /** - * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is - * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex + * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is + * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex * before and after using such a function will be bounded by the parameter diameter_of_bin. **/ - void put_data_toBins( T diameter_of_bin ); - + void put_data_toBins( T diameter_of_bin ); + /** * Functions to find min and max values of filtration. - **/ + **/ std::pair< T ,T > min_max_filtration(); //ITERATORS @@ -191,76 +193,179 @@ public: * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ - typedef typename std::vector< T >::iterator all_cells_iterator; + //typedef typename std::vector< T >::iterator all_cells_iterator; /** * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ - typedef typename std::vector< T >::const_iterator all_cells_const_iterator; - + //typedef typename std::vector< T >::const_iterator all_cells_const_iterator; + /** * Function returning a constant iterator to the first cell of the bitmap. **/ - all_cells_const_iterator all_cells_const_begin()const - { - return this->data.begin(); - } - - + //all_cells_const_iterator all_cells_const_begin()const + //{ + // return this->data.begin(); + //} + + /** * Function returning a constant iterator to the last cell of the bitmap. **/ - all_cells_const_iterator all_cells_const_end()const + //all_cells_const_iterator all_cells_const_end()const + //{ + // return this->data.end(); + //} + + /** + * Function returning an iterator to the first cell of the bitmap. + **/ + //all_cells_iterator all_cells_begin() + //{ + // return this->data.begin(); + //} + + /** + * Function returning a constant iterator to the first cell of the bitmap. + **/ + //all_cells_const_iterator all_cells_begin() const + //{ + // return this->data.begin(); + //} + + /** + * Function returning an iterator to the last cell of the bitmap. + **/ + //all_cells_iterator all_cells_end() + //{ + // return this->data.end(); + //} + + /** + * Function returning a constant iterator to the last cell of the bitmap. + **/ + //all_cells_const_iterator all_cells_end() const + //{ + // return this->data.end(); + //} + + /** + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). + **/ + class All_cells_iterator : std::iterator< std::input_iterator_tag, T > { - return this->data.end(); - } + public: + All_cells_iterator() + { + this->counter = 0; + } + All_cells_iterator operator++() + { + //first find first element of the counter that can be increased: + ++this->counter; + return *this; + } + All_cells_iterator operator++(int) + { + All_cells_iterator result = *this; + ++(*this); + return result; + } + All_cells_iterator operator =( const All_cells_iterator& rhs ) + { + this->counter = rhs.counter; + return *this; + } + bool operator == ( const All_cells_iterator& rhs )const + { + if ( this->counter != rhs.counter )return false; + return true; + } + bool operator != ( const All_cells_iterator& rhs )const + { + return !(*this == rhs); + } + size_t operator*() + { + return this->counter; + } + friend class Bitmap_cubical_complex_base; + protected: + size_t counter; + }; + /** - * Function returning an iterator to the first cell of the bitmap. + * Function returning a All_cells_iterator to the first cell of the bitmap. **/ - all_cells_iterator all_cells_begin() + All_cells_iterator all_cells_iterator_begin() { - return this->data.begin(); - } - + All_cells_iterator a; + return a; + } + /** - * Function returning a constant iterator to the first cell of the bitmap. + * Function returning a All_cells_iterator to the last cell of the bitmap. **/ - all_cells_const_iterator all_cells_begin() const + All_cells_iterator all_cells_iterator_end() { - return this->data.begin(); - } - + All_cells_iterator a; + a.counter = this->data.size(); + return a; + } + /** - * Function returning an iterator to the last cell of the bitmap. + * Boundary_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< size_t >::iterator Boundary_iterator; + typedef typename std::vector< size_t > Boundary_range; + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. **/ - all_cells_iterator all_cells_end() + Boundary_range boundary_range(size_t sh) { - return this->data.end(); - } - + return this->get_boundary_of_a_cell(sh); + } + /** - * Function returning a constant iterator to the last cell of the bitmap. + * Coboundary_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< size_t >::iterator Coboundary_iterator; + typedef typename std::vector< size_t > Coboundary_range; + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. **/ - all_cells_const_iterator all_cells_end() const + Coboundary_range coboundary_range(size_t sh) { - return this->data.end(); - } + return this->get_coboundary_of_a_cell(sh); + } + + + + + + + /** * Iterator through top dimensional cells of the complex. The cells appear in order they are stored * in the structure (i.e. in lexicographical order) **/ - class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, double > + class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > { public: Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) { - this->counter = std::vector(b.dimension()); - //std::fill( this->counter.begin() , this->counter.end() , 0 ); - } + this->counter = std::vector(b.dimension()); + //std::fill( this->counter.begin() , this->counter.end() , 0 ); + } Top_dimensional_cells_iterator operator++() { //first find first element of the counter that can be increased: @@ -308,15 +413,20 @@ public: return !(*this == rhs); } - T& operator*() - { - //given the counter, compute the index in the array and return this element. - unsigned index = 0; - for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - { - index += (2*this->counter[i]+1)*this->b.multipliers[i]; - } - return this->b.data[index]; + //T& operator*() + //{ + // //given the counter, compute the index in the array and return this element. + // unsigned index = 0; + // for ( size_t i = 0 ; i != this->counter.size() ; ++i ) + // { + // index += (2*this->counter[i]+1)*this->b.multipliers[i]; + // } + // return this->b.data[index]; + //} + + size_t operator*() + { + return this->compute_index_in_bitmap(); } size_t compute_index_in_bitmap()const @@ -327,7 +437,8 @@ public: index += (2*this->counter[i]+1)*this->b.multipliers[i]; } return index; - } + } + void print_counter()const { @@ -340,19 +451,19 @@ public: protected: std::vector< size_t > counter; Bitmap_cubical_complex_base& b; - }; - + }; + /** - * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell cell of the bitmap. + * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap. **/ Top_dimensional_cells_iterator top_dimensional_cells_begin() { Top_dimensional_cells_iterator a(*this); return a; - } - + } + /** - * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell cell of the bitmap. + * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap. **/ Top_dimensional_cells_iterator top_dimensional_cells_end() { @@ -370,11 +481,11 @@ public: //****************************************************************************************************************// //****************************************************************************************************************// //****************************************************************************************************************// - - -inline size_t number_cells()const -{ - return this->total_number_of_cells; + + +inline size_t number_cells()const +{ + return this->total_number_of_cells; } //****************************************************************************************************************// @@ -412,7 +523,7 @@ protected: std::vector compute_counter_for_given_cell( size_t cell )const { - std::vector counter; + std::vector counter; counter.reserve( this->sizes.size() ); for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) { @@ -421,59 +532,59 @@ protected: } std::reverse( counter.begin() , counter.end() ); return counter; - } - void read_perseus_style_file( const char* perseus_style_file ); - void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); - Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); - Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); + } + void read_perseus_style_file( const char* perseus_style_file ); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); + Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); + Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ); }; +template +void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) +{ + bool bdg = false; + + std::pair< T ,T > min_max = this->min_max_filtration(); + T dx = (min_max.second-min_max.first)/(T)number_of_bins; + + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + template -void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) -{ - bool bdg = false; - - std::pair< T ,T > min_max = this->min_max_filtration(); - T dx = (min_max.second-min_max.first)/(T)number_of_bins; - - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - -template -void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) -{ - bool bdg = false; - std::pair< T ,T > min_max = this->min_max_filtration(); - - size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - -template -std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() -{ - std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( this->data[i] < min_max.first )min_max.first = this->data[i]; - if ( this->data[i] > min_max.second )min_max.second = this->data[i]; - } - return min_max; -} +void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) +{ + bool bdg = false; + std::pair< T ,T > min_max = this->min_max_filtration(); + + size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; + //now put the data into the appropriate bins: + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} + this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; + if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} + } +} + +template +std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() +{ + std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); + for ( size_t i = 0 ; i != this->data.size() ; ++i ) + { + if ( this->data[i] < min_max.first )min_max.first = this->data[i]; + if ( this->data[i] > min_max.second )min_max.second = this->data[i]; + } + return min_max; +} template @@ -494,10 +605,10 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base { this->set_up_containers( sizes ); } - -template -void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) -{ + +template +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) +{ this->set_up_containers( sizes_in_following_directions ); size_t number_of_top_dimensional_elements = 1; @@ -523,22 +634,22 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells size_t index = 0; for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) { - (*it) = top_dimensional_cells[index]; + this->get_cell_data(*it) = top_dimensional_cells[index]; ++index; } - this->impose_lower_star_filtration(); -} + this->impose_lower_star_filtration(); +} template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base ( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) { this->setup_bitmap_based_on_top_dimensional_cells_list( sizes_in_following_directions , top_dimensional_cells ); -} - -template -void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) -{ +} + +template +void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) +{ bool dbg = false; ifstream inFiltration, inIds; inFiltration.open( perseus_style_file ); @@ -547,7 +658,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;getchar();} - std::vector sizes; + std::vector sizes; sizes.reserve( dimensionOfData ); for ( size_t i = 0 ; i != dimensionOfData ; ++i ) { @@ -564,7 +675,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu while ( !inFiltration.eof() ) { - double filtrationLevel; + T filtrationLevel; inFiltration >> filtrationLevel; if ( dbg ) { @@ -574,35 +685,35 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) << " get the value : " << filtrationLevel << endl; } - *it = filtrationLevel; + this->get_cell_data(*it) = filtrationLevel; ++it; } inFiltration.close(); - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->read_perseus_style_file( perseus_style_file ); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->set_up_containers( sizes ); -} - -template + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->read_perseus_style_file( perseus_style_file ); +} + +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->set_up_containers( sizes ); +} + +template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); +{ + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); } template @@ -615,29 +726,29 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const { - std::vector< size_t > boundary_elements; - - //Speed traded of for memory. Check if it is better in practice. - boundary_elements.reserve( this->dimension()*2 ); + std::vector< size_t > boundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + boundary_elements.reserve( this->dimension()*2 ); size_t cell1 = cell; for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) { unsigned position = cell1/this->multipliers[i-1]; if ( position%2 == 1 ) - { - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); + { + boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); } cell1 = cell1%this->multipliers[i-1]; } return boundary_elements; -} - - - +} + + + template std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const { @@ -662,8 +773,8 @@ std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( cell1 = cell1%this->multipliers[i-1]; } return coboundary_elements; -} - +} + @@ -712,14 +823,14 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() //this vector will be used to check which elements have already been taken care of //in imposing lower star filtration: std::vector is_this_cell_considered( this->data.size() , false ); - - size_t size_to_reserve = 1; - for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) - { - size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); - } - - std::vector indices_to_consider; + + size_t size_to_reserve = 1; + for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) + { + size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); + } + + std::vector indices_to_consider; indices_to_consider.reserve( size_to_reserve ); //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. @@ -745,20 +856,20 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) - { - if ( dbg ) - { - cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; - getchar(); - + { + if ( dbg ) + { + cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; + getchar(); + } if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) { - this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; - if ( dbg ) - { - cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; - getchar(); + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + if ( dbg ) + { + cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; + getchar(); } } if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) @@ -797,4 +908,4 @@ bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , ch } -} +} diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 8c1254db..9a5ef0eb 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -121,7 +121,7 @@ void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_comp size_t i = 0; for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) { - *it = topDimensionalCells[i]; + this->get_cell_data(*it) = topDimensionalCells[i]; ++i; } this->impose_lower_star_filtration(); @@ -178,7 +178,7 @@ Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_comp << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) << " get the value : " << filtrationLevel << endl; } - *it = filtrationLevel; + this->get_cell_data(*it) = filtrationLevel; ++it; } inFiltration.close(); diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 968483a3..c1c846c9 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -95,13 +95,13 @@ BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { int i = 0; for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { - BOOST_CHECK(*it == expectedFiltrationValues2[i]); + BOOST_CHECK(increasing.get_cell_data(*it) == expectedFiltrationValues2[i]); ++i; } i = 0; for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { - BOOST_CHECK(*it == expectedFiltrationValues1[i]); + BOOST_CHECK(hole.get_cell_data(*it) == expectedFiltrationValues1[i]); ++i; } } @@ -884,3 +884,182 @@ BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) { BOOST_CHECK( filtration[i] == cmplx.get_cell_data(i) ); } } + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + for ( Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin() ; it != ba.all_cells_iterator_end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} -- cgit v1.2.3 From 79e0db96e6cf4def4df5cad902c44abcaa179ff8 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 17 Mar 2016 10:13:28 +0000 Subject: Add in a comment an alternative version of prune_above_filtration Fix some cpplint/cppcheck defaults git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1051 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9cfd8c7f7f9c82998a4c9d2d00f105ed16690208 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 46 ++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index ac5fbe79..b7b4b8b2 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -41,7 +41,6 @@ #include #endif -#include #include #include #include // for greater<> @@ -223,7 +222,7 @@ class Simplex_tree { * * 'value_type' is Simplex_handle. */ typedef typename Filtration_simplex_range::const_iterator Filtration_simplex_iterator; - + /* @} */ // end name range and iterator types /** \name Range and iterator methods * @{ */ @@ -455,7 +454,7 @@ class Simplex_tree { */ void assign_filtration(Simplex_handle sh, Filtration_value fv) { GUDHI_CHECK(sh == null_simplex(), - std::invalid_argument ("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex")); + std::invalid_argument("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex")); sh->second.assign_filtration(fv); } @@ -1119,7 +1118,7 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } - + public: /** \brief Browse the simplex tree to ensure the filtration is not decreasing. * The simplex tree is browsed starting from the root until the leaf, and the filtration values are set with their @@ -1139,7 +1138,7 @@ class Simplex_tree { } return modified; } - + private: /** \brief Recursively Browse the simplex tree to ensure the filtration is not decreasing. * @param[in] sib Siblings to be parsed. @@ -1183,7 +1182,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 @@ -1205,6 +1204,37 @@ class Simplex_tree { initialize_filtration(); } + /* + // Another alternative for prune_above_filtration + // Seg fault in this state + void prune_above_filtration(Filtration_value filt) { + if (!Options::store_filtration || filt >= filtration()) return; + rec_prune_above_filtration(root(), filt); + set_filtration(filt); + } + + private: + void rec_prune_above_filtration(Siblings* sib, Filtration_value filt) { + auto&& list=sib->members(); + auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) { + if (simplex.second.filtration()<=filt) return false; + if (has_children(&simplex)) rec_delete(simplex.second.children()); + return true; + }); + + if (last == list.begin() && sib != root()) { + // Removing the whole siblings, parent becomes a leaf. + sib->oncles()->members()[sib->parent()].assign_children(sib->oncles()); + delete sib; + } else { + // Keeping some elements of siblings. Remove the others, and recurse in the remaining ones. + list.erase(last, list.end()); + for(auto&& simplex : list) + if(has_children(&simplex)) + 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. @@ -1214,8 +1244,8 @@ class Simplex_tree { 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")); - + 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(); -- 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(-) 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(-) 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 10083c1ed5ae478b54b6bb1b17be3325838533fe Mon Sep 17 00:00:00 2001 From: pdlotko Date: Sun, 20 Mar 2016 17:41:52 +0000 Subject: answering Marc's comments git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1059 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2f0e6e894c0c48ffc80a0864f4a4992066fd2273 --- src/Bitmap_cubical_complex/example/CMakeLists.txt | 5 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 137 +++---- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 426 +++++++++++++++++++++ 3 files changed, 493 insertions(+), 75 deletions(-) diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index 14c94e8e..088e6fbd 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -14,4 +14,7 @@ add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubi target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) #add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) -#target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file +#target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) + +#add_executable ( periodic_boundary_conditions_phat periodic_boundary_conditions_phat.cpp ) +#target_link_libraries(periodic_boundary_conditions_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 6d2b705c..e081764c 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -161,96 +161,35 @@ public: } /** - * Writing to stream operator. + * Writing to stream operator. By using it we get the values T of cells in order in which they are stored in the structure. This procedure is used for debugging purposes. **/ template friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); /** - * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. + * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. **/ - void put_data_toBins( size_t number_of_bins ); + void put_data_to_bins( size_t number_of_bins ); /** - * Function that put the input data to bins. Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets + * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. + * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex * before and after using such a function will be bounded by the parameter diameter_of_bin. **/ - void put_data_toBins( T diameter_of_bin ); + void put_data_to_bins( T diameter_of_bin ); /** * Functions to find min and max values of filtration. **/ std::pair< T ,T > min_max_filtration(); - //ITERATORS - - /** - * Iterator through all cells in the complex (in order they appear in the structure -- i.e. - * in lexicographical order). - **/ - //typedef typename std::vector< T >::iterator all_cells_iterator; - - - /** - * Constant iterator through all cells in the complex (in order they appear in the structure -- i.e. - * in lexicographical order). - **/ - //typedef typename std::vector< T >::const_iterator all_cells_const_iterator; - - /** - * Function returning a constant iterator to the first cell of the bitmap. - **/ - //all_cells_const_iterator all_cells_const_begin()const - //{ - // return this->data.begin(); - //} - - - /** - * Function returning a constant iterator to the last cell of the bitmap. - **/ - //all_cells_const_iterator all_cells_const_end()const - //{ - // return this->data.end(); - //} - - /** - * Function returning an iterator to the first cell of the bitmap. - **/ - //all_cells_iterator all_cells_begin() - //{ - // return this->data.begin(); - //} - - /** - * Function returning a constant iterator to the first cell of the bitmap. - **/ - //all_cells_const_iterator all_cells_begin() const - //{ - // return this->data.begin(); - //} - - /** - * Function returning an iterator to the last cell of the bitmap. - **/ - //all_cells_iterator all_cells_end() - //{ - // return this->data.end(); - //} - - /** - * Function returning a constant iterator to the last cell of the bitmap. - **/ - //all_cells_const_iterator all_cells_end() const - //{ - // return this->data.end(); - //} - + //ITERATORS /** * Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). @@ -288,7 +227,12 @@ public: { return !(*this == rhs); } - + + /* + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * and in function get_cell_data to get a filtration of a cell. + */ size_t operator*() { return this->counter; @@ -317,10 +261,31 @@ public: return a; } + + /** + * All_cells_iterator_range class provides ranges for All_cells_iterator + **/ + class All_cells_iterator_range + { + public: + All_cells_iterator_range(Bitmap_cubical_complex_base* b):b(b){}; + All_cells_iterator begin() + { + return b->all_cells_iterator_begin(); + } + All_cells_iterator end() + { + return b->all_cells_iterator_end(); + } + private: + Bitmap_cubical_complex_base* b; + }; + + /** * Boundary_range class provides ranges for boundary iterators. **/ - typedef typename std::vector< size_t >::iterator Boundary_iterator; + typedef typename std::vector< size_t >::const_iterator Boundary_iterator; typedef typename std::vector< size_t > Boundary_range; /** @@ -424,6 +389,11 @@ public: // return this->b.data[index]; //} + /* + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * and in function get_cell_data to get a filtration of a cell. + */ size_t operator*() { return this->compute_index_in_bitmap(); @@ -474,7 +444,26 @@ public: } a.counter[0]++; return a; - } + } + + /** + * All_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range + **/ + class Top_dimensional_cells_iterator_range + { + public: + Top_dimensional_cells_iterator_range(Bitmap_cubical_complex_base* b):b(b){}; + Top_dimensional_cells_iterator begin() + { + return b->top_dimensional_cells_begin(); + } + Top_dimensional_cells_iterator end() + { + return b->top_dimensional_cells_end(); + } + private: + Bitmap_cubical_complex_base* b; + }; //****************************************************************************************************************// @@ -542,7 +531,7 @@ protected: template -void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) +void Bitmap_cubical_complex_base::put_data_to_bins( size_t number_of_bins ) { bool bdg = false; @@ -559,7 +548,7 @@ void Bitmap_cubical_complex_base::put_data_toBins( size_t number_of_bins ) } template -void Bitmap_cubical_complex_base::put_data_toBins( T diameter_of_bin ) +void Bitmap_cubical_complex_base::put_data_to_bins( T diameter_of_bin ) { bool bdg = false; std::pair< T ,T > min_max = this->min_max_filtration(); diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index c1c846c9..b7a1c8b6 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -1063,3 +1063,429 @@ BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical ++i; } } + + + + + + + + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check_2) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + + Bitmap_cubical_complex_base::All_cells_iterator_range range(&ba); + for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + + + + + + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + + Bitmap_cubical_complex_base::All_cells_iterator_range range(&ba); + for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + +BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator_range range(&ba); + for ( Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( data[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( ba.get_dimension_of_a_cell( *it ) == 2 ); + ++i; + } +} -- cgit v1.2.3 From ffc9ea770f2fb5710cae669c20ec0f009197a8a2 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 21 Mar 2016 08:10:50 +0000 Subject: fix #include "gudhi/Simplex_tree.h" in generated doc git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1062 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f7d2fad28cb01ea0970b63d695f53ec9e65723c3 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 53f6fec7..bea62de6 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -86,6 +86,7 @@ namespace Gudhi { struct Simplex_tree_options_full_featured; /** + * \class Simplex_tree Simplex_tree.h gudhi/Simplex_tree.h * \brief Simplex Tree data structure for representing simplicial complexes. * * \details Every simplex \f$[v_0, \cdots ,v_d]\f$ admits a canonical orientation -- cgit v1.2.3 From 04c63ee74520c966451b0cb1713df8b3e9ca5bfb Mon Sep 17 00:00:00 2001 From: pdlotko Date: Mon, 21 Mar 2016 08:21:22 +0000 Subject: Answers to comments. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1063 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 99cebe0573d75c98c8559ae4572b8f510e5cd9c0 --- .../include/gudhi/Bitmap_cubical_complex_base.h | 46 +++++++++++++--------- ...cal_complex_periodic_boundary_conditions_base.h | 6 +-- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 10 ++--- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index e081764c..f0517a86 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -170,7 +170,7 @@ public: /** * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( size_t number_of_bins ) + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_to_bins( size_t number_of_bins ) * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. **/ void put_data_to_bins( size_t number_of_bins ); @@ -178,7 +178,7 @@ public: /** * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_toBins( T diameter_of_bin ) is + * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_to_bins( T diameter_of_bin ) is * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex * before and after using such a function will be bounded by the parameter diameter_of_bin. **/ @@ -263,12 +263,12 @@ public: /** - * All_cells_iterator_range class provides ranges for All_cells_iterator + * All_cells_range class provides ranges for All_cells_iterator **/ - class All_cells_iterator_range + class All_cells_range { public: - All_cells_iterator_range(Bitmap_cubical_complex_base* b):b(b){}; + All_cells_range(Bitmap_cubical_complex_base* b):b(b){}; All_cells_iterator begin() { return b->all_cells_iterator_begin(); @@ -279,7 +279,12 @@ public: } private: Bitmap_cubical_complex_base* b; - }; + }; + + All_cells_range all_cells_range() + { + return All_cells_range(this); + } /** @@ -300,7 +305,7 @@ public: /** * Coboundary_range class provides ranges for boundary iterators. **/ - typedef typename std::vector< size_t >::iterator Coboundary_iterator; + typedef typename std::vector< size_t >::const_iterator Coboundary_iterator; typedef typename std::vector< size_t > Coboundary_range; /** @@ -426,7 +431,7 @@ public: /** * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap. **/ - Top_dimensional_cells_iterator top_dimensional_cells_begin() + Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin() { Top_dimensional_cells_iterator a(*this); return a; @@ -435,7 +440,7 @@ public: /** * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap. **/ - Top_dimensional_cells_iterator top_dimensional_cells_end() + Top_dimensional_cells_iterator top_dimensional_cells_iterator_end() { Top_dimensional_cells_iterator a(*this); for ( size_t i = 0 ; i != this->dimension() ; ++i ) @@ -447,23 +452,28 @@ public: } /** - * All_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range + * Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range **/ - class Top_dimensional_cells_iterator_range + class Top_dimensional_cells_range { public: - Top_dimensional_cells_iterator_range(Bitmap_cubical_complex_base* b):b(b){}; + Top_dimensional_cells_range(Bitmap_cubical_complex_base* b):b(b){}; Top_dimensional_cells_iterator begin() { - return b->top_dimensional_cells_begin(); + return b->top_dimensional_cells_iterator_begin(); } Top_dimensional_cells_iterator end() { - return b->top_dimensional_cells_end(); + return b->top_dimensional_cells_iterator_end(); } private: Bitmap_cubical_complex_base* b; - }; + }; + + Top_dimensional_cells_range top_dimensional_cells_range() + { + return Top_dimensional_cells_range(this); + } //****************************************************************************************************************// @@ -621,7 +631,7 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); size_t index = 0; - for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + for ( it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) { this->get_cell_data(*it) = top_dimensional_cells[index]; ++index; @@ -660,7 +670,7 @@ void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseu this->set_up_containers( sizes ); Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_begin(); + it = this->top_dimensional_cells_iterator_begin(); while ( !inFiltration.eof() ) { @@ -824,7 +834,7 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() //we assume here that we already have a filtration on the top dimensional cells and //we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - for ( it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + for ( it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) { indices_to_consider.push_back( it.compute_index_in_bitmap() ); } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 9a5ef0eb..956e74a7 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -119,7 +119,7 @@ void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_comp this->set_up_containers( dimensions ); size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) { this->get_cell_data(*it) = topDimensionalCells[i]; ++i; @@ -162,7 +162,7 @@ Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_comp this->set_up_containers( sizes ); typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_begin(); + it = this->top_dimensional_cells_iterator_begin(); while ( !inFiltration.eof() ) { @@ -230,7 +230,7 @@ Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_comp this->set_up_containers( sizes ); size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_begin() ; it != this->top_dimensional_cells_end() ; ++it ) + for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) { *it = data[i]; ++i; diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index b7a1c8b6..35c54ade 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -94,13 +94,13 @@ BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { int i = 0; for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator - it = increasing.top_dimensional_cells_begin(); it != increasing.top_dimensional_cells_end(); ++it) { + it = increasing.top_dimensional_cells_iterator_begin(); it != increasing.top_dimensional_cells_iterator_end(); ++it) { BOOST_CHECK(increasing.get_cell_data(*it) == expectedFiltrationValues2[i]); ++i; } i = 0; for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator - it = hole.top_dimensional_cells_begin(); it != hole.top_dimensional_cells_end(); ++it) { + it = hole.top_dimensional_cells_iterator_begin(); it != hole.top_dimensional_cells_iterator_end(); ++it) { BOOST_CHECK(hole.get_cell_data(*it) == expectedFiltrationValues1[i]); ++i; } @@ -1229,7 +1229,7 @@ BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical int bd_it = 0; int cbd_it = 0; - Bitmap_cubical_complex_base::All_cells_iterator_range range(&ba); + Bitmap_cubical_complex_base::All_cells_range range(&ba); for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) { BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); @@ -1415,7 +1415,7 @@ BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical int bd_it = 0; int cbd_it = 0; - Bitmap_cubical_complex_base::All_cells_iterator_range range(&ba); + Bitmap_cubical_complex_base::All_cells_range range = ba.all_cells_range(); for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) { BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); @@ -1481,7 +1481,7 @@ BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check) Bitmap_cubical_complex_base ba( sizes , data ); int i = 0; - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator_range range(&ba); + Bitmap_cubical_complex_base::Top_dimensional_cells_range range = ba.top_dimensional_cells_range(); for ( Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin() ; it != range.end() ; ++it ) { BOOST_CHECK( data[i] == ba.get_cell_data( *it ) ); -- cgit v1.2.3 From 806bdf8fad13eaf48e8dc55f123645b15b285620 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 21 Mar 2016 14:44:32 +0000 Subject: Add titles for Persistence diagram git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1065 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 27e728ca0b06af56ca9cb3824938f67f897a80ae --- src/Persistent_cohomology/doc/3DTorus_poch.png | Bin 33733 -> 40164 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/Persistent_cohomology/doc/3DTorus_poch.png b/src/Persistent_cohomology/doc/3DTorus_poch.png index 293c1b8c..1c9d8328 100644 Binary files a/src/Persistent_cohomology/doc/3DTorus_poch.png and b/src/Persistent_cohomology/doc/3DTorus_poch.png differ -- 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(-) 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(-) 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(-) 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(-) 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 73d8be19b7834f500e38f7304fd01e0e641ef018 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 23 Mar 2016 23:04:43 +0000 Subject: An alternative to prune_above_filtration in comment. Fix UT for alternative git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1072 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1958a5ee06c339d8cd8cdaae92358d2fff445a7a --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index af298f33..1bad8d7d 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1219,37 +1219,39 @@ class Simplex_tree { return (simplex_list_to_removed.size() > 0); } - /* + // Another alternative for prune_above_filtration - // 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); - set_filtration(filt); + // UT are passed and performance are similar. + /*bool prune_above_filtration(Filtration_value filt) { + return rec_prune_above_filtration(root(), filt); } private: - void rec_prune_above_filtration(Siblings* sib, Filtration_value filt) { + bool rec_prune_above_filtration(Siblings* sib, Filtration_value filt) { auto&& list=sib->members(); auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) { - if (simplex.second.filtration()<=filt) return false; - if (has_children(&simplex)) rec_delete(simplex.second.children()); - return true; + if (simplex.second.filtration()<=filt) return false; + if (has_children(&simplex)) rec_delete(simplex.second.children()); + return true; }); - + + bool modified = (last != list.end()); if (last == list.begin() && sib != root()) { // Removing the whole siblings, parent becomes a leaf. sib->oncles()->members()[sib->parent()].assign_children(sib->oncles()); delete sib; + return true; } else { // Keeping some elements of siblings. Remove the others, and recurse in the remaining ones. list.erase(last, list.end()); for(auto&& simplex : list) if(has_children(&simplex)) - rec_prune_above_filtration(simplex.second.children(), filt); + modified |= rec_prune_above_filtration(simplex.second.children(), filt); } + return modified; }*/ + public: /** \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. -- 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(-) 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 d1a3b2267b7e638b5d868720cf46987641b22132 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 29 Mar 2016 16:05:12 +0000 Subject: Merge VR_bitmap git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1074 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4c9ac225ffcfb924371c72fccc44cbd6ecb3d6e3 --- .../doc/Gudhi_Cubical_Complex_doc.h | 160 +- .../example/Bitmap_cubical_complex.cpp | 107 +- ...ubical_complex_periodic_boundary_conditions.cpp | 134 +- src/Bitmap_cubical_complex/example/CMakeLists.txt | 11 +- .../example/Random_bitmap_cubical_complex.cpp | 159 +- .../include/gudhi/Bitmap_cubical_complex.h | 1060 +++++------ .../include/gudhi/Bitmap_cubical_complex_base.h | 1499 ++++++++-------- ...cal_complex_periodic_boundary_conditions_base.h | 625 +++---- src/Bitmap_cubical_complex/test/Bitmap_test.cpp | 1837 +++++++++----------- 9 files changed, 2663 insertions(+), 2929 deletions(-) diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index 00b39f01..cde0b2fc 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -21,64 +21,87 @@ */ -#pragma once +#ifndef DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_ +#define DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_ -namespace Gudhi -{ +namespace Gudhi { -namespace Cubical_complex -{ +namespace Cubical_complex { /** \defgroup cubical_complex Cubical complex -* -* \author Pawel Dlotko -* -* @{ -* - -*Bitmap_cubical_complex is an example of a structured complex useful in computational mathematics (specially rigorous numerics) and image analysis. The presented implementation of cubical complexes is based on the following definition. -* -* An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} \f$. The first one is called non-degenerate, while the second one is \a degenerate interval. A boundary of a elementary -*interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of non-degenerate elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An elementary cube \f$ C \f$ is a + * + * \author Pawel Dlotko + * + * @{ + * -*product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. Embedding dimension of a cube is n, the number of elementary intervals (degenerate or not) in the product. A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the -*number of non degenerate elementary intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained in the following way: -*\f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f] -*A cubical complex \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex \f$\mathcal{K}\f$ is maximal if it is not in -*a boundary of any other cube in \f$\mathcal{K}\f$. A \a support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension of \f$C\f$). -* -*Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may be a set of two elements). -* -*For further details and theory of cubical complexes, please consult \cite kaczynski2004computational as well as the following paper \cite peikert2012topological . -* -*\section datastructure Data structure. -* -*The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in \f$\mathbb{R}^n\f$. This extra -*assumption allows for a memory efficient way of storing cubical complexes in a form of so called bitmaps. Let \f$R = [b_1,e_1] \times \ldots \times [b_n,e_n]\f$, for \f$b_1,...b_n,e_1,...,e_n \in \mathbb{Z}\f$ -*, \f$b_i \leq d_i\f$ be the considered rectangular region and let \f$\mathcal{K}\f$ be a filtered cubical complex having the rectangle \f$R\f$ as its support. Note that the structure of the coordinate system gives a way -*a lexicographical ordering of cells of \f$\mathcal{K}\f$. This ordering is a base of the presented bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector -*of the values of filtration. This, together with dimension of \f$\mathcal{K}\f$ and the sizes of \f$\mathcal{K}\f$ in all directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube \f$C \in \mathcal{K}\f$. -* -*\image html "bitmapAllCubes.png" "Cubical complex. -* -*Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical complexes in \f$\mathbb{R}\f$. The number of all cubes in each direction is -*equal \f$2n+1\f$, where \f$n\f$ is the number of maximal cubes in the considered direction. Let us consider a cube at the position \f$k\f$ in the bitmap. Knowing the sizes of the bitmap, -*by a series of modulo operation, we can determine which elementary intervals are present in the product that gives the cube \f$C\f$. In a similar way, we can compute boundary -*and the coboundary of each cube. Further details can be found in the literature. -* -*\section inputformat Input Format. -* -*In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors -*that can be used to construct cubical complex by users who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. -*Currently one input from a text file is used. It uses a format used already in Perseus software (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. -*Below we are providing a description of the format. The first line contains a number d begin the dimension of the bitmap (2 in the example below). Next d lines are the numbers of -*top dimensional cubes in each dimensions (3 and 3 in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8 20 4 7 6 5 in the example below). -* -* -*\image html "exampleBitmap.png" "Example of a input data." -* -*The input file for the following complex is: -*\verbatim + * Bitmap_cubical_complex is an example of a structured complex useful in computational mathematics (specially rigorous + * numerics) and image analysis. The presented implementation of cubical complexes is based on the following + * definition. + * + * An elementary interval is an interval of a form \f$ [n,n+1] \f$, or \f$[n,n]\f$, for \f$ n \in \mathcal{Z} + * \f$. The first one is called non-degenerate, while the second one is \a degenerate interval. A + * boundary of a elementary interval is a chain \f$\partial [n,n+1] = [n+1,n+1]-[n,n] \f$ in case of + * non-degenerated elementary interval and \f$\partial [n,n] = 0 \f$ in case of degenerate elementary interval. An + * elementary cube \f$ C \f$ is a product of elementary intervals, \f$C=I_1 \times \ldots \times I_n\f$. + * Embedding dimension of a cube is n, the number of elementary intervals (degenerate or not) in the product. + * A dimension of a cube \f$C=I_1 \times ... \times I_n\f$ is the number of non degenerate elementary + * intervals in the product. A boundary of a cube \f$C=I_1 \times \ldots \times I_n\f$ is a chain obtained + * in the following way: + * \f[\partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + + * \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n).\f] + * A cubical complex \f$\mathcal{K}\f$ is a collection of cubes closed under operation of taking boundary + * (i.e. boundary of every cube from the collection is in the collection). A cube \f$C\f$ in cubical complex + * \f$\mathcal{K}\f$ is maximal if it is not in a boundary of any other cube in \f$\mathcal{K}\f$. A \a + * support of a cube \f$C\f$ is the set in \f$\mathbb{R}^n\f$ occupied by \f$C\f$ (\f$n\f$ is the embedding dimension + * of \f$C\f$). + * + * Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical + * complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may + * be a set of two elements). + * + * For further details and theory of cubical complexes, please consult \cite kaczynski2004computational as well as the + * following paper \cite peikert2012topological . + * + * \section datastructure Data structure. + * + * The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in + * \f$\mathbb{R}^n\f$. This extra assumption allows for a memory efficient way of storing cubical complexes in a form + * of so called bitmaps. Let \f$R = [b_1,e_1] \times \ldots \times [b_n,e_n]\f$, for \f$b_1,...b_n,e_1,...,e_n \in + * \mathbb{Z}\f$, \f$b_i \leq d_i\f$ be the considered rectangular region and let \f$\mathcal{K}\f$ be a filtered + * cubical complex having the rectangle \f$R\f$ as its support. Note that the structure of the coordinate system gives + * a way a lexicographical ordering of cells of \f$\mathcal{K}\f$. This ordering is a base of the presented + * bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector of the values + * of filtration. This, together with dimension of \f$\mathcal{K}\f$ and the sizes of \f$\mathcal{K}\f$ in all + * directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube \f$C \in + * \mathcal{K}\f$. + * + * \image html "bitmapAllCubes.png" "Cubical complex. + * + * Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical + * complexes in \f$\mathbb{R}\f$. The number of all cubes in each direction is equal \f$2n+1\f$, where \f$n\f$ is the + * number of maximal cubes in the considered direction. Let us consider a cube at the position \f$k\f$ in the bitmap. + * Knowing the sizes of the bitmap, by a series of modulo operation, we can determine which elementary intervals are + * present in the product that gives the cube \f$C\f$. In a similar way, we can compute boundary and the coboundary of + * each cube. Further details can be found in the literature. + * + * \section inputformat Input Format. + * + * In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star + * filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users + * who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. + * Currently one input from a text file is used. It uses a format used already in Perseus software + * (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. + * Below we are providing a description of the format. The first line contains a number d begin the dimension of the + * bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each dimensions (3 and 3 + * in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8 + * 20 4 7 6 5 in the example below). + * + * + * \image html "exampleBitmap.png" "Example of a input data." + * + * The input file for the following complex is: + * \verbatim 2 3 3 @@ -93,15 +116,17 @@ namespace Cubical_complex 5 \endverbatim -\section PeriodicBoundaryConditions Periodic boundary conditions -Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times I_n \f$ be a box -that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary conditions in the direction i, means that the left and the right side of a complex -\f$ \mathcal{K} \f$ are considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed in all directions, then complex -\f$ \mathcal{K} \f$ became n-dimensional torus. One can use various constructors from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical -complex with periodic boundary conditions. One can also use Perseus style input files. To indicate periodic boundary conditions in a given direction, then number of top dimensional cells -in this direction have to be multiplied by -1. For instance: + * \section PeriodicBoundaryConditions Periodic boundary conditions + * Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times + * I_n \f$ be a box that is decomposed with a cubical complex \f$ \mathcal{K} \f$. Imposing periodic boundary + * conditions in the direction i, means that the left and the right side of a complex \f$ \mathcal{K} \f$ are + * considered the same. In particular, if for a bitmap \f$ \mathcal{K} \f$ periodic boundary conditions are imposed + * in all directions, then complex \f$ \mathcal{K} \f$ became n-dimensional torus. One can use various constructors + * from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical complex with periodic + * boundary conditions. One can also use Perseus style input files. To indicate periodic boundary conditions in a + * given direction, then number of top dimensional cells in this direction have to be multiplied by -1. For instance: -*\verbatim + *\verbatim 2 -3 3 @@ -116,15 +141,16 @@ in this direction have to be multiplied by -1. For instance: 5 \endverbatim -Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. + * Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. * \section BitmapExamples Examples * End user programs are available in example/Bitmap_cubical_complex folder. - -*/ + */ /** @} */ // end defgroup cubical_complex -*@}//end of the group -} -} +} // namespace Cubical_complex + +} // namespace Gudhi + +#endif // DOC_GUDHI_CUBICAL_COMPLEX_COMPLEX_H_ diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp index 4c30ee85..7c7e8ac5 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex.cpp @@ -1,73 +1,72 @@ - /* 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): Pawel Dlotko - * - * 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 . - */ +/* 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): Pawel Dlotko + * + * 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 -#include #include #include - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include #include -using namespace std; +int main(int argc, char** argv) { + std::cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical " << + "complexes provided in text files in Perseus style (the only numbered in the first line is a dimension D of a" << + "bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let " << + "N denote product of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are " << + "filtrations of top dimensional cells. We assume that the cells are in the lexicographical order. See " << + "CubicalOneSphere.txt or CubicalTwoSphere.txt for example.\n" << std::endl; + int p = 2; + double min_persistence = 0; -int main( int argc , char** argv ) -{ - cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; + if (argc != 2) { + std::cerr << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at " << + "the input. The program will now terminate.\n"; + return 1; + } - int p = 2; - double min_persistence = 0; + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_base Bitmap_cubical_complex_base; + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex Bitmap_cubical_complex; + typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp; + typedef Gudhi::persistent_cohomology::Persistent_cohomology Persistent_cohomology; - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } + Bitmap_cubical_complex b(argv[1]); - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( argv[1] ); + // Compute the persistence diagram of the complex + Persistent_cohomology pcoh(b); + pcoh.init_coefficients(p); // initializes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology + std::stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out(ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); - pcoh.compute_persistent_cohomology( min_persistence ); + std::cout << "Result in file: " << ss.str().c_str() << "\n"; - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 0; + return 0; } + diff --git a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp index df01240b..2c5d7fd3 100644 --- a/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp +++ b/src/Bitmap_cubical_complex/example/Bitmap_cubical_complex_periodic_boundary_conditions.cpp @@ -1,24 +1,24 @@ - /* 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): Pawel Dlotko - * - * 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 . - */ +/* 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): Pawel Dlotko + * + * 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 @@ -26,59 +26,49 @@ #include #include -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include #include -using namespace std; - -int main( int argc , char** argv ) -{ - clock_t beginOfProgram = clock(); - - cout << "This program computes persistent homology, by using Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in Perseus style (the only numbered in \ -the first line is a dimension D of a bitmap. In the lines I between 2 and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product \ -of the numbers in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We assume that the cells are in the \ -lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for example." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc != 2 ) - { - cout << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at the input. The program will now terminate.\n"; - return 1; - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > b( argv[1] ); - - cerr << "Here \n"; - - clock_t endCreateBitmap = clock(); - double elapsed_secsCreateBitmap = double(endCreateBitmap - beginOfProgram) / CLOCKS_PER_SEC; - cerr << "Time of creation of bitmap : " << elapsed_secsCreateBitmap << endl; - - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base >, Field_Zp > pcoh(b,true); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - - - stringstream ss; - ss << argv[1] << "_persistence"; - std::ofstream out((char*)ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - clock_t endOfProgram = clock(); - double elapsed_secsOfProgram = double(endOfProgram - beginOfProgram) / CLOCKS_PER_SEC; - cerr << "Overall execution time : " << elapsed_secsOfProgram << endl; - return 0; +int main(int argc, char** argv) { + std::cout << "This program computes persistent homology, by using " << + "Bitmap_cubical_complex_periodic_boundary_conditions class, of cubical complexes provided in text files in " << + "Perseus style (the only numbered in the first line is a dimension D of a bitmap. In the lines I between 2 " << + "and D+1 there are numbers of top dimensional cells in the direction I. Let N denote product of the numbers " << + "in the lines between 2 and D. In the lines D+2 to D+2+N there are filtrations of top dimensional cells. We " << + "assume that the cells are in the lexicographical order. See CubicalOneSphere.txt or CubicalTwoSphere.txt for" << + " example.\n" << std::endl; + + int p = 2; + double min_persistence = 0; + + if (argc != 2) { + std::cerr << "Wrong number of parameters. Please provide the name of a file with a Perseus style bitmap at " << + "the input. The program will now terminate.\n"; + return 1; + } + + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base Bitmap_base; + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex< Bitmap_base > Bitmap_cubical_complex; + + Bitmap_cubical_complex b(argv[1]); + + typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp; + typedef Gudhi::persistent_cohomology::Persistent_cohomology Persistent_cohomology; + // Compute the persistence diagram of the complex + Persistent_cohomology pcoh(b, true); + pcoh.init_coefficients(p); // initializes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); + + std::stringstream ss; + ss << argv[1] << "_persistence"; + std::ofstream out(ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + std::cout << "Result in file: " << ss.str().c_str() << "\n"; + + return 0; } + diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index 088e6fbd..8f9cfa80 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -3,8 +3,8 @@ project(GUDHIBitmap) add_executable ( Bitmap_cubical_complex Bitmap_cubical_complex.cpp ) target_link_libraries(Bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) -add_test(Bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalOneSphere.txt) -add_test(Bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) +add_test(Bitmap_cubical_complex_one_sphere ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalOneSphere.txt) +add_test(Bitmap_cubical_complex_two_sphere ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) add_executable ( Random_bitmap_cubical_complex Random_bitmap_cubical_complex.cpp ) target_link_libraries(Random_bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) @@ -12,9 +12,6 @@ add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp ) target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) +add_test(Bitmap_cubical_complex_periodic_2d_torus ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex_periodic_boundary_conditions ${CMAKE_SOURCE_DIR}/data/bitmap/2d_torus.txt) +add_test(Bitmap_cubical_complex_periodic_3d_torus ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex_periodic_boundary_conditions ${CMAKE_SOURCE_DIR}/data/bitmap/3d_torus.txt) -#add_executable ( Compute_persistence_with_phat Compute_persistence_with_phat.cpp ) -#target_link_libraries(Compute_persistence_with_phat ${Boost_SYSTEM_LIBRARY}) - -#add_executable ( periodic_boundary_conditions_phat periodic_boundary_conditions_phat.cpp ) -#target_link_libraries(periodic_boundary_conditions_phat ${Boost_SYSTEM_LIBRARY}) \ No newline at end of file diff --git a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp index 8b7f6a04..416ad8f2 100644 --- a/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp +++ b/src/Bitmap_cubical_complex/example/Random_bitmap_cubical_complex.cpp @@ -1,94 +1,83 @@ - /* 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): Pawel Dlotko - * - * 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 . - */ - - -//for persistence algorithm +/* 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): Pawel Dlotko + * + * 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 . + */ + + +// for persistence algorithm #include #include #include - -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; - -//standard stuff +// standard stuff #include #include #include -using namespace std; - -int main( int argc , char** argv ) -{ - srand( time(0) ); - - cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical complexes. \ -The first parameter of the program is the dimension D of the bitmap. \ -The next D parameters are number of top dimensional cubes in each dimension of the bitmap.\ -The program will create random cubical complex of that sizes and compute persistent homology of it." << endl; - - int p = 2; - double min_persistence = 0; - - if ( argc < 3 ) - { - cerr << "Wrong number of parameters, the program will now terminate\n"; - return 1; - } - - size_t dimensionOfBitmap = (size_t)atoi( argv[1] ); - std::vector< unsigned > sizes; - size_t multipliers = 1; - for ( size_t dim = 0 ; dim != dimensionOfBitmap ; ++dim ) - { - unsigned sizeInThisDimension = (unsigned)atoi( argv[2+dim] ); - sizes.push_back( sizeInThisDimension ); - multipliers *= sizeInThisDimension; - } - - std::vector< double > data; - for ( size_t i = 0 ; i != multipliers ; ++i ) - { - data.push_back( rand()/(double)RAND_MAX ); - } - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > b( sizes , data ); - - - - - - // Compute the persistence diagram of the complex - persistent_cohomology::Persistent_cohomology< Bitmap_cubical_complex< Bitmap_cubical_complex_base >, Field_Zp > pcoh(b); - pcoh.init_coefficients( p ); //initilizes the coefficient field for homology - pcoh.compute_persistent_cohomology( min_persistence ); - - - stringstream ss; - ss << "randomComplex_persistence"; - std::ofstream out(ss.str().c_str()); - pcoh.output_diagram(out); - out.close(); - - return 0; +int main(int argc, char** argv) { + srand(time(0)); + + std::cout << "This program computes persistent homology, by using bitmap_cubical_complex class, of cubical " << + "complexes. The first parameter of the program is the dimension D of the bitmap. The next D parameters are " << + "number of top dimensional cubes in each dimension of the bitmap. The program will create random cubical " << + "complex of that sizes and compute persistent homology of it." << std::endl; + + int p = 2; + double min_persistence = 0; + + if (argc < 3) { + std::cerr << "Wrong number of parameters, the program will now terminate\n"; + return 1; + } + + size_t dimensionOfBitmap = (size_t) atoi(argv[1]); + std::vector< unsigned > sizes; + size_t multipliers = 1; + for (size_t dim = 0; dim != dimensionOfBitmap; ++dim) { + unsigned sizeInThisDimension = (unsigned) atoi(argv[2 + dim]); + sizes.push_back(sizeInThisDimension); + multipliers *= sizeInThisDimension; + } + + std::vector< double > data; + for (size_t i = 0; i != multipliers; ++i) { + data.push_back(rand() / static_cast(RAND_MAX)); + } + + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_base Bitmap_cubical_complex_base; + typedef Gudhi::Cubical_complex::Bitmap_cubical_complex Bitmap_cubical_complex; + Bitmap_cubical_complex b(sizes, data); + + // Compute the persistence diagram of the complex + typedef Gudhi::persistent_cohomology::Field_Zp Field_Zp; + typedef Gudhi::persistent_cohomology::Persistent_cohomology Persistent_cohomology; + Persistent_cohomology pcoh(b); + pcoh.init_coefficients(p); // initializes the coefficient field for homology + pcoh.compute_persistent_cohomology(min_persistence); + + std::stringstream ss; + ss << "randomComplex_persistence"; + std::ofstream out(ss.str().c_str()); + pcoh.output_diagram(out); + out.close(); + + return 0; } + diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 4dd295e7..1fd36914 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -20,28 +20,28 @@ * along with this program. If not, see . */ +#ifndef BITMAP_CUBICAL_COMPLEX_H_ +#define BITMAP_CUBICAL_COMPLEX_H_ -#pragma once -#include -#include -#include "Bitmap_cubical_complex_base.h" -#include "Bitmap_cubical_complex_periodic_boundary_conditions_base.h" - +#include +#include +#include +#include // for pair<> +#include // for sort +#include -namespace Gudhi -{ +namespace Gudhi { -namespace Cubical_complex -{ +namespace Cubical_complex { -//global variable, was used just for debugging. +// global variable, was used just for debugging. const bool globalDbg = false; -template class is_before_in_filtration; - +template class is_before_in_filtration; + /** -* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into +* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into * Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex_base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. **/ @@ -51,529 +51,533 @@ template class is_before_in_filtration; *@ingroup cubical_complex */ template -class Bitmap_cubical_complex : public T -{ -public: -//*********************************************// -//Typedefs and typenames -//*********************************************// - typedef size_t Simplex_key; - typedef typename T::filtration_type Filtration_value; - typedef Simplex_key Simplex_handle; - - -//*********************************************// -//Constructors -//*********************************************// - //Over here we need to definie various input types. I am proposing the following ones: - //Perseus style - //H5 files? TODO - //binary files with little endiangs / big endians? TODO - //constructor from a vector of elements of a type T. TODO - - /** - * Constructor form a Perseus-style file. - **/ - Bitmap_cubical_complex( const char* perseus_style_file ): - T(perseus_style_file),key_associated_to_simplex(this->total_number_of_cells+1) - { - //clock_t begin = clock(); - if ( globalDbg ){cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";} - for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) - { - this->key_associated_to_simplex[i] = i; - } - //we initialize this only once, in each constructor, when the bitmap is constructed. - //If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. - this->initialize_simplex_associated_to_key(); - //cerr << "Time of running Bitmap_cubical_complex( const char* perseus_style_file ) constructor : " << double(clock() - begin) / CLOCKS_PER_SEC << endl; - } - - - /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells - * in the following directions and vector of element of a type T - * with filtration on top dimensional cells. - **/ - Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells ): - T(dimensions,top_dimensional_cells), - key_associated_to_simplex(this->total_number_of_cells+1) - { - for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) - { - this->key_associated_to_simplex[i] = i; - } - //we initialize this only once, in each constructor, when the bitmap is constructed. - //If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. - this->initialize_simplex_associated_to_key(); - } - - /** - * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells - * in the following directions and vector of element of a type T::filtration_type - * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. - * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. - **/ - Bitmap_cubical_complex( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed ): - T(dimensions,top_dimensional_cells,directions_in_which_periodic_b_cond_are_to_be_imposed), - key_associated_to_simplex(this->total_number_of_cells+1) - { - for ( size_t i = 0 ; i != this->total_number_of_cells ; ++i ) - { - this->key_associated_to_simplex[i] = i; - } - //we initialize this only once, in each constructor, when the bitmap is constructed. - //If the user decide to change some elements of the bitmap, then this procedure need - //to be called again. - this->initialize_simplex_associated_to_key(); - } - - /** - * Destructor of the Bitmap_cubical_complex class. - **/ - virtual ~Bitmap_cubical_complex(){} - - -//*********************************************// -//Other 'easy' functions -//*********************************************// - /** - * Returns number of all cubes in the complex. - **/ - size_t num_simplices()const - { - return this->total_number_of_cells; - } - - /** - * Returns a Simplex_handle to a cube that do not exist in this complex. - **/ - static Simplex_handle null_simplex() - { - if ( globalDbg ){cerr << "Simplex_handle null_simplex()\n";} - return std::numeric_limits::max(); - } - - - /** - * Returns dimension of the complex. - **/ - inline size_t dimension()const - { - return this->sizes.size(); - } - - /** - * Return dimension of a cell pointed by the Simplex_handle. - **/ - inline unsigned dimension(Simplex_handle sh)const - { - if ( globalDbg ){cerr << "unsigned dimension(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) return this->get_dimension_of_a_cell( sh ); - return -1; - } - - /** - * Return the filtration of a cell pointed by the Simplex_handle. - **/ - typename T::filtration_type filtration(Simplex_handle sh) - { - if ( globalDbg ){cerr << "T::filtration_type filtration(const Simplex_handle& sh)\n";} - //Returns the filtration value of a simplex. - if ( sh != std::numeric_limits::max() ) return this->data[sh]; - return std::numeric_limits::max(); - } - - /** - * Return a key which is not a key of any cube in the considered data structure. - **/ - static Simplex_key null_key() - { - if ( globalDbg ){cerr << "Simplex_key null_key()\n";} - return std::numeric_limits::max(); - } - - /** - * Return the key of a cube pointed by the Simplex_handle. - **/ - Simplex_key key(Simplex_handle sh)const - { - if ( globalDbg ){cerr << "Simplex_key key(const Simplex_handle& sh)\n";} - if ( sh != std::numeric_limits::max() ) - { - return this->key_associated_to_simplex[sh]; - } - return this->null_key(); - } - - /** - * Return the Simplex_handle given the key of the cube. - **/ - Simplex_handle simplex(Simplex_key key) - { - if ( globalDbg ){cerr << "Simplex_handle simplex(Simplex_key key)\n";} - if ( key != std::numeric_limits::max() ) - { - return this->simplex_associated_to_key[ key ]; - } - return null_simplex(); - } - - /** - * Assign key to a cube pointed by the Simplex_handle - **/ - void assign_key(Simplex_handle sh, Simplex_key key) - { - if ( globalDbg ){cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";} - if ( key == std::numeric_limits::max() ) return; - this->key_associated_to_simplex[sh] = key; - this->simplex_associated_to_key[key] = sh; - } - - /** - * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. - **/ - void initialize_simplex_associated_to_key(); - - - -//*********************************************// -//Iterators -//*********************************************// - - - - /** - * Boundary_simplex_range class provides ranges for boundary iterators. - **/ - typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; - typedef typename std::vector< Simplex_handle > Boundary_simplex_range; - - - - /** - * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. - * Secondary criteria for filtration are: - * (1) Dimension of a cube (lower dimensional comes first). - * (2) Position in the data structure (the ones that are earlies in the data structure comes first). - **/ - class Filtration_simplex_range; - class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > - { - //Iterator over all simplices of the complex in the order of the indexing scheme. - //'value_type' must be 'Simplex_handle'. - public: - Filtration_simplex_iterator( Bitmap_cubical_complex* b ):b(b),position(0){}; - Filtration_simplex_iterator():b(NULL){}; - - Filtration_simplex_iterator operator++() - { - if ( globalDbg ){cerr << "Filtration_simplex_iterator operator++\n";} - ++this->position; - return (*this); - } - Filtration_simplex_iterator operator++(int) - { - Filtration_simplex_iterator result = *this; - ++(*this); - return result; - } - Filtration_simplex_iterator operator =( const Filtration_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "Filtration_simplex_iterator operator =\n";} - this->b = rhs.b; - this->position = rhs.position; - } - bool operator == ( const Filtration_simplex_iterator& rhs )const - { - if ( globalDbg ){cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";} - return ( this->position == rhs.position ); - } - - bool operator != ( const Filtration_simplex_iterator& rhs )const - { - if ( globalDbg ){cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";} - return !(*this == rhs); - } - Simplex_handle operator*() - { - if ( globalDbg ){cerr << "Simplex_handle operator*()\n";} - return this->b->simplex_associated_to_key[ this->position ]; - } - - friend class Filtration_simplex_range; - private: - Bitmap_cubical_complex* b; - size_t position; - }; - - - /** - * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. - **/ - class Filtration_simplex_range - { - //Range over the simplices of the complex in the order of the filtration. - //.begin() and .end() return type Filtration_simplex_iterator. - public: - typedef Filtration_simplex_iterator const_iterator; - typedef Filtration_simplex_iterator iterator; - Filtration_simplex_range(Bitmap_cubical_complex* b):b(b){}; - Filtration_simplex_iterator begin() - { - if ( globalDbg ){cerr << "Filtration_simplex_iterator begin() \n";} - return Filtration_simplex_iterator( this->b ); - } - Filtration_simplex_iterator end() - { - if ( globalDbg ){cerr << "Filtration_simplex_iterator end()\n";} - Filtration_simplex_iterator it( this->b ); - it.position = this->b->simplex_associated_to_key.size(); - return it; - } - private: - Bitmap_cubical_complex* b; - }; - - - -//*********************************************// -//Methods to access iterators from the container: - /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class - * that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) - { - /* - std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); - Boundary_simplex_range result( bdry.size() ); - for ( size_t i = 0 ; i != bdry.size() ; ++i ) - { - result[i] = this->simplex_associated_to_key[ bdry[i] ]; - } - return result; - */ - return this->get_boundary_of_a_cell(sh); - } - - /** - * filtration_simplex_range creates an object of a Filtration_simplex_range class - * that provides ranges for the Filtration_simplex_iterator. - **/ - Filtration_simplex_range filtration_simplex_range() - { - if ( globalDbg ){cerr << "Filtration_simplex_range filtration_simplex_range()\n";} - //Returns a range over the simplices of the complex in the order of the filtration - return Filtration_simplex_range(this); - } -//*********************************************// - - - -//*********************************************// -//Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are there. - //TODO -- the file IndexingTag.h in the Gudhi library contains an empty structure, so - //I understand that this is something that was planned (for simplicial maps?) - //but was never finished. The only idea I have here is to use the same empty structure from - //IndexingTag.h file, but only if the compiler needs it. If the compiler - //do not need it, then I would rather not add here elements which I do not understand. - //typedef Indexing_tag - /** - * Function needed for compatibility with Gudhi. Not useful for other purposes. - **/ - std::pair endpoints( Simplex_handle sh ) - { - std::vector< size_t > bdry = this->get_boundary_of_a_cell( sh ); - if ( globalDbg ) - { - cerr << "std::pair endpoints( Simplex_handle sh )\n"; - cerr << "bdry.size() : " << bdry.size() << endl; - } - //this method returns two first elements from the boundary of sh. - if ( bdry.size() < 2 ) - throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); - return std::make_pair( bdry[0] , bdry[1] ); - } - - - /** - * Class needed for compatibility with Gudhi. Not useful for other purposes. - **/ - class Skeleton_simplex_range; - class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > - { - //Iterator over all simplices of the complex in the order of the indexing scheme. - //'value_type' must be 'Simplex_handle'. - public: - Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d ):b(b),dimension(d) - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n";} - //find the position of the first simplex of a dimension d - this->position = 0; - while ( - (this->position != b->data.size()) && - ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) - ) - { - ++this->position; - } - }; - Skeleton_simplex_iterator ():b(NULL),dimension(0){}; - - Skeleton_simplex_iterator operator++() - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator++()\n";} - //increment the position as long as you did not get to the next element of the dimension dimension. - ++this->position; - while ( - (this->position != this->b->data.size()) && - ( this->b->get_dimension_of_a_cell( this->position ) != this->dimension ) - ) - { - ++this->position; - } - return (*this); - } - Skeleton_simplex_iterator operator++(int) - { - Skeleton_simplex_iterator result = *this; - ++(*this); - return result; - } - Skeleton_simplex_iterator operator =( const Skeleton_simplex_iterator& rhs ) - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator operator =\n";} - this->b = rhs.b; - this->position = rhs.position; - } - bool operator == ( const Skeleton_simplex_iterator& rhs )const - { - if ( globalDbg ){cerr << "bool operator ==\n";} - return ( this->position == rhs.position ); - } - - bool operator != ( const Skeleton_simplex_iterator& rhs )const - { - if ( globalDbg ){cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";} - return !(*this == rhs); - } - Simplex_handle operator*() - { - if ( globalDbg ){cerr << "Simplex_handle operator*() \n";} - return this->position; - } - - friend class Skeleton_simplex_range; - private: - Bitmap_cubical_complex* b; - size_t position; - unsigned dimension; - }; - /** - * Class needed for compatibility with Gudhi. Not useful for other purposes. - **/ - class Skeleton_simplex_range - { - //Range over the simplices of the complex in the order of the filtration. - //.begin() and .end() return type Filtration_simplex_iterator. - public: - typedef Skeleton_simplex_iterator const_iterator; - typedef Skeleton_simplex_iterator iterator; - Skeleton_simplex_range(Bitmap_cubical_complex* b , unsigned dimension):b(b),dimension(dimension){}; - Skeleton_simplex_iterator begin() - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator begin()\n";} - return Skeleton_simplex_iterator( this->b , this->dimension ); - } - Skeleton_simplex_iterator end() - { - if ( globalDbg ){cerr << "Skeleton_simplex_iterator end()\n";} - Skeleton_simplex_iterator it( this->b , this->dimension ); - it.position = this->b->data.size(); - return it; - } - private: - Bitmap_cubical_complex* b; - unsigned dimension; - }; - - /** - * Function needed for compatibility with Gudhi. Not useful for other purposes. - **/ - Skeleton_simplex_range skeleton_simplex_range( unsigned dimension ) - { - if ( globalDbg ){cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n";} - return Skeleton_simplex_range( this , dimension ); - } - - friend class is_before_in_filtration; - - -protected: - std::vector< size_t > key_associated_to_simplex; - std::vector< size_t > simplex_associated_to_key; -};//Bitmap_cubical_complex +class Bitmap_cubical_complex : public T { + public: + //*********************************************// + // Typedefs and typenames + //*********************************************// + typedef size_t Simplex_key; + typedef typename T::filtration_type Filtration_value; + typedef Simplex_key Simplex_handle; + + + //*********************************************// + // Constructors + //*********************************************// + // Over here we need to define various input types. I am proposing the following ones: + // Perseus style + // TODO(PD) H5 files? + // TODO(PD) binary files with little endiangs / big endians ? + // TODO(PD) constructor from a vector of elements of a type T. ? + + /** + * Constructor form a Perseus-style file. + **/ + Bitmap_cubical_complex(const char* perseus_style_file) : + T(perseus_style_file), key_associated_to_simplex(this->total_number_of_cells + 1) { + if (globalDbg) { + std::cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n"; + } + for (size_t i = 0; i != this->total_number_of_cells; ++i) { + this->key_associated_to_simplex[i] = i; + } + // we initialize this only once, in each constructor, when the bitmap is constructed. + // If the user decide to change some elements of the bitmap, then this procedure need + // to be called again. + this->initialize_simplex_associated_to_key(); + } + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * in the following directions and vector of element of a type T + * with filtration on top dimensional cells. + **/ + Bitmap_cubical_complex(const std::vector& dimensions, + const std::vector& top_dimensional_cells) : + T(dimensions, top_dimensional_cells), + key_associated_to_simplex(this->total_number_of_cells + 1) { + for (size_t i = 0; i != this->total_number_of_cells; ++i) { + this->key_associated_to_simplex[i] = i; + } + // we initialize this only once, in each constructor, when the bitmap is constructed. + // If the user decide to change some elements of the bitmap, then this procedure need + // to be called again. + this->initialize_simplex_associated_to_key(); + } + + /** + * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells + * in the following directions and vector of element of a type T::filtration_type + * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. + * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. + **/ + Bitmap_cubical_complex(const std::vector& dimensions, + const std::vector& top_dimensional_cells, + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed) : + T(dimensions, top_dimensional_cells, directions_in_which_periodic_b_cond_are_to_be_imposed), + key_associated_to_simplex(this->total_number_of_cells + 1) { + for (size_t i = 0; i != this->total_number_of_cells; ++i) { + this->key_associated_to_simplex[i] = i; + } + // we initialize this only once, in each constructor, when the bitmap is constructed. + // If the user decide to change some elements of the bitmap, then this procedure need + // to be called again. + this->initialize_simplex_associated_to_key(); + } + + /** + * Destructor of the Bitmap_cubical_complex class. + **/ + virtual ~Bitmap_cubical_complex(){} + + //*********************************************// + // Other 'easy' functions + //*********************************************// + + /** + * Returns number of all cubes in the complex. + **/ + size_t num_simplices()const { + return this->total_number_of_cells; + } + + /** + * Returns a Simplex_handle to a cube that do not exist in this complex. + **/ + static Simplex_handle null_simplex() { + if (globalDbg) { + std::cerr << "Simplex_handle null_simplex()\n"; + } + return std::numeric_limits::max(); + } + + /** + * Returns dimension of the complex. + **/ + inline size_t dimension()const { + return this->sizes.size(); + } + + /** + * Return dimension of a cell pointed by the Simplex_handle. + **/ + inline unsigned dimension(Simplex_handle sh)const { + if (globalDbg) { + std::cerr << "unsigned dimension(const Simplex_handle& sh)\n"; + } + if (sh != std::numeric_limits::max()) return this->get_dimension_of_a_cell(sh); + return -1; + } + + /** + * Return the filtration of a cell pointed by the Simplex_handle. + **/ + typename T::filtration_type filtration(Simplex_handle sh) { + if (globalDbg) { + std::cerr << "T::filtration_type filtration(const Simplex_handle& sh)\n"; + } + // Returns the filtration value of a simplex. + if (sh != std::numeric_limits::max()) return this->data[sh]; + return std::numeric_limits::max(); + } + + /** + * Return a key which is not a key of any cube in the considered data structure. + **/ + static Simplex_key null_key() { + if (globalDbg) { + std::cerr << "Simplex_key null_key()\n"; + } + return std::numeric_limits::max(); + } + + /** + * Return the key of a cube pointed by the Simplex_handle. + **/ + Simplex_key key(Simplex_handle sh)const { + if (globalDbg) { + std::cerr << "Simplex_key key(const Simplex_handle& sh)\n"; + } + if (sh != std::numeric_limits::max()) { + return this->key_associated_to_simplex[sh]; + } + return this->null_key(); + } + + /** + * Return the Simplex_handle given the key of the cube. + **/ + Simplex_handle simplex(Simplex_key key) { + if (globalDbg) { + std::cerr << "Simplex_handle simplex(Simplex_key key)\n"; + } + if (key != std::numeric_limits::max()) { + return this->simplex_associated_to_key[ key ]; + } + return null_simplex(); + } + + /** + * Assign key to a cube pointed by the Simplex_handle + **/ + void assign_key(Simplex_handle sh, Simplex_key key) { + if (globalDbg) { + std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n"; + } + if (key == std::numeric_limits::max()) return; + this->key_associated_to_simplex[sh] = key; + this->simplex_associated_to_key[key] = sh; + } + + /** + * Function called from a constructor. It is needed for Filtration_simplex_iterator to work. + **/ + void initialize_simplex_associated_to_key(); + + //*********************************************// + // Iterators + //*********************************************// + + /** + * Boundary_simplex_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator; + typedef typename std::vector< Simplex_handle > Boundary_simplex_range; + + /** + * Filtration_simplex_iterator class provides an iterator though the whole structure in the order of filtration. + * Secondary criteria for filtration are: + * (1) Dimension of a cube (lower dimensional comes first). + * (2) Position in the data structure (the ones that are earlies in the data structure comes first). + **/ + class Filtration_simplex_range; + + class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + // Iterator over all simplices of the complex in the order of the indexing scheme. + // 'value_type' must be 'Simplex_handle'. + public: + Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { } + + Filtration_simplex_iterator() : b(NULL) { } + + Filtration_simplex_iterator operator++() { + if (globalDbg) { + std::cerr << "Filtration_simplex_iterator operator++\n"; + } + ++this->position; + return (*this); + } -template -void Bitmap_cubical_complex::initialize_simplex_associated_to_key() -{ - if ( globalDbg ) - { - cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; - } - this->simplex_associated_to_key = std::vector( this->data.size() ); - std::iota (std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); - std::sort( simplex_associated_to_key.begin() , - simplex_associated_to_key.end() , - is_before_in_filtration(this) ); - - //we still need to deal here with a key_associated_to_simplex: - for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) - { - this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; + Filtration_simplex_iterator operator++(int) { + Filtration_simplex_iterator result = *this; + ++(*this); + return result; } -} + Filtration_simplex_iterator& operator=(const Filtration_simplex_iterator& rhs) { + if (globalDbg) { + std::cerr << "Filtration_simplex_iterator operator =\n"; + } + this->b = rhs.b; + this->position = rhs.position; + } -template -class is_before_in_filtration -{ -public: - explicit is_before_in_filtration(Bitmap_cubical_complex * CC) - : CC_(CC) { } - - bool operator()( const typename Bitmap_cubical_complex::Simplex_handle sh1, const typename Bitmap_cubical_complex::Simplex_handle sh2) const - { - // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. - typename T::filtration_type fil1 = CC_->data[sh1]; - typename T::filtration_type fil2 = CC_->data[sh2]; - if ( fil1 != fil2 ) - { - return fil1 < fil2; + bool operator==(const Filtration_simplex_iterator& rhs)const { + if (globalDbg) { + std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n"; + } + return ( this->position == rhs.position); + } + + bool operator!=(const Filtration_simplex_iterator& rhs)const { + if (globalDbg) { + std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + std::cerr << "Simplex_handle operator*()\n"; + } + return this->b->simplex_associated_to_key[ this->position ]; + } + + friend class Filtration_simplex_range; + + private: + Bitmap_cubical_complex* b; + size_t position; + }; + + /** + * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. + **/ + class Filtration_simplex_range { + // Range over the simplices of the complex in the order of the filtration. + // .begin() and .end() return type Filtration_simplex_iterator. + public: + typedef Filtration_simplex_iterator const_iterator; + typedef Filtration_simplex_iterator iterator; + + Filtration_simplex_range(Bitmap_cubical_complex* b) : b(b) { } + + Filtration_simplex_iterator begin() { + if (globalDbg) { + std::cerr << "Filtration_simplex_iterator begin() \n"; } - //in this case they are on the same filtration level, so the dimension decide. - size_t dim1 = CC_->get_dimension_of_a_cell(sh1); - size_t dim2 = CC_->get_dimension_of_a_cell(sh2); - if ( dim1 != dim2 ) - { - return dim1 < dim2; + return Filtration_simplex_iterator(this->b); + } + + Filtration_simplex_iterator end() { + if (globalDbg) { + std::cerr << "Filtration_simplex_iterator end()\n"; } - //in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply compare their positions in the bitmap: - return sh1 < sh2; - } -protected: - Bitmap_cubical_complex* CC_; + Filtration_simplex_iterator it(this->b); + it.position = this->b->simplex_associated_to_key.size(); + return it; + } + + private: + Bitmap_cubical_complex* b; }; -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// + //*********************************************// + // Methods to access iterators from the container: + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. + **/ + Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) { + return this->get_boundary_of_a_cell(sh); + } + + /** + * filtration_simplex_range creates an object of a Filtration_simplex_range class + * that provides ranges for the Filtration_simplex_iterator. + **/ + Filtration_simplex_range filtration_simplex_range() { + if (globalDbg) { + std::cerr << "Filtration_simplex_range filtration_simplex_range()\n"; + } + // Returns a range over the simplices of the complex in the order of the filtration + return Filtration_simplex_range(this); + } + //*********************************************// + + + + //*********************************************// + // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are + // there. + // TODO(PD) the file IndexingTag.h in the Gudhi library contains an empty structure, so + // I understand that this is something that was planned (for simplicial maps?) + // but was never finished. The only idea I have here is to use the same empty structure from + // IndexingTag.h file, but only if the compiler needs it. If the compiler + // do not need it, then I would rather not add here elements which I do not understand. + // typedef Indexing_tag + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + std::pair endpoints(Simplex_handle sh) { + std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh); + if (globalDbg) { + std::cerr << "std::pair endpoints( Simplex_handle sh )\n"; + std::cerr << "bdry.size() : " << bdry.size() << std::endl; + } + // this method returns two first elements from the boundary of sh. + if (bdry.size() < 2) + throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); + return std::make_pair(bdry[0], bdry[1]); + } + + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range; + + class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > { + // Iterator over all simplices of the complex in the order of the indexing scheme. + // 'value_type' must be 'Simplex_handle'. + public: + Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n"; + } + // find the position of the first simplex of a dimension d + this->position = 0; + while ( + (this->position != b->data.size()) && + (this->b->get_dimension_of_a_cell(this->position) != this->dimension) + ) { + ++this->position; + } + } + + Skeleton_simplex_iterator() : b(NULL), position(0), dimension(0) { } + + Skeleton_simplex_iterator operator++() { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator operator++()\n"; + } + // increment the position as long as you did not get to the next element of the dimension dimension. + ++this->position; + while ( + (this->position != this->b->data.size()) && + (this->b->get_dimension_of_a_cell(this->position) != this->dimension) + ) { + ++this->position; + } + return (*this); + } + + Skeleton_simplex_iterator operator++(int) { + Skeleton_simplex_iterator result = *this; + ++(*this); + return result; + } + + Skeleton_simplex_iterator& operator=(const Skeleton_simplex_iterator& rhs) { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator operator =\n"; + } + this->b = rhs.b; + this->position = rhs.position; + this->dimension = rhs.dimension; + } + + bool operator==(const Skeleton_simplex_iterator& rhs)const { + if (globalDbg) { + std::cerr << "bool operator ==\n"; + } + return ( this->position == rhs.position); + } + + bool operator!=(const Skeleton_simplex_iterator& rhs)const { + if (globalDbg) { + std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n"; + } + return !(*this == rhs); + } + + Simplex_handle operator*() { + if (globalDbg) { + std::cerr << "Simplex_handle operator*() \n"; + } + return this->position; + } + + friend class Skeleton_simplex_range; + private: + Bitmap_cubical_complex* b; + size_t position; + unsigned dimension; + }; + + /** + * Class needed for compatibility with Gudhi. Not useful for other purposes. + **/ + class Skeleton_simplex_range { + // Range over the simplices of the complex in the order of the filtration. + // .begin() and .end() return type Filtration_simplex_iterator. + public: + typedef Skeleton_simplex_iterator const_iterator; + typedef Skeleton_simplex_iterator iterator; + + Skeleton_simplex_range(Bitmap_cubical_complex* b, unsigned dimension) : b(b), dimension(dimension) { } + + Skeleton_simplex_iterator begin() { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator begin()\n"; + } + return Skeleton_simplex_iterator(this->b, this->dimension); + } + + Skeleton_simplex_iterator end() { + if (globalDbg) { + std::cerr << "Skeleton_simplex_iterator end()\n"; + } + Skeleton_simplex_iterator it(this->b, this->dimension); + it.position = this->b->data.size(); + return it; + } + + private: + Bitmap_cubical_complex* b; + unsigned dimension; + }; + + /** + * Function needed for compatibility with Gudhi. Not useful for other purposes. + **/ + Skeleton_simplex_range skeleton_simplex_range(unsigned dimension) { + if (globalDbg) { + std::cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n"; + } + return Skeleton_simplex_range(this, dimension); + } + + friend class is_before_in_filtration; + + protected: + std::vector< size_t > key_associated_to_simplex; + std::vector< size_t > simplex_associated_to_key; +}; // Bitmap_cubical_complex + +template +void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { + if (globalDbg) { + std::cerr << "void Bitmap_cubical_complex::initialize_elements_ordered_according_to_filtration() \n"; + } + this->simplex_associated_to_key = std::vector(this->data.size()); + std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); + std::sort(simplex_associated_to_key.begin(), + simplex_associated_to_key.end(), + is_before_in_filtration(this)); + + // we still need to deal here with a key_associated_to_simplex: + for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) + { + this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; + } } -} + +template +class is_before_in_filtration { + public: + explicit is_before_in_filtration(Bitmap_cubical_complex * CC) + : CC_(CC) { } + + bool operator()(const typename Bitmap_cubical_complex::Simplex_handle& sh1, + const typename Bitmap_cubical_complex::Simplex_handle& sh2) const { + // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. + typename T::filtration_type fil1 = CC_->data[sh1]; + typename T::filtration_type fil2 = CC_->data[sh2]; + if (fil1 != fil2) { + return fil1 < fil2; + } + // in this case they are on the same filtration level, so the dimension decide. + size_t dim1 = CC_->get_dimension_of_a_cell(sh1); + size_t dim2 = CC_->get_dimension_of_a_cell(sh2); + if (dim1 != dim2) { + return dim1 < dim2; + } + // in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply + // compare their positions in the bitmap: + return sh1 < sh2; + } + + protected: + Bitmap_cubical_complex* CC_; +}; + +} // namespace Cubical_complex + +} // namespace Gudhi + +#endif // BITMAP_CUBICAL_COMPLEX_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index f0517a86..62776019 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -20,35 +20,30 @@ * along with this program. If not, see . */ -#pragma once +#ifndef BITMAP_CUBICAL_COMPLEX_BASE_H_ +#define BITMAP_CUBICAL_COMPLEX_BASE_H_ -#include -#include -#include +#include + +#include #include #include #include #include #include -#include -#include -#include "Bitmap_cubical_complex/counter.h" - - -using namespace std; +#include +#include // for pair<> -namespace Gudhi -{ - -namespace Cubical_complex -{ +namespace Gudhi { +namespace Cubical_complex { /** - *@class Bitmap_cubical_complex_base - *@brief Cubical complex represented as a bitmap, class with basic implementation. - *@ingroup cubical_complex + * @class Bitmap_cubical_complex_base + * @brief Cubical complex represented as a bitmap, class with basic implementation. + * @ingroup cubical_complex */ + /** * This is a class implementing a basic bitmap data structure to store cubical complexes. * It implements only the most basic subroutines. @@ -67,844 +62,750 @@ namespace Cubical_complex * The default filtration used in this implementation is the lower star filtration. */ template -class Bitmap_cubical_complex_base -{ -public: - typedef T filtration_type; - /** - *Default constructor - **/ - Bitmap_cubical_complex_base() - { - } - /** - * There are a few constructors of a Bitmap_cubical_complex_base class. - * First one, that takes vector, creates an empty bitmap of a dimension equal - * the number of elements in the - * input vector and size in the i-th dimension equal the number in the position i-of the input vector. - */ - Bitmap_cubical_complex_base( const std::vector& sizes ); - /** - * The second constructor takes as a input a Perseus style file. For more details, - * please consult the documentations of - * Perseus software as well as examples attached to this - * implementation. - **/ - Bitmap_cubical_complex_base( const char* perseus_style_file ); - /** - * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) - * together with vector of filtration values of top dimensional cells. - **/ - Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells ); - - /** - * Destructor of the Bitmap_cubical_complex_base class. - **/ - virtual ~Bitmap_cubical_complex_base(){} - - /** - * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell - * and get_cell_data are the basic - * functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a - * non-negative integer, indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to - * the positions of (co)boundary element of the input cell. - */ - virtual inline std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; - /** - * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, - * get_dimension_of_a_cell and get_cell_data are the basic - * functions that compute boundary / coboundary / dimension and the filtration - * value form a position of a cell in the structure of a bitmap. - * The input parameter of all of those function is a non-negative integer, - * indicating a position of a cube in the data structure. - * In the case of functions that compute (co)boundary, the output is a vector if - * non-negative integers pointing to the - * positions of (co)boundary element of the input cell. - **/ - virtual inline std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; - /** - * In the case of get_dimension_of_a_cell function, the output is a non-negative integer - * indicating the dimension of a cell. - **/ - inline unsigned get_dimension_of_a_cell( size_t cell )const; - /** - * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. This allows reading and changing the value of filtration. - * Note that if the value of a filtration is changed, the code do not check if we have a filtration or not. i.e. it do not check if the value of a filtration of a cell is - * not smaller than the value of a filtration of its boundary and not greater than the value of its coboundary. - **/ - inline T& get_cell_data( size_t cell ); - - - /** - * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. - * Then, there are a few ways one can pick the filtration of lower dimensional - * cells. The most typical one is by so called lower star filtration. This function is always called by any - * constructor which takes the top dimensional cells. If you use such a constructor, - * then there is no need to call this function. Call it only if you are putting the filtration - * of the cells by your own (for instance by using Top_dimensional_cells_iterator). - **/ - void impose_lower_star_filtration();//assume that top dimensional cells are already set. - - /** - * Returns dimension of a complex. - **/ - inline unsigned dimension()const{ return sizes.size(); } - - /** - * Returns number of all cubes in the data structure. - **/ - inline unsigned size()const - { - return this->data.size(); - } - - /** - * Writing to stream operator. By using it we get the values T of cells in order in which they are stored in the structure. This procedure is used for debugging purposes. - **/ - template - friend ostream& operator << ( ostream & os , const Bitmap_cubical_complex_base& b ); - - - /** - * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. - * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_to_bins( size_t number_of_bins ) - * ais designed for that purpose. The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. - **/ - void put_data_to_bins( size_t number_of_bins ); - - /** - * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values equally distributed in the range of data. - * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute persistence gets - * worst. When dealing with this type of data, one may want to put different values on cells to some number of bins. The function put_data_to_bins( T diameter_of_bin ) is - * designed for that purpose. The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence diagram of the cubical complex - * before and after using such a function will be bounded by the parameter diameter_of_bin. - **/ - void put_data_to_bins( T diameter_of_bin ); - - /** - * Functions to find min and max values of filtration. - **/ - std::pair< T ,T > min_max_filtration(); - - //ITERATORS - /** - * Iterator through all cells in the complex (in order they appear in the structure -- i.e. - * in lexicographical order). - **/ - class All_cells_iterator : std::iterator< std::input_iterator_tag, T > - { - public: - All_cells_iterator() - { - this->counter = 0; - } - All_cells_iterator operator++() - { - //first find first element of the counter that can be increased: - ++this->counter; - return *this; - } - All_cells_iterator operator++(int) - { - All_cells_iterator result = *this; - ++(*this); - return result; - } - All_cells_iterator operator =( const All_cells_iterator& rhs ) - { - this->counter = rhs.counter; - return *this; - } - bool operator == ( const All_cells_iterator& rhs )const - { - if ( this->counter != rhs.counter )return false; - return true; - } - bool operator != ( const All_cells_iterator& rhs )const - { - return !(*this == rhs); - } - - /* - * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: - * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension - * and in function get_cell_data to get a filtration of a cell. - */ - size_t operator*() - { - return this->counter; - } - friend class Bitmap_cubical_complex_base; - protected: - size_t counter; - }; - - /** - * Function returning a All_cells_iterator to the first cell of the bitmap. - **/ - All_cells_iterator all_cells_iterator_begin() - { - All_cells_iterator a; - return a; - } - - /** - * Function returning a All_cells_iterator to the last cell of the bitmap. - **/ - All_cells_iterator all_cells_iterator_end() - { - All_cells_iterator a; - a.counter = this->data.size(); - return a; - } - - - /** - * All_cells_range class provides ranges for All_cells_iterator - **/ - class All_cells_range - { - public: - All_cells_range(Bitmap_cubical_complex_base* b):b(b){}; - All_cells_iterator begin() - { - return b->all_cells_iterator_begin(); - } - All_cells_iterator end() - { - return b->all_cells_iterator_end(); - } - private: - Bitmap_cubical_complex_base* b; - }; - - All_cells_range all_cells_range() - { - return All_cells_range(this); - } - - - /** - * Boundary_range class provides ranges for boundary iterators. - **/ - typedef typename std::vector< size_t >::const_iterator Boundary_iterator; - typedef typename std::vector< size_t > Boundary_range; - - /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class - * that provides ranges for the Boundary_simplex_iterator. - **/ - Boundary_range boundary_range(size_t sh) - { - return this->get_boundary_of_a_cell(sh); - } - - /** - * Coboundary_range class provides ranges for boundary iterators. - **/ - typedef typename std::vector< size_t >::const_iterator Coboundary_iterator; - typedef typename std::vector< size_t > Coboundary_range; - - /** - * boundary_simplex_range creates an object of a Boundary_simplex_range class - * that provides ranges for the Boundary_simplex_iterator. - **/ - Coboundary_range coboundary_range(size_t sh) - { - return this->get_coboundary_of_a_cell(sh); - } - - - - - - - - - /** - * Iterator through top dimensional cells of the complex. The cells appear in order they are stored - * in the structure (i.e. in lexicographical order) - **/ - class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > - { - public: - Top_dimensional_cells_iterator( Bitmap_cubical_complex_base& b ):b(b) - { - this->counter = std::vector(b.dimension()); - //std::fill( this->counter.begin() , this->counter.end() , 0 ); - } - Top_dimensional_cells_iterator operator++() - { - //first find first element of the counter that can be increased: - size_t dim = 0; - while ( ( dim != this->b.dimension() ) && ( this->counter[dim] == this->b.sizes[dim]-1 ) )++dim; - - if ( dim != this->b.dimension() ) - { - ++this->counter[dim]; - for ( size_t i = 0 ; i != dim ; ++i ) - { - this->counter[i] = 0; - } - } - else - { - ++this->counter[0]; - } - return *this; - } - Top_dimensional_cells_iterator operator++(int) - { - Top_dimensional_cells_iterator result = *this; - ++(*this); - return result; - } - Top_dimensional_cells_iterator operator =( const Top_dimensional_cells_iterator& rhs ) - { - this->counter = rhs.counter; - this->b = rhs.b; - return *this; - } - bool operator == ( const Top_dimensional_cells_iterator& rhs )const - { - if ( &this->b != &rhs.b )return false; - if ( this->counter.size() != rhs.counter.size() )return false; - for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - { - if ( this->counter[i] != rhs.counter[i] )return false; - } - return true; - } - bool operator != ( const Top_dimensional_cells_iterator& rhs )const - { - return !(*this == rhs); - } - - //T& operator*() - //{ - // //given the counter, compute the index in the array and return this element. - // unsigned index = 0; - // for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - // { - // index += (2*this->counter[i]+1)*this->b.multipliers[i]; - // } - // return this->b.data[index]; - //} - - /* - * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: - * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension - * and in function get_cell_data to get a filtration of a cell. - */ - size_t operator*() - { - return this->compute_index_in_bitmap(); - } - - size_t compute_index_in_bitmap()const - { - size_t index = 0; - for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - { - index += (2*this->counter[i]+1)*this->b.multipliers[i]; - } - return index; - } - - - void print_counter()const - { - for ( size_t i = 0 ; i != this->counter.size() ; ++i ) - { - cout << this->counter[i] << " "; - } - } - friend class Bitmap_cubical_complex_base; - protected: - std::vector< size_t > counter; - Bitmap_cubical_complex_base& b; - }; - - /** - * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap. - **/ - Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin() - { - Top_dimensional_cells_iterator a(*this); - return a; - } - - /** - * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap. - **/ - Top_dimensional_cells_iterator top_dimensional_cells_iterator_end() - { - Top_dimensional_cells_iterator a(*this); - for ( size_t i = 0 ; i != this->dimension() ; ++i ) - { - a.counter[i] = this->sizes[i]-1; - } - a.counter[0]++; - return a; - } - - /** - * Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range - **/ - class Top_dimensional_cells_range - { - public: - Top_dimensional_cells_range(Bitmap_cubical_complex_base* b):b(b){}; - Top_dimensional_cells_iterator begin() - { - return b->top_dimensional_cells_iterator_begin(); - } - Top_dimensional_cells_iterator end() - { - return b->top_dimensional_cells_iterator_end(); - } - private: - Bitmap_cubical_complex_base* b; - }; - - Top_dimensional_cells_range top_dimensional_cells_range() - { - return Top_dimensional_cells_range(this); - } - - -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// - - -inline size_t number_cells()const -{ - return this->total_number_of_cells; -} +class Bitmap_cubical_complex_base { + public: + typedef T filtration_type; + + /** + *Default constructor + **/ + Bitmap_cubical_complex_base() : + total_number_of_cells(0) { } + /** + * There are a few constructors of a Bitmap_cubical_complex_base class. + * First one, that takes vector, creates an empty bitmap of a dimension equal + * the number of elements in the + * input vector and size in the i-th dimension equal the number in the position i-of the input vector. + */ + Bitmap_cubical_complex_base(const std::vector& sizes); + /** + * The second constructor takes as a input a Perseus style file. For more details, + * please consult the documentations of + * Perseus software as well as examples attached to this + * implementation. + **/ + Bitmap_cubical_complex_base(const char* perseus_style_file); + /** + * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one) + * together with vector of filtration values of top dimensional cells. + **/ + Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells); + + /** + * Destructor of the Bitmap_cubical_complex_base class. + **/ + virtual ~Bitmap_cubical_complex_base() { } + + /** + * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell + * and get_cell_data are the basic + * functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a + * non-negative integer, indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to + * the positions of (co)boundary element of the input cell. + */ + virtual inline std::vector< size_t > get_boundary_of_a_cell(size_t cell)const; + /** + * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell, + * get_dimension_of_a_cell and get_cell_data are the basic + * functions that compute boundary / coboundary / dimension and the filtration + * value form a position of a cell in the structure of a bitmap. + * The input parameter of all of those function is a non-negative integer, + * indicating a position of a cube in the data structure. + * In the case of functions that compute (co)boundary, the output is a vector if + * non-negative integers pointing to the + * positions of (co)boundary element of the input cell. + **/ + virtual inline std::vector< size_t > get_coboundary_of_a_cell(size_t cell)const; + /** + * In the case of get_dimension_of_a_cell function, the output is a non-negative integer + * indicating the dimension of a cell. + **/ + inline unsigned get_dimension_of_a_cell(size_t cell)const; + /** + * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position. + * This allows reading and changing the value of filtration. Note that if the value of a filtration is changed, the + * code do not check if we have a filtration or not. i.e. it do not check if the value of a filtration of a cell is + * not smaller than the value of a filtration of its boundary and not greater than the value of its coboundary. + **/ + inline T& get_cell_data(size_t cell); + + + /** + * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells. + * Then, there are a few ways one can pick the filtration of lower dimensional + * cells. The most typical one is by so called lower star filtration. This function is always called by any + * constructor which takes the top dimensional cells. If you use such a constructor, + * then there is no need to call this function. Call it only if you are putting the filtration + * of the cells by your own (for instance by using Top_dimensional_cells_iterator). + **/ + void impose_lower_star_filtration(); // assume that top dimensional cells are already set. + + /** + * Returns dimension of a complex. + **/ + inline unsigned dimension()const { + return sizes.size(); + } + + /** + * Returns number of all cubes in the data structure. + **/ + inline unsigned size()const { + return this->data.size(); + } + + /** + * Writing to stream operator. By using it we get the values T of cells in order in which they are stored in the + * structure. This procedure is used for debugging purposes. + **/ + template + friend std::ostream& operator<<(std::ostream & os, const Bitmap_cubical_complex_base& b); + + /** + * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values + * equally distributed in the range of data. + * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute + * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to + * some number of bins. The function put_data_to_bins( size_t number_of_bins ) is designed for that purpose. + * The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex. + **/ + void put_data_to_bins(size_t number_of_bins); + + /** + * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values + * equally distributed in the range of data. + * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute + * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to + * some number of bins. The function put_data_to_bins( T diameter_of_bin ) is designed for that purpose. + * The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence + * diagram of the cubical complex before and after using such a function will be bounded by the parameter + * diameter_of_bin. + **/ + void put_data_to_bins(T diameter_of_bin); + + /** + * Functions to find min and max values of filtration. + **/ + std::pair< T, T > min_max_filtration(); + + // ITERATORS + + /** + * Iterator through all cells in the complex (in order they appear in the structure -- i.e. + * in lexicographical order). + **/ + class All_cells_iterator : std::iterator< std::input_iterator_tag, T > { + public: + + All_cells_iterator() { + this->counter = 0; + } -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// -//****************************************************************************************************************// - -protected: - std::vector sizes; - std::vector multipliers; - std::vector data; - size_t total_number_of_cells; - void set_up_containers( const std::vector& sizes ) - { - unsigned multiplier = 1; - for ( size_t i = 0 ; i != sizes.size() ; ++i ) - { - this->sizes.push_back(sizes[i]); - this->multipliers.push_back(multiplier); - multiplier *= 2*sizes[i]+1; - } - this->data = std::vector(multiplier, std::numeric_limits::max()); - this->total_number_of_cells = multiplier; + All_cells_iterator operator++() { + //first find first element of the counter that can be increased: + ++this->counter; + return *this; } - size_t compute_position_in_bitmap( const std::vector< unsigned >& counter ) - { - size_t position = 0; - for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) - { - position += this->multipliers[i]*counter[i]; - } - return position; + All_cells_iterator operator++(int) { + All_cells_iterator result = *this; + ++(*this); + return result; + } + + All_cells_iterator operator=(const All_cells_iterator& rhs) { + this->counter = rhs.counter; + return *this; } - std::vector compute_counter_for_given_cell( size_t cell )const - { - std::vector counter; - counter.reserve( this->sizes.size() ); - for ( size_t dim = this->sizes.size() ; dim != 0 ; --dim ) - { - counter.push_back(cell/this->multipliers[dim-1]); - cell = cell%this->multipliers[dim-1]; + bool operator==(const All_cells_iterator& rhs)const { + if (this->counter != rhs.counter)return false; + return true; + } + + bool operator!=(const All_cells_iterator& rhs)const { + return !(*this == rhs); + } + + /* + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * and in function get_cell_data to get a filtration of a cell. + */ + size_t operator*() { + return this->counter; + } + friend class Bitmap_cubical_complex_base; + protected: + size_t counter; + }; + + /** + * Function returning a All_cells_iterator to the first cell of the bitmap. + **/ + All_cells_iterator all_cells_iterator_begin() { + All_cells_iterator a; + return a; + } + + /** + * Function returning a All_cells_iterator to the last cell of the bitmap. + **/ + All_cells_iterator all_cells_iterator_end() { + All_cells_iterator a; + a.counter = this->data.size(); + return a; + } + + /** + * All_cells_range class provides ranges for All_cells_iterator + **/ + class All_cells_range { + public: + + All_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }; + + All_cells_iterator begin() { + return b->all_cells_iterator_begin(); + } + + All_cells_iterator end() { + return b->all_cells_iterator_end(); + } + private: + Bitmap_cubical_complex_base* b; + }; + + All_cells_range all_cells_range() { + return All_cells_range(this); + } + + + /** + * Boundary_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< size_t >::const_iterator Boundary_iterator; + typedef typename std::vector< size_t > Boundary_range; + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. + **/ + Boundary_range boundary_range(size_t sh) { + return this->get_boundary_of_a_cell(sh); + } + + /** + * Coboundary_range class provides ranges for boundary iterators. + **/ + typedef typename std::vector< size_t >::const_iterator Coboundary_iterator; + typedef typename std::vector< size_t > Coboundary_range; + + /** + * boundary_simplex_range creates an object of a Boundary_simplex_range class + * that provides ranges for the Boundary_simplex_iterator. + **/ + Coboundary_range coboundary_range(size_t sh) { + return this->get_coboundary_of_a_cell(sh); + } + + /** + * Iterator through top dimensional cells of the complex. The cells appear in order they are stored + * in the structure (i.e. in lexicographical order) + **/ + class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > { + public: + + Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b) : b(b) { + this->counter = std::vector(b.dimension()); + //std::fill( this->counter.begin() , this->counter.end() , 0 ); + } + + Top_dimensional_cells_iterator operator++() { + //first find first element of the counter that can be increased: + size_t dim = 0; + while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; + + if (dim != this->b.dimension()) { + ++this->counter[dim]; + for (size_t i = 0; i != dim; ++i) { + this->counter[i] = 0; } - std::reverse( counter.begin() , counter.end() ); - return counter; - } - void read_perseus_style_file( const char* perseus_style_file ); - void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells); - Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ); - Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ); - Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ); + } else { + ++this->counter[0]; + } + return *this; + } + + Top_dimensional_cells_iterator operator++(int) { + Top_dimensional_cells_iterator result = *this; + ++(*this); + return result; + } + + Top_dimensional_cells_iterator operator=(const Top_dimensional_cells_iterator& rhs) { + this->counter = rhs.counter; + this->b = rhs.b; + return *this; + } + + bool operator==(const Top_dimensional_cells_iterator& rhs)const { + if (&this->b != &rhs.b)return false; + if (this->counter.size() != rhs.counter.size())return false; + for (size_t i = 0; i != this->counter.size(); ++i) { + if (this->counter[i] != rhs.counter[i])return false; + } + return true; + } + + bool operator!=(const Top_dimensional_cells_iterator& rhs)const { + return !(*this == rhs); + } + + /* + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * and in function get_cell_data to get a filtration of a cell. + */ + size_t operator*() { + return this->compute_index_in_bitmap(); + } + + size_t compute_index_in_bitmap()const { + size_t index = 0; + for (size_t i = 0; i != this->counter.size(); ++i) { + index += (2 * this->counter[i] + 1) * this->b.multipliers[i]; + } + return index; + } + + void print_counter()const { + for (size_t i = 0; i != this->counter.size(); ++i) { + std::cout << this->counter[i] << " "; + } + } + friend class Bitmap_cubical_complex_base; + protected: + std::vector< size_t > counter; + Bitmap_cubical_complex_base& b; + }; + + /** + * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap. + **/ + Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin() { + Top_dimensional_cells_iterator a(*this); + return a; + } + + /** + * Function returning a Top_dimensional_cells_iterator to the last top dimensional cell of the bitmap. + **/ + Top_dimensional_cells_iterator top_dimensional_cells_iterator_end() { + Top_dimensional_cells_iterator a(*this); + for (size_t i = 0; i != this->dimension(); ++i) { + a.counter[i] = this->sizes[i] - 1; + } + a.counter[0]++; + return a; + } + + /** + * Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range + **/ + class Top_dimensional_cells_range { + public: + + Top_dimensional_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }; + + Top_dimensional_cells_iterator begin() { + return b->top_dimensional_cells_iterator_begin(); + } + + Top_dimensional_cells_iterator end() { + return b->top_dimensional_cells_iterator_end(); + } + private: + Bitmap_cubical_complex_base* b; + }; + + Top_dimensional_cells_range top_dimensional_cells_range() { + return Top_dimensional_cells_range(this); + } + + + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + + inline size_t number_cells()const { + return this->total_number_of_cells; + } + + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + //****************************************************************************************************************// + + protected: + std::vector sizes; + std::vector multipliers; + std::vector data; + size_t total_number_of_cells; + + void set_up_containers(const std::vector& sizes) { + unsigned multiplier = 1; + for (size_t i = 0; i != sizes.size(); ++i) { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + multiplier *= 2 * sizes[i] + 1; + } + this->data = std::vector(multiplier, std::numeric_limits::max()); + this->total_number_of_cells = multiplier; + } + + size_t compute_position_in_bitmap(const std::vector< unsigned >& counter) { + size_t position = 0; + for (size_t i = 0; i != this->multipliers.size(); ++i) { + position += this->multipliers[i] * counter[i]; + } + return position; + } + + std::vector compute_counter_for_given_cell(size_t cell)const { + std::vector counter; + counter.reserve(this->sizes.size()); + for (size_t dim = this->sizes.size(); dim != 0; --dim) { + counter.push_back(cell / this->multipliers[dim - 1]); + cell = cell % this->multipliers[dim - 1]; + } + std::reverse(counter.begin(), counter.end()); + return counter; + } + void read_perseus_style_file(const char* perseus_style_file); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells); + Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector directions); + Bitmap_cubical_complex_base(const std::vector& sizes, std::vector directions); + Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells, std::vector directions); }; +template +void Bitmap_cubical_complex_base::put_data_to_bins(size_t number_of_bins) { + bool bdg = false; + + std::pair< T, T > min_max = this->min_max_filtration(); + T dx = (min_max.second - min_max.first) / (T) number_of_bins; + + //now put the data into the appropriate bins: + for (size_t i = 0; i != this->data.size(); ++i) { + if (bdg) { + std::cerr << "Before binning : " << this->data[i] << std::endl; + } + this->data[i] = min_max.first + dx * (this->data[i] - min_max.first) / number_of_bins; + if (bdg) { + std::cerr << "After binning : " << this->data[i] << std::endl; + getchar(); + } + } +} -template -void Bitmap_cubical_complex_base::put_data_to_bins( size_t number_of_bins ) -{ - bool bdg = false; - - std::pair< T ,T > min_max = this->min_max_filtration(); - T dx = (min_max.second-min_max.first)/(T)number_of_bins; - - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + dx*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - template -void Bitmap_cubical_complex_base::put_data_to_bins( T diameter_of_bin ) -{ - bool bdg = false; - std::pair< T ,T > min_max = this->min_max_filtration(); - - size_t number_of_bins = (min_max.second - min_max.first)/diameter_of_bin; - //now put the data into the appropriate bins: - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( bdg ){cerr << "Before binning : " << this->data[i] << endl;} - this->data[i] = min_max.first + diameter_of_bin*(this->data[i]-min_max.first)/number_of_bins; - if ( bdg ){cerr << "After binning : " << this->data[i] << endl;getchar();} - } -} - -template -std::pair< T ,T > Bitmap_cubical_complex_base::min_max_filtration() -{ - std::pair< T ,T > min_max( std::numeric_limits::max() , std::numeric_limits::min() ); - for ( size_t i = 0 ; i != this->data.size() ; ++i ) - { - if ( this->data[i] < min_max.first )min_max.first = this->data[i]; - if ( this->data[i] > min_max.second )min_max.second = this->data[i]; - } - return min_max; -} +void Bitmap_cubical_complex_base::put_data_to_bins(T diameter_of_bin) { + bool bdg = false; + std::pair< T, T > min_max = this->min_max_filtration(); + + size_t number_of_bins = (min_max.second - min_max.first) / diameter_of_bin; + //now put the data into the appropriate bins: + for (size_t i = 0; i != this->data.size(); ++i) { + if (bdg) { + std::cerr << "Before binning : " << this->data[i] << std::endl; + } + this->data[i] = min_max.first + diameter_of_bin * (this->data[i] - min_max.first) / number_of_bins; + if (bdg) { + std::cerr << "After binning : " << this->data[i] << std::endl; + getchar(); + } + } +} +template +std::pair< T, T > Bitmap_cubical_complex_base::min_max_filtration() { + std::pair< T, T > min_max(std::numeric_limits::max(), std::numeric_limits::min()); + for (size_t i = 0; i != this->data.size(); ++i) { + if (this->data[i] < min_max.first)min_max.first = this->data[i]; + if (this->data[i] > min_max.second)min_max.second = this->data[i]; + } + return min_max; +} template -ostream& operator << ( ostream & out , const Bitmap_cubical_complex_base& b ) -{ - for ( typename Bitmap_cubical_complex_base::all_cells_const_iterator - it = b.all_cells_const_begin() ; it != b.all_cells_const_end() ; ++it ) - { - out << *it << " "; - } - return out; +ostream& operator<<(ostream & out, const Bitmap_cubical_complex_base& b) { + for (typename Bitmap_cubical_complex_base::all_cells_const_iterator + it = b.all_cells_const_begin(); it != b.all_cells_const_end(); ++it) { + out << *it << " "; + } + return out; } - template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( const std::vector& sizes ) -{ - this->set_up_containers( sizes ); +(const std::vector& sizes) { + this->set_up_containers(sizes); } - -template -void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells) -{ - this->set_up_containers( sizes_in_following_directions ); - - size_t number_of_top_dimensional_elements = 1; - for ( size_t i = 0 ; i != sizes_in_following_directions.size() ; ++i ) - { - number_of_top_dimensional_elements *= sizes_in_following_directions[i]; - } - if ( number_of_top_dimensional_elements != top_dimensional_cells.size() ) - { - cerr << - "Error in constructor\ + +template +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells) { + this->set_up_containers(sizes_in_following_directions); + + size_t number_of_top_dimensional_elements = 1; + for (size_t i = 0; i != sizes_in_following_directions.size(); ++i) { + number_of_top_dimensional_elements *= sizes_in_following_directions[i]; + } + if (number_of_top_dimensional_elements != top_dimensional_cells.size()) { + std::cerr << + "Error in constructor\ Bitmap_cubical_complex_base\ ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ Number of top dimensional elements that follow from sizes_in_following_directions vector is different\ - than the size of top_dimensional_cells vector." << endl; - throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ + than the size of top_dimensional_cells vector." << std::endl; + throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ std::vector top_dimensional_cells )\ . Number of top dimensional elements that follow from sizes_in_following_directions vector is different than the\ size of top_dimensional_cells vector."); - } - - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - size_t index = 0; - for ( it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) - { - this->get_cell_data(*it) = top_dimensional_cells[index]; - ++index; - } - this->impose_lower_star_filtration(); -} + } + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + size_t index = 0; + for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { + this->get_cell_data(*it) = top_dimensional_cells[index]; + ++index; + } + this->impose_lower_star_filtration(); +} template Bitmap_cubical_complex_base::Bitmap_cubical_complex_base -( const std::vector& sizes_in_following_directions , const std::vector& top_dimensional_cells ) -{ - this->setup_bitmap_based_on_top_dimensional_cells_list( sizes_in_following_directions , top_dimensional_cells ); -} - -template -void Bitmap_cubical_complex_base::read_perseus_style_file( const char* perseus_style_file ) -{ - bool dbg = false; - ifstream inFiltration, inIds; - inFiltration.open( perseus_style_file ); - unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - if (dbg){cerr << "dimensionOfData : " << dimensionOfData << endl;getchar();} - - std::vector sizes; - sizes.reserve( dimensionOfData ); - for ( size_t i = 0 ; i != dimensionOfData ; ++i ) - { - unsigned size_in_this_dimension; - inFiltration >> size_in_this_dimension; - size_in_this_dimension = size_in_this_dimension; - sizes.push_back( size_in_this_dimension ); - if (dbg){cerr << "size_in_this_dimension : " << size_in_this_dimension << endl;} - } - this->set_up_containers( sizes ); - - Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_iterator_begin(); - - while ( !inFiltration.eof() ) - { - T filtrationLevel; - inFiltration >> filtrationLevel; - if ( dbg ) - { - cerr << "Cell of an index : " - << it.compute_index_in_bitmap() - << " and dimension: " - << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) - << " get the value : " << filtrationLevel << endl; - } - this->get_cell_data(*it) = filtrationLevel; - ++it; - } - inFiltration.close(); - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->read_perseus_style_file( perseus_style_file ); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& sizes , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const std::vector& dimensions , const std::vector& top_dimensional_cells , std::vector directions ) -{ - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. - this->setup_bitmap_based_on_top_dimensional_cells_list( dimensions , top_dimensional_cells ); +(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells) { + this->setup_bitmap_based_on_top_dimensional_cells_list(sizes_in_following_directions, top_dimensional_cells); } template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base( const char* perseus_style_file ) -{ - this->read_perseus_style_file( perseus_style_file ); +void Bitmap_cubical_complex_base::read_perseus_style_file(const char* perseus_style_file) { + bool dbg = false; + std::ifstream inFiltration, inIds; + inFiltration.open(perseus_style_file); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + if (dbg) { + std::cerr << "dimensionOfData : " << dimensionOfData << std::endl; + getchar(); + } + + std::vector sizes; + sizes.reserve(dimensionOfData); + for (size_t i = 0; i != dimensionOfData; ++i) { + unsigned size_in_this_dimension; + inFiltration >> size_in_this_dimension; + size_in_this_dimension = size_in_this_dimension; + sizes.push_back(size_in_this_dimension); + if (dbg) { + std::cerr << "size_in_this_dimension : " << size_in_this_dimension << std::endl; + } + } + this->set_up_containers(sizes); + + Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_iterator_begin(); + + while (!inFiltration.eof()) { + T filtrationLevel; + inFiltration >> filtrationLevel; + if (dbg) { + std::cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << std::endl; + } + this->get_cell_data(*it) = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); } - template -std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell( size_t cell )const -{ - std::vector< size_t > boundary_elements; - - //Speed traded of for memory. Check if it is better in practice. - boundary_elements.reserve( this->dimension()*2 ); - - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - if ( position%2 == 1 ) - { - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - } - cell1 = cell1%this->multipliers[i-1]; - } - return boundary_elements; -} - +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector directions) { + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->read_perseus_style_file(perseus_style_file); +} - - - template -std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell( size_t cell )const -{ - std::vector counter = this->compute_counter_for_given_cell( cell ); - std::vector< size_t > coboundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - if ( position%2 == 0 ) - { - if ( (cell > this->multipliers[i-1]) && (counter[i-1] != 0) ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - } - if ( - (cell + this->multipliers[i-1] < this->data.size()) && (counter[i-1] != 2*this->sizes[i-1]) ) - { - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - } - cell1 = cell1%this->multipliers[i-1]; - } - return coboundary_elements; -} - - - - +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& sizes, std::vector directions) { + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->set_up_containers(sizes); +} +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells, std::vector directions) { + //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. + //It ignores the last parameter of the function. + this->setup_bitmap_based_on_top_dimensional_cells_list(dimensions, top_dimensional_cells); +} +template +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const char* perseus_style_file) { + this->read_perseus_style_file(perseus_style_file); +} +template +std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell)const { + std::vector< size_t > boundary_elements; + + //Speed traded of for memory. Check if it is better in practice. + boundary_elements.reserve(this->dimension()*2); + + size_t cell1 = cell; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / this->multipliers[i - 1]; + if (position % 2 == 1) { + boundary_elements.push_back(cell - this->multipliers[ i - 1 ]); + boundary_elements.push_back(cell + this->multipliers[ i - 1 ]); + } + cell1 = cell1 % this->multipliers[i - 1]; + } + return boundary_elements; +} template -unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell( size_t cell )const -{ - bool dbg = false; - if (dbg)cerr << "\n\n\n Computing position o a cell of an index : " << cell << endl; - unsigned dimension = 0; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell/this->multipliers[i-1]; - - if (dbg)cerr << "i-1 :" << i-1 << endl; - if (dbg)cerr << "cell : " << cell << endl; - if (dbg)cerr << "position : " << position << endl; - if (dbg)cerr << "multipliers["<multipliers[i-1] << endl; - if (dbg)getchar(); - - if ( position%2 == 1 ) - { - if (dbg)cerr << "Nonzero length in this direction \n"; - dimension++; - } - cell = cell%this->multipliers[i-1]; +std::vector< size_t > Bitmap_cubical_complex_base::get_coboundary_of_a_cell(size_t cell)const { + std::vector counter = this->compute_counter_for_given_cell(cell); + std::vector< size_t > coboundary_elements; + size_t cell1 = cell; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / this->multipliers[i - 1]; + if (position % 2 == 0) { + if ((cell > this->multipliers[i - 1]) && (counter[i - 1] != 0)) { + coboundary_elements.push_back(cell - this->multipliers[i - 1]); + } + if ( + (cell + this->multipliers[i - 1] < this->data.size()) && (counter[i - 1] != 2 * this->sizes[i - 1])) { + coboundary_elements.push_back(cell + this->multipliers[i - 1]); + } } - return dimension; + cell1 = cell1 % this->multipliers[i - 1]; + } + return coboundary_elements; } template -inline T& Bitmap_cubical_complex_base::get_cell_data( size_t cell ) -{ - return this->data[cell]; +unsigned Bitmap_cubical_complex_base::get_dimension_of_a_cell(size_t cell)const { + bool dbg = false; + if (dbg) std::cerr << "\n\n\n Computing position o a cell of an index : " << cell << std::endl; + unsigned dimension = 0; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell / this->multipliers[i - 1]; + + if (dbg) { + std::cerr << "i-1 :" << i - 1 << std::endl; + std::cerr << "cell : " << cell << std::endl; + std::cerr << "position : " << position << std::endl; + std::cerr << "multipliers[" << i - 1 << "] = " << this->multipliers[i - 1] << std::endl; + getchar(); + } + + if (position % 2 == 1) { + if (dbg) std::cerr << "Nonzero length in this direction \n"; + dimension++; + } + cell = cell % this->multipliers[i - 1]; + } + return dimension; } +template +inline T& Bitmap_cubical_complex_base::get_cell_data(size_t cell) { + return this->data[cell]; +} template -void Bitmap_cubical_complex_base::impose_lower_star_filtration() -{ - bool dbg = false; - - //this vector will be used to check which elements have already been taken care of - //in imposing lower star filtration: - std::vector is_this_cell_considered( this->data.size() , false ); - - size_t size_to_reserve = 1; - for ( size_t i = 0 ; i != this->multipliers.size() ; ++i ) - { - size_to_reserve *= (size_t)((this->multipliers[i]-1)/2); - } - - std::vector indices_to_consider; - indices_to_consider.reserve( size_to_reserve ); - //we assume here that we already have a filtration on the top dimensional cells and - //we have to extend it to lower ones. - typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); - for ( it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) - { - indices_to_consider.push_back( it.compute_index_in_bitmap() ); - } - - while ( indices_to_consider.size() ) - { - if ( dbg ) - { - cerr << "indices_to_consider in this iteration \n"; - for ( size_t i = 0 ; i != indices_to_consider.size() ; ++i ) - { - cout << indices_to_consider[i] << " "; - } +void Bitmap_cubical_complex_base::impose_lower_star_filtration() { + bool dbg = false; + + //this vector will be used to check which elements have already been taken care of + //in imposing lower star filtration: + std::vector is_this_cell_considered(this->data.size(), false); + + size_t size_to_reserve = 1; + for (size_t i = 0; i != this->multipliers.size(); ++i) { + size_to_reserve *= (size_t) ((this->multipliers[i] - 1) / 2); + } + + std::vector indices_to_consider; + indices_to_consider.reserve(size_to_reserve); + //we assume here that we already have a filtration on the top dimensional cells and + //we have to extend it to lower ones. + typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); + for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { + indices_to_consider.push_back(it.compute_index_in_bitmap()); + } + + while (indices_to_consider.size()) { + if (dbg) { + std::cerr << "indices_to_consider in this iteration \n"; + for (size_t i = 0; i != indices_to_consider.size(); ++i) { + std::cout << indices_to_consider[i] << " "; + } + getchar(); + } + std::vector new_indices_to_consider; + for (size_t i = 0; i != indices_to_consider.size(); ++i) { + std::vector bd = this->get_boundary_of_a_cell(indices_to_consider[i]); + for (size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) { + if (dbg) { + std::cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << std::endl; + getchar(); + + } + if (this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ]) { + this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; + if (dbg) { + std::cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << std::endl; getchar(); + } } - std::vector new_indices_to_consider; - for ( size_t i = 0 ; i != indices_to_consider.size() ; ++i ) - { - std::vector bd = this->get_boundary_of_a_cell( indices_to_consider[i] ); - for ( size_t boundaryIt = 0 ; boundaryIt != bd.size() ; ++boundaryIt ) - { - if ( dbg ) - { - cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << endl; - getchar(); - - } - if ( this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ] ) - { - this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; - if ( dbg ) - { - cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << endl; - getchar(); - } - } - if ( is_this_cell_considered[ bd[boundaryIt] ] == false ) - { - new_indices_to_consider.push_back( bd[boundaryIt] ); - is_this_cell_considered[ bd[boundaryIt] ] = true; - } - } + if (is_this_cell_considered[ bd[boundaryIt] ] == false) { + new_indices_to_consider.push_back(bd[boundaryIt]); + is_this_cell_considered[ bd[boundaryIt] ] = true; } - indices_to_consider.swap(new_indices_to_consider); + } } + indices_to_consider.swap(new_indices_to_consider); + } } - template -bool compareFirstElementsOfTuples( const std::pair< std::pair< T , size_t > , char >& first , - const std::pair< std::pair< T , size_t > , char >& second ) -{ - if ( first.first.first < second.first.first ) - { - return true; - } - else - { - if ( first.first.first > second.first.first ) - { - return false; - } - //in this case first.first.first == second.first.first, so we need to compare dimensions - return first.second < second.second; +bool compareFirstElementsOfTuples(const std::pair< std::pair< T, size_t >, char >& first, + const std::pair< std::pair< T, size_t >, char >& second) { + if (first.first.first < second.first.first) { + return true; + } else { + if (first.first.first > second.first.first) { + return false; } + //in this case first.first.first == second.first.first, so we need to compare dimensions + return first.second < second.second; + } } +} // namespace Cubical_complex +} // namespace Gudhi - -} - -} +#endif // BITMAP_CUBICAL_COMPLEX_BASE_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 956e74a7..2c0d77fe 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -18,348 +18,289 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - */ - -#pragma once -#include -#include "Bitmap_cubical_complex_base.h" - -using namespace std; - -namespace Gudhi -{ - -namespace Cubical_complex -{ - -//in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic boundary conditions). But, we set up the iterators and the procedures -//to compute boundary and coboundary in the way that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all the cells on the -//right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base - - + */ + +#ifndef BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_ +#define BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_ + +#include + +#include +#include // for numeric_limits<> +#include + +namespace Gudhi { + +namespace Cubical_complex { + +// in this class, we are storing all the elements which are in normal bitmap (i.e. the bitmap without the periodic +// boundary conditions). But, we set up the iterators and the procedures to compute boundary and coboundary in the way +// that it is all right. We assume here that all the cells that are on the left / bottom and so on remains, while all +// the cells on the right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base + /** - *@class Bitmap_cubical_complex_periodic_boundary_conditions_base - *@brief Cubical complex with periodic boundary conditions represented as a bitmap. - *@ingroup cubical_complex - */ + * @class Bitmap_cubical_complex_periodic_boundary_conditions_base + * @brief Cubical complex with periodic boundary conditions represented as a bitmap. + * @ingroup cubical_complex + */ /** -* This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. +* This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. * The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. -*/ -template -class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base -{ -public: - //constructors that take an extra parameter: - /** - * Default constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class. - */ - Bitmap_cubical_complex_periodic_boundary_conditions_base(){}; - - /** - * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of booleans. If at i-th position of this vector there is true value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction i. - */ - Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); - /** - * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the name of Perseus style file as an input. Please consult the documentation about the specification of the file. - */ - Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseusStyleFile ); - /** - * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of top dimensional cells (ordered lexicographically) and (3) vector of booleans. If at i-th position of this vector there is true value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction i. - */ - Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); - - /** - * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class. - **/ - virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base(){} - - //overwritten methods co compute boundary and coboundary - /** - * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. - */ - virtual std::vector< size_t > get_boundary_of_a_cell( size_t cell )const; - /** - * A version of a function that return coboundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. - */ - virtual std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; -protected: - std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; - void set_up_containers( const std::vector& sizes ) - { - - unsigned multiplier = 1; - for ( size_t i = 0 ; i != sizes.size() ; ++i ) - { - this->sizes.push_back(sizes[i]); - this->multipliers.push_back(multiplier); - - if ( directions_in_which_periodic_b_cond_are_to_be_imposed[i] ) - { - multiplier *= 2*sizes[i]; - } - else - { - multiplier *= 2*sizes[i]+1; - } - } - //std::reverse( this->sizes.begin() , this->sizes.end() ); - this->data = std::vector(multiplier,std::numeric_limits::max()); - this->total_number_of_cells = multiplier; - } - Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes ); - Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells ); - void construct_complex_based_on_top_dimensional_cells( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ); -}; - -template -void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; - this->set_up_containers( dimensions ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) - { - this->get_cell_data(*it) = topDimensionalCells[i]; - ++i; - } - this->impose_lower_star_filtration(); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed(directions_in_which_periodic_b_cond_are_to_be_imposed); - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const char* perseus_style_file ) -{ - - //for Perseus style files: - bool dbg = false; - ifstream inFiltration; - inFiltration.open( perseus_style_file ); - unsigned dimensionOfData; - inFiltration >> dimensionOfData; - - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensionOfData , false ); - - std::vector sizes; - sizes.reserve( dimensionOfData ); - for ( size_t i = 0 ; i != dimensionOfData ; ++i ) - { - int size_in_this_dimension; - inFiltration >> size_in_this_dimension; - if ( size_in_this_dimension < 0 ) - { - this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; - } - sizes.push_back( abs(size_in_this_dimension) ); - } - this->set_up_containers( sizes ); - - typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); - it = this->top_dimensional_cells_iterator_begin(); - - while ( !inFiltration.eof() ) - { - double filtrationLevel; - inFiltration >> filtrationLevel; - if ( inFiltration.eof() )break; - - if ( dbg ) - { - cerr << "Cell of an index : " - << it.compute_index_in_bitmap() - << " and dimension: " - << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) - << " get the value : " << filtrationLevel << endl; - } - this->get_cell_data(*it) = filtrationLevel; - ++it; - } - inFiltration.close(); - this->impose_lower_star_filtration(); - -/* - char* filename = (char*)perseus_style_file; - //char* filename = "combustionWithPeriodicBoundaryConditions/v0/tV0_000000.float"; - ifstream file( filename , ios::binary | ios::ate ); - unsigned realSizeOfFile = file.tellg(); - file.close(); - realSizeOfFile = realSizeOfFile/sizeof(T); - - unsigned w, h, d; - - w = h = d = ceil(pow( realSizeOfFile , (double)(1/(double)3) )); - - T* slice = new T[w*h*d]; - if (slice == NULL) - { - cerr << "Allocation error, cannot allocate " << w*h*d*sizeof(T) << " bytes to store the data from the file. The program will now terminate \n"; - exit(EXIT_FAILURE); - } - - FILE* fp; - if ((fp=fopen( filename, "rb" )) == NULL ) - { - cerr << "Cannot open the file: " << filename << ". The program will now terminate \n"; - exit(1); - } - - clock_t read_begin = clock(); - fread( slice,4,w*h*d,fp ); - fclose(fp); - cerr << "Time of reading the file : " << double(clock() - read_begin) / CLOCKS_PER_SEC << endl; - - - clock_t begin_creation_bitap = clock(); - std::vector data(slice,slice+w*h*d); - delete[] slice; - std::vector< unsigned > sizes; - sizes.push_back(w); - sizes.push_back(w); - sizes.push_back(w); - - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->directions_in_which_periodic_b_cond_are_to_be_imposed.push_back( true ); - this->set_up_containers( sizes ); - - size_t i = 0; - for ( typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin() ; it != this->top_dimensional_cells_iterator_end() ; ++it ) - { - *it = data[i]; - ++i; - } - this->impose_lower_star_filtration(); - cerr << "Time of creation of a bitmap : " << double(clock() - begin_creation_bitap ) / CLOCKS_PER_SEC << endl; - */ -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& sizes ) -{ - this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( sizes.size() , false ); - this->set_up_containers( sizes ); -} - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells ) -{ - std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector( dimensions.size() , false ); - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - - - - - -template -Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base( const std::vector& dimensions , const std::vector& topDimensionalCells , const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed ) -{ - this->construct_complex_based_on_top_dimensional_cells( dimensions , topDimensionalCells , directions_in_which_periodic_b_cond_are_to_be_imposed ); -} - -//***********************Methods************************// - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell( size_t cell )const -{ - bool dbg = false; - if ( dbg ){cerr << "Computations of boundary of a cell : " << cell << endl;} - - std::vector< size_t > boundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - //this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. - - if ( position%2 == 1 ) - { - //if there are no periodic boundary conditions in this direction, we do not have to do anything. - if ( !directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //cerr << "A\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. - if ( position != 2*this->sizes[ i-1 ]-1 ) - { - //cerr << "B\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell + this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell + this->multipliers[ i-1 ] << " ";} - } - else - { - //cerr << "C\n"; - boundary_elements.push_back( cell - this->multipliers[ i-1 ] ); - boundary_elements.push_back( cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] ); - if (dbg){cerr << cell - this->multipliers[ i-1 ] << " " << cell - (2*this->sizes[ i-1 ]-1)*this->multipliers[ i-1 ] << " ";} - } - } - } - cell1 = cell1%this->multipliers[i-1]; - } - return boundary_elements; -} - -template -std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell( size_t cell )const -{ - std::vector counter = this->compute_counter_for_given_cell( cell ); - std::vector< size_t > coboundary_elements; - size_t cell1 = cell; - for ( size_t i = this->multipliers.size() ; i != 0 ; --i ) - { - unsigned position = cell1/this->multipliers[i-1]; - //if the cell has zero length in this direction, then it will have cbd in this direction. - if ( position%2 == 0 ) - { - if ( !this->directions_in_which_periodic_b_cond_are_to_be_imposed[i-1] ) - { - //no periodic boundary conditions in this direction - if ( (counter[i-1] != 0) && (cell > this->multipliers[i-1]) ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - } - if ( (counter[i-1] != 2*this->sizes[i-1]) && (cell + this->multipliers[i-1] < this->data.size()) ) - { - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - } - else - { - //we want to have periodic boundary conditions in this direction - if ( counter[i-1] != 0 ) - { - coboundary_elements.push_back( cell - this->multipliers[i-1] ); - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - } - else - { - //in this case counter[i-1] == 0. - coboundary_elements.push_back( cell + this->multipliers[i-1] ); - coboundary_elements.push_back( cell + (2*this->sizes[ i-1 ]-1)*this->multipliers[i-1] ); - } - } - } - - cell1 = cell1%this->multipliers[i-1]; - } - return coboundary_elements; -} - - - -}//Cubical_complex -}//namespace Gudhi +*/ +template +class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base { + public: + // constructors that take an extra parameter: + + /** + * Default constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base() { } + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following + * parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of booleans. If + * at i-th position of this vector there is true value, that means that periodic boundary conditions are to be + * imposed in this direction. In case of false, the periodic boundary conditions will not be imposed in the direction + * i. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& sizes, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed); + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the name of Perseus + * style file as an input. Please consult the documentation about the specification of the file. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base(const char* perseusStyleFile); + /** + * A constructor of Bitmap_cubical_complex_periodic_boundary_conditions_base class that takes the following + * parameters: (1) vector with numbers of top dimensional cells in all dimensions and (2) vector of top dimensional + * cells (ordered lexicographically) and (3) vector of booleans. If at i-th position of this vector there is true + * value, that means that periodic boundary conditions are to be imposed in this direction. In case of false, the + * periodic boundary conditions will not be imposed in the direction i. + */ + Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& dimensions, + const std::vector& topDimensionalCells, + const std::vector< bool >& directions_in_which_periodic_b_cond_are_to_be_imposed); + + /** + * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class. + **/ + virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base(){} + + // overwritten methods co compute boundary and coboundary + /** + * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + virtual std::vector< size_t > get_boundary_of_a_cell(size_t cell)const; + + /** + * A version of a function that return coboundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + */ + virtual std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + + protected: + std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; + + void set_up_containers(const std::vector& sizes) { + unsigned multiplier = 1; + for (size_t i = 0; i != sizes.size(); ++i) { + this->sizes.push_back(sizes[i]); + this->multipliers.push_back(multiplier); + + if (directions_in_which_periodic_b_cond_are_to_be_imposed[i]) { + multiplier *= 2 * sizes[i]; + } else { + multiplier *= 2 * sizes[i] + 1; + } + } + // std::reverse( this->sizes.begin() , this->sizes.end() ); + this->data = std::vector(multiplier, std::numeric_limits::max()); + this->total_number_of_cells = multiplier; + } + Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& sizes); + Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& dimensions, + const std::vector& topDimensionalCells); + void construct_complex_based_on_top_dimensional_cells(const std::vector& dimensions, + const std::vector& topDimensionalCells, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed); +}; + +template +void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_complex_based_on_top_dimensional_cells(const std::vector& dimensions, + const std::vector& topDimensionalCells, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed) { + this->directions_in_which_periodic_b_cond_are_to_be_imposed = directions_in_which_periodic_b_cond_are_to_be_imposed; + this->set_up_containers(dimensions); + + size_t i = 0; + for (typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { + this->get_cell_data(*it) = topDimensionalCells[i]; + ++i; + } + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& sizes, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed) { + this->directions_in_which_periodic_b_cond_are_to_be_imposed(directions_in_which_periodic_b_cond_are_to_be_imposed); + this->set_up_containers(sizes); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base(const char* perseus_style_file) { + // for Perseus style files: + bool dbg = false; + + std::ifstream inFiltration; + inFiltration.open(perseus_style_file); + unsigned dimensionOfData; + inFiltration >> dimensionOfData; + + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector(dimensionOfData, false); + + std::vector sizes; + sizes.reserve(dimensionOfData); + for (size_t i = 0; i != dimensionOfData; ++i) { + int size_in_this_dimension; + inFiltration >> size_in_this_dimension; + if (size_in_this_dimension < 0) { + this->directions_in_which_periodic_b_cond_are_to_be_imposed[i] = true; + } + sizes.push_back(abs(size_in_this_dimension)); + } + this->set_up_containers(sizes); + + typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it(*this); + it = this->top_dimensional_cells_iterator_begin(); + + while (!inFiltration.eof()) { + double filtrationLevel; + inFiltration >> filtrationLevel; + if (inFiltration.eof())break; + + if (dbg) { + std::cerr << "Cell of an index : " + << it.compute_index_in_bitmap() + << " and dimension: " + << this->get_dimension_of_a_cell(it.compute_index_in_bitmap()) + << " get the value : " << filtrationLevel << std::endl; + } + this->get_cell_data(*it) = filtrationLevel; + ++it; + } + inFiltration.close(); + this->impose_lower_star_filtration(); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& sizes) { + this->directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector(sizes.size(), false); + this->set_up_containers(sizes); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base::Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& dimensions, + const std::vector& topDimensionalCells) { + std::vector directions_in_which_periodic_b_cond_are_to_be_imposed = std::vector(dimensions.size(), false); + this->construct_complex_based_on_top_dimensional_cells(dimensions, topDimensionalCells, + directions_in_which_periodic_b_cond_are_to_be_imposed); +} + +template +Bitmap_cubical_complex_periodic_boundary_conditions_base:: +Bitmap_cubical_complex_periodic_boundary_conditions_base(const std::vector& dimensions, + const std::vector& topDimensionalCells, + const std::vector& directions_in_which_periodic_b_cond_are_to_be_imposed) { + this->construct_complex_based_on_top_dimensional_cells(dimensions, topDimensionalCells, + directions_in_which_periodic_b_cond_are_to_be_imposed); +} + +// ***********************Methods************************ // + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_boundary_of_a_cell(size_t cell) const { + bool dbg = false; + if (dbg) { + std::cerr << "Computations of boundary of a cell : " << cell << std::endl; + } + + std::vector< size_t > boundary_elements; + size_t cell1 = cell; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / this->multipliers[i - 1]; + // this cell have a nonzero length in this direction, therefore we can compute its boundary in this direction. + + if (position % 2 == 1) { + // if there are no periodic boundary conditions in this direction, we do not have to do anything. + if (!directions_in_which_periodic_b_cond_are_to_be_imposed[i - 1]) { + // std::cerr << "A\n"; + boundary_elements.push_back(cell - this->multipliers[ i - 1 ]); + boundary_elements.push_back(cell + this->multipliers[ i - 1 ]); + if (dbg) { + std::cerr << cell - this->multipliers[ i - 1 ] << " " << cell + this->multipliers[ i - 1 ] << " "; + } + } else { + // in this direction we have to do boundary conditions. Therefore, we need to check if we are not at the end. + if (position != 2 * this->sizes[ i - 1 ] - 1) { + // std::cerr << "B\n"; + boundary_elements.push_back(cell - this->multipliers[ i - 1 ]); + boundary_elements.push_back(cell + this->multipliers[ i - 1 ]); + if (dbg) { + std::cerr << cell - this->multipliers[ i - 1 ] << " " << cell + this->multipliers[ i - 1 ] << " "; + } + } else { + // std::cerr << "C\n"; + boundary_elements.push_back(cell - this->multipliers[ i - 1 ]); + boundary_elements.push_back(cell - (2 * this->sizes[ i - 1 ] - 1) * this->multipliers[ i - 1 ]); + if (dbg) { + std::cerr << cell - this->multipliers[ i - 1 ] << " " << + cell - (2 * this->sizes[ i - 1 ] - 1) * this->multipliers[ i - 1 ] << " "; + } + } + } + } + cell1 = cell1 % this->multipliers[i - 1]; + } + return boundary_elements; +} + +template +std::vector< size_t > Bitmap_cubical_complex_periodic_boundary_conditions_base::get_coboundary_of_a_cell(size_t cell) const { + std::vector counter = this->compute_counter_for_given_cell(cell); + std::vector< size_t > coboundary_elements; + size_t cell1 = cell; + for (size_t i = this->multipliers.size(); i != 0; --i) { + unsigned position = cell1 / this->multipliers[i - 1]; + // if the cell has zero length in this direction, then it will have cbd in this direction. + if (position % 2 == 0) { + if (!this->directions_in_which_periodic_b_cond_are_to_be_imposed[i - 1]) { + // no periodic boundary conditions in this direction + if ((counter[i - 1] != 0) && (cell > this->multipliers[i - 1])) { + coboundary_elements.push_back(cell - this->multipliers[i - 1]); + } + if ((counter[i - 1] != 2 * this->sizes[i - 1]) && (cell + this->multipliers[i - 1] < this->data.size())) { + coboundary_elements.push_back(cell + this->multipliers[i - 1]); + } + } else { + // we want to have periodic boundary conditions in this direction + if (counter[i - 1] != 0) { + coboundary_elements.push_back(cell - this->multipliers[i - 1]); + coboundary_elements.push_back(cell + this->multipliers[i - 1]); + } else { + // in this case counter[i-1] == 0. + coboundary_elements.push_back(cell + this->multipliers[i - 1]); + coboundary_elements.push_back(cell + (2 * this->sizes[ i - 1 ] - 1) * this->multipliers[i - 1]); + } + } + } + + cell1 = cell1 % this->multipliers[i - 1]; + } + return coboundary_elements; +} + +} // namespace Cubical_complex + +} // namespace Gudhi + +#endif // BITMAP_CUBICAL_COMPLEX_PERIODIC_BOUNDARY_CONDITIONS_BASE_H_ diff --git a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp index 35c54ade..a9162cee 100644 --- a/src/Bitmap_cubical_complex/test/Bitmap_test.cpp +++ b/src/Bitmap_cubical_complex/test/Bitmap_test.cpp @@ -1,105 +1,79 @@ +/* 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): Pawel Dlotko + * + * 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_DYN_LINK +#define BOOST_TEST_MODULE "cubical_complex" +#include + #include #include #include -#include // standard stuff #include #include +#include -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "cubical_complex" -#include +typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_base Bitmap_cubical_complex_base; +typedef Gudhi::Cubical_complex::Bitmap_cubical_complex Bitmap_cubical_complex; -using namespace std; -using namespace Gudhi; -using namespace Gudhi::Cubical_complex; -using namespace Gudhi::persistent_cohomology; +typedef Gudhi::Cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base +Bitmap_cubical_complex_periodic_boundary_conditions_base; +typedef Gudhi::Cubical_complex::Bitmap_cubical_complex +Bitmap_cubical_complex_periodic_boundary_conditions; +BOOST_AUTO_TEST_CASE(check_dimension) { + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); + std::vector dimensions({3, 3}); -BOOST_AUTO_TEST_CASE(check_dimension) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); BOOST_CHECK(increasing.dimension() == 2); } BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { - std::vector< double > expectedFiltrationValues1; - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(100); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - expectedFiltrationValues1.push_back(0); - - std::vector< double > expectedFiltrationValues2; - expectedFiltrationValues2.push_back(1); - expectedFiltrationValues2.push_back(2); - expectedFiltrationValues2.push_back(3); - expectedFiltrationValues2.push_back(4); - expectedFiltrationValues2.push_back(5); - expectedFiltrationValues2.push_back(6); - expectedFiltrationValues2.push_back(7); - expectedFiltrationValues2.push_back(8); - expectedFiltrationValues2.push_back(9); - - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector< double > oneDimensionalCycle; - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(100); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - oneDimensionalCycle.push_back(0); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); - Bitmap_cubical_complex< Bitmap_cubical_complex_base > hole(dimensions, oneDimensionalCycle); + std::vector< double > expectedFiltrationValues1({0, 0, 0, 0, 100, 0, 0, 0, 0}); + + std::vector< double > expectedFiltrationValues2({1, 2, 3, 4, 5, 6, 7, 8, 9}); + + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); + + std::vector< double > oneDimensionalCycle({0, 0, 0, 0, 100, 0, 0, 0, 0}); + + std::vector dimensions({3, 3}); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex hole(dimensions, oneDimensionalCycle); int i = 0; - for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = increasing.top_dimensional_cells_iterator_begin(); it != increasing.top_dimensional_cells_iterator_end(); ++it) { BOOST_CHECK(increasing.get_cell_data(*it) == expectedFiltrationValues2[i]); ++i; } i = 0; - for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Top_dimensional_cells_iterator + for (Bitmap_cubical_complex::Top_dimensional_cells_iterator it = hole.top_dimensional_cells_iterator_begin(); it != hole.top_dimensional_cells_iterator_end(); ++it) { BOOST_CHECK(hole.get_cell_data(*it) == expectedFiltrationValues1[i]); ++i; @@ -107,7 +81,6 @@ BOOST_AUTO_TEST_CASE(topDimensionalCellsIterator_test) { } BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { - std::vector boundary0; std::vector boundary1; boundary1.push_back(0); @@ -294,22 +267,11 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); + std::vector dimensions({3, 3}); - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); for (size_t i = 0; i != increasing.size(); ++i) { std::vector< size_t > bd = increasing.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { @@ -319,22 +281,11 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_1) { } BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); + std::vector dimensions({3, 3}); - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector coboundaryElements; @@ -429,27 +380,15 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_2) { BOOST_CHECK(coboundaryElements[number] == bd[j]); ++number; } - } } BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); + + std::vector dimensions({3, 3}); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector dim; dim.push_back(0); @@ -508,22 +447,11 @@ BOOST_AUTO_TEST_CASE(compute_boundary_test_3) { } BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { - std::vector< double > increasingFiltrationOfTopDimensionalCells; - increasingFiltrationOfTopDimensionalCells.push_back(1); - increasingFiltrationOfTopDimensionalCells.push_back(2); - increasingFiltrationOfTopDimensionalCells.push_back(3); - increasingFiltrationOfTopDimensionalCells.push_back(4); - increasingFiltrationOfTopDimensionalCells.push_back(5); - increasingFiltrationOfTopDimensionalCells.push_back(6); - increasingFiltrationOfTopDimensionalCells.push_back(7); - increasingFiltrationOfTopDimensionalCells.push_back(8); - increasingFiltrationOfTopDimensionalCells.push_back(9); - - std::vector dimensions; - dimensions.push_back(3); - dimensions.push_back(3); - - Bitmap_cubical_complex< Bitmap_cubical_complex_base > increasing(dimensions, increasingFiltrationOfTopDimensionalCells); + std::vector< double > increasingFiltrationOfTopDimensionalCells({1, 2, 3, 4, 5, 6, 7, 8, 9}); + + std::vector dimensions({3, 3}); + + Bitmap_cubical_complex increasing(dimensions, increasingFiltrationOfTopDimensionalCells); std::vector< unsigned > dim; dim.push_back(0); @@ -628,104 +556,93 @@ BOOST_AUTO_TEST_CASE(Filtration_simplex_iterator_test) { fil.push_back(9); - Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Filtration_simplex_range range = increasing.filtration_simplex_range(); + Bitmap_cubical_complex::Filtration_simplex_range range = increasing.filtration_simplex_range(); size_t position = 0; - for (Bitmap_cubical_complex< Bitmap_cubical_complex_base >::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { + for (Bitmap_cubical_complex::Filtration_simplex_iterator it = range.begin(); it != range.end(); ++it) { BOOST_CHECK(increasing.dimension(*it) == dim[position]); BOOST_CHECK(increasing.filtration(*it) == fil[position]); ++position; } } - - - + BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) { - std::vector< double > filtration; - filtration.push_back(0); - filtration.push_back(0); - filtration.push_back(0); - filtration.push_back(0); - - - std::vector dimensions; - dimensions.push_back(2); - dimensions.push_back(2); - - std::vector periodic_directions; - periodic_directions.push_back(true); - periodic_directions.push_back(true); - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtration,periodic_directions); - BOOST_CHECK(cmplx.dimension() == 2); - - + std::vector< double > filtration({0, 0, 0, 0}); + + std::vector dimensions({2, 2}); + + std::vector periodic_directions({true, true}); + + Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtration, periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + std::vector boundary0; - std::vector boundary1; - boundary1.push_back(0); - boundary1.push_back(2); - std::vector boundary2; - std::vector boundary3; - boundary3.push_back(2); - boundary3.push_back(0); - std::vector boundary4; - boundary4.push_back(0); - boundary4.push_back(8); - std::vector boundary5; - boundary5.push_back(1); - boundary5.push_back(9); - boundary5.push_back(4); - boundary5.push_back(6); - std::vector boundary6; - boundary6.push_back(2); - boundary6.push_back(10); - std::vector boundary7; - boundary7.push_back(3); - boundary7.push_back(11); - boundary7.push_back(6); - boundary7.push_back(4); - std::vector boundary8; - std::vector boundary9; - boundary9.push_back(8); - boundary9.push_back(10); - std::vector boundary10; - std::vector boundary11; - boundary11.push_back(10); - boundary11.push_back(8); - std::vector boundary12; - boundary12.push_back(8); - boundary12.push_back(0); - std::vector boundary13; - boundary13.push_back(9); - boundary13.push_back(1); - boundary13.push_back(12); - boundary13.push_back(14); - std::vector boundary14; - boundary14.push_back(10); - boundary14.push_back(2); - std::vector boundary15; - boundary15.push_back(11); - boundary15.push_back(3); - boundary15.push_back(14); - boundary15.push_back(12); - - std::vector< std::vector > boundaries; - boundaries.push_back( boundary0 ); - boundaries.push_back( boundary1 ); - boundaries.push_back( boundary2 ); - boundaries.push_back( boundary3 ); - boundaries.push_back( boundary4 ); - boundaries.push_back( boundary5 ); - boundaries.push_back( boundary6 ); - boundaries.push_back( boundary7 ); - boundaries.push_back( boundary8 ); - boundaries.push_back( boundary9 ); - boundaries.push_back( boundary10 ); - boundaries.push_back( boundary11 ); - boundaries.push_back( boundary12 ); - boundaries.push_back( boundary13 ); - boundaries.push_back( boundary14 ); - boundaries.push_back( boundary15 ); - + std::vector boundary1; + boundary1.push_back(0); + boundary1.push_back(2); + std::vector boundary2; + std::vector boundary3; + boundary3.push_back(2); + boundary3.push_back(0); + std::vector boundary4; + boundary4.push_back(0); + boundary4.push_back(8); + std::vector boundary5; + boundary5.push_back(1); + boundary5.push_back(9); + boundary5.push_back(4); + boundary5.push_back(6); + std::vector boundary6; + boundary6.push_back(2); + boundary6.push_back(10); + std::vector boundary7; + boundary7.push_back(3); + boundary7.push_back(11); + boundary7.push_back(6); + boundary7.push_back(4); + std::vector boundary8; + std::vector boundary9; + boundary9.push_back(8); + boundary9.push_back(10); + std::vector boundary10; + std::vector boundary11; + boundary11.push_back(10); + boundary11.push_back(8); + std::vector boundary12; + boundary12.push_back(8); + boundary12.push_back(0); + std::vector boundary13; + boundary13.push_back(9); + boundary13.push_back(1); + boundary13.push_back(12); + boundary13.push_back(14); + std::vector boundary14; + boundary14.push_back(10); + boundary14.push_back(2); + std::vector boundary15; + boundary15.push_back(11); + boundary15.push_back(3); + boundary15.push_back(14); + boundary15.push_back(12); + + std::vector< std::vector > boundaries; + boundaries.push_back(boundary0); + boundaries.push_back(boundary1); + boundaries.push_back(boundary2); + boundaries.push_back(boundary3); + boundaries.push_back(boundary4); + boundaries.push_back(boundary5); + boundaries.push_back(boundary6); + boundaries.push_back(boundary7); + boundaries.push_back(boundary8); + boundaries.push_back(boundary9); + boundaries.push_back(boundary10); + boundaries.push_back(boundary11); + boundaries.push_back(boundary12); + boundaries.push_back(boundary13); + boundaries.push_back(boundary14); + boundaries.push_back(boundary15); + for (size_t i = 0; i != cmplx.size(); ++i) { std::vector< size_t > bd = cmplx.get_boundary_of_a_cell(i); for (size_t j = 0; j != bd.size(); ++j) { @@ -733,759 +650,729 @@ BOOST_AUTO_TEST_CASE(boudary_operator_2d_bitmap_with_periodic_bcond) { } } } - - - - - - + BOOST_AUTO_TEST_CASE(coboudary_operator_2d_bitmap_with_periodic_bcond) { - std::vector< double > filtration; - filtration.push_back(0); - filtration.push_back(0); - filtration.push_back(0); - filtration.push_back(0); - - - std::vector dimensions; - dimensions.push_back(2); - dimensions.push_back(2); - - std::vector periodic_directions; - periodic_directions.push_back(true); - periodic_directions.push_back(true); - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtration,periodic_directions); - BOOST_CHECK(cmplx.dimension() == 2); - - - std::vector coboundary0; - coboundary0.push_back(4); - coboundary0.push_back(12); - coboundary0.push_back(1); - coboundary0.push_back(3); - std::vector coboundary1; - coboundary1.push_back(5); - coboundary1.push_back(13); - std::vector coboundary2; - coboundary2.push_back(6); - coboundary2.push_back(14); - coboundary2.push_back(1); - coboundary2.push_back(3); - std::vector coboundary3; - coboundary3.push_back(7); - coboundary3.push_back(15); - std::vector coboundary4; - coboundary4.push_back(5); - coboundary4.push_back(7); - std::vector coboundary5; - std::vector coboundary6; - coboundary6.push_back(5); - coboundary6.push_back(7); - std::vector coboundary7; - std::vector coboundary8; - coboundary8.push_back(4); - coboundary8.push_back(12); - coboundary8.push_back(9); - coboundary8.push_back(11); - std::vector coboundary9; - coboundary9.push_back(5); - coboundary9.push_back(13); - std::vector coboundary10; - coboundary10.push_back(6); - coboundary10.push_back(14); - coboundary10.push_back(9); - coboundary10.push_back(11); - std::vector coboundary11; - coboundary11.push_back(7); - coboundary11.push_back(15); - std::vector coboundary12; - coboundary12.push_back(13); - coboundary12.push_back(15); - std::vector coboundary13; - std::vector coboundary14; - coboundary14.push_back(13); - coboundary14.push_back(15); + std::vector< double > filtration({0, 0, 0, 0}); + + std::vector dimensions({2, 2}); + + std::vector periodic_directions({true, true}); + + Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtration, periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector coboundary0; + coboundary0.push_back(4); + coboundary0.push_back(12); + coboundary0.push_back(1); + coboundary0.push_back(3); + std::vector coboundary1; + coboundary1.push_back(5); + coboundary1.push_back(13); + std::vector coboundary2; + coboundary2.push_back(6); + coboundary2.push_back(14); + coboundary2.push_back(1); + coboundary2.push_back(3); + std::vector coboundary3; + coboundary3.push_back(7); + coboundary3.push_back(15); + std::vector coboundary4; + coboundary4.push_back(5); + coboundary4.push_back(7); + std::vector coboundary5; + std::vector coboundary6; + coboundary6.push_back(5); + coboundary6.push_back(7); + std::vector coboundary7; + std::vector coboundary8; + coboundary8.push_back(4); + coboundary8.push_back(12); + coboundary8.push_back(9); + coboundary8.push_back(11); + std::vector coboundary9; + coboundary9.push_back(5); + coboundary9.push_back(13); + std::vector coboundary10; + coboundary10.push_back(6); + coboundary10.push_back(14); + coboundary10.push_back(9); + coboundary10.push_back(11); + std::vector coboundary11; + coboundary11.push_back(7); + coboundary11.push_back(15); + std::vector coboundary12; + coboundary12.push_back(13); + coboundary12.push_back(15); + std::vector coboundary13; + std::vector coboundary14; + coboundary14.push_back(13); + coboundary14.push_back(15); std::vector coboundary15; - - std::vector< std::vector > coboundaries; - coboundaries.push_back( coboundary0 ); - coboundaries.push_back( coboundary1 ); - coboundaries.push_back( coboundary2 ); - coboundaries.push_back( coboundary3 ); - coboundaries.push_back( coboundary4 ); - coboundaries.push_back( coboundary5 ); - coboundaries.push_back( coboundary6 ); - coboundaries.push_back( coboundary7 ); - coboundaries.push_back( coboundary8 ); - coboundaries.push_back( coboundary9 ); - coboundaries.push_back( coboundary10 ); - coboundaries.push_back( coboundary11 ); - coboundaries.push_back( coboundary12 ); - coboundaries.push_back( coboundary13 ); - coboundaries.push_back( coboundary14 ); - coboundaries.push_back( coboundary15 ); - + + std::vector< std::vector > coboundaries; + coboundaries.push_back(coboundary0); + coboundaries.push_back(coboundary1); + coboundaries.push_back(coboundary2); + coboundaries.push_back(coboundary3); + coboundaries.push_back(coboundary4); + coboundaries.push_back(coboundary5); + coboundaries.push_back(coboundary6); + coboundaries.push_back(coboundary7); + coboundaries.push_back(coboundary8); + coboundaries.push_back(coboundary9); + coboundaries.push_back(coboundary10); + coboundaries.push_back(coboundary11); + coboundaries.push_back(coboundary12); + coboundaries.push_back(coboundary13); + coboundaries.push_back(coboundary14); + coboundaries.push_back(coboundary15); + for (size_t i = 0; i != cmplx.size(); ++i) { std::vector< size_t > cbd = cmplx.get_coboundary_of_a_cell(i); for (size_t j = 0; j != cbd.size(); ++j) { BOOST_CHECK(coboundaries[i][j] == cbd[j]); } } -} - - - - - - - +} + BOOST_AUTO_TEST_CASE(bitmap_2d_with_periodic_bcond_filtration) { - std::vector< double > filtrationOrg; - filtrationOrg.push_back(0); - filtrationOrg.push_back(1); - filtrationOrg.push_back(2); - filtrationOrg.push_back(3); - - - std::vector dimensions; - dimensions.push_back(2); - dimensions.push_back(2); - - std::vector periodic_directions; - periodic_directions.push_back(true); - periodic_directions.push_back(true); - - Bitmap_cubical_complex< Bitmap_cubical_complex_periodic_boundary_conditions_base > cmplx(dimensions, filtrationOrg,periodic_directions); - BOOST_CHECK(cmplx.dimension() == 2); - - - std::vector filtration; - filtration.push_back(0);//0 - filtration.push_back(0);//1 - filtration.push_back(0);//2 - filtration.push_back(1);//3 - filtration.push_back(0);//4 - filtration.push_back(0);//5 - filtration.push_back(0);//6 - filtration.push_back(1);//7 - filtration.push_back(0);//8 - filtration.push_back(0);//9 - filtration.push_back(0);//10 - filtration.push_back(1);//11 - filtration.push_back(2);//12 - filtration.push_back(2);//13 - filtration.push_back(2);//14 - filtration.push_back(3);//15 - - - for (size_t i = 0; i != cmplx.size(); ++i) - { - BOOST_CHECK( filtration[i] == cmplx.get_cell_data(i) ); + std::vector< double > filtrationOrg({0, 1, 2, 3}); + + std::vector dimensions({2, 2}); + + std::vector periodic_directions({true, true}); + + Bitmap_cubical_complex_periodic_boundary_conditions cmplx(dimensions, filtrationOrg, periodic_directions); + BOOST_CHECK(cmplx.dimension() == 2); + + + std::vector filtration; + filtration.push_back(0); // 0 + filtration.push_back(0); // 1 + filtration.push_back(0); // 2 + filtration.push_back(1); // 3 + filtration.push_back(0); // 4 + filtration.push_back(0); // 5 + filtration.push_back(0); // 6 + filtration.push_back(1); // 7 + filtration.push_back(0); // 8 + filtration.push_back(0); // 9 + filtration.push_back(0); // 10 + filtration.push_back(1); // 11 + filtration.push_back(2); // 12 + filtration.push_back(2); // 13 + filtration.push_back(2); // 14 + filtration.push_back(3); // 15 + + + for (size_t i = 0; i != cmplx.size(); ++i) { + BOOST_CHECK(filtration[i] == cmplx.get_cell_data(i)); } -} - -BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check) -{ - std::vector< double > expected_filtration; - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - - std::vector expected_dimension; - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - - std::vector expected_boundary; - expected_boundary.push_back(0); - expected_boundary.push_back(2); - expected_boundary.push_back(2); - expected_boundary.push_back(4); - expected_boundary.push_back(0); - expected_boundary.push_back(10); - expected_boundary.push_back(1); - expected_boundary.push_back(11); - expected_boundary.push_back(5); - expected_boundary.push_back(7); - expected_boundary.push_back(2); - expected_boundary.push_back(12); - expected_boundary.push_back(3); - expected_boundary.push_back(13); - expected_boundary.push_back(7); - expected_boundary.push_back(9); - expected_boundary.push_back(4); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(12); - expected_boundary.push_back(12); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(20); - expected_boundary.push_back(11); - expected_boundary.push_back(21); - expected_boundary.push_back(15); - expected_boundary.push_back(17); - expected_boundary.push_back(12); - expected_boundary.push_back(22); - expected_boundary.push_back(13); - expected_boundary.push_back(23); - expected_boundary.push_back(17); - expected_boundary.push_back(19); - expected_boundary.push_back(14); - expected_boundary.push_back(24); - expected_boundary.push_back(20); - expected_boundary.push_back(22); - expected_boundary.push_back(22); - expected_boundary.push_back(24); - - - std::vector expected_coboundary; - expected_coboundary.push_back(5); - expected_coboundary.push_back(1); - expected_coboundary.push_back(6); - expected_coboundary.push_back(7); - expected_coboundary.push_back(1); - expected_coboundary.push_back(3); - expected_coboundary.push_back(8); - expected_coboundary.push_back(9); - expected_coboundary.push_back(3); - expected_coboundary.push_back(6); - expected_coboundary.push_back(6); - expected_coboundary.push_back(8); - expected_coboundary.push_back(8); - expected_coboundary.push_back(5); - expected_coboundary.push_back(15); - expected_coboundary.push_back(11); - expected_coboundary.push_back(6); - expected_coboundary.push_back(16); - expected_coboundary.push_back(7); - expected_coboundary.push_back(17); - expected_coboundary.push_back(11); - expected_coboundary.push_back(13); - expected_coboundary.push_back(8); - expected_coboundary.push_back(18); - expected_coboundary.push_back(9); - expected_coboundary.push_back(19); - expected_coboundary.push_back(13); - expected_coboundary.push_back(16); - expected_coboundary.push_back(16); - expected_coboundary.push_back(18); - expected_coboundary.push_back(18); - expected_coboundary.push_back(15); - expected_coboundary.push_back(21); - expected_coboundary.push_back(16); - expected_coboundary.push_back(17); - expected_coboundary.push_back(21); - expected_coboundary.push_back(23); - expected_coboundary.push_back(18); - expected_coboundary.push_back(19); - expected_coboundary.push_back(23); - - - - std::vector< unsigned > sizes(2); - sizes[0] = 2; - sizes[1] = 2; - - std::vector< double > data(4); - data[0] = 0; - data[1] = 1; - data[2] = 2; - data[3] = 3; - - Bitmap_cubical_complex_base ba( sizes , data ); - int i = 0; - int bd_it = 0; - int cbd_it = 0; - for ( Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin() ; it != ba.all_cells_iterator_end() ; ++it ) - { - BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); - BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); - - Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); - for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) - { - BOOST_CHECK( expected_boundary[bd_it] == *bd ); - ++bd_it; - } - - Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); - for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) - { - BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); - ++cbd_it; - } - ++i; - } -} - - - - - - - - -BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check_2) -{ - std::vector< double > expected_filtration; - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - - std::vector expected_dimension; - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - - std::vector expected_boundary; - expected_boundary.push_back(0); - expected_boundary.push_back(2); - expected_boundary.push_back(2); - expected_boundary.push_back(4); - expected_boundary.push_back(0); - expected_boundary.push_back(10); - expected_boundary.push_back(1); - expected_boundary.push_back(11); - expected_boundary.push_back(5); - expected_boundary.push_back(7); - expected_boundary.push_back(2); - expected_boundary.push_back(12); - expected_boundary.push_back(3); - expected_boundary.push_back(13); - expected_boundary.push_back(7); - expected_boundary.push_back(9); - expected_boundary.push_back(4); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(12); - expected_boundary.push_back(12); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(20); - expected_boundary.push_back(11); - expected_boundary.push_back(21); - expected_boundary.push_back(15); - expected_boundary.push_back(17); - expected_boundary.push_back(12); - expected_boundary.push_back(22); - expected_boundary.push_back(13); - expected_boundary.push_back(23); - expected_boundary.push_back(17); - expected_boundary.push_back(19); - expected_boundary.push_back(14); - expected_boundary.push_back(24); - expected_boundary.push_back(20); - expected_boundary.push_back(22); - expected_boundary.push_back(22); - expected_boundary.push_back(24); - - - std::vector expected_coboundary; - expected_coboundary.push_back(5); - expected_coboundary.push_back(1); - expected_coboundary.push_back(6); - expected_coboundary.push_back(7); - expected_coboundary.push_back(1); - expected_coboundary.push_back(3); - expected_coboundary.push_back(8); - expected_coboundary.push_back(9); - expected_coboundary.push_back(3); - expected_coboundary.push_back(6); - expected_coboundary.push_back(6); - expected_coboundary.push_back(8); - expected_coboundary.push_back(8); - expected_coboundary.push_back(5); - expected_coboundary.push_back(15); - expected_coboundary.push_back(11); - expected_coboundary.push_back(6); - expected_coboundary.push_back(16); - expected_coboundary.push_back(7); - expected_coboundary.push_back(17); - expected_coboundary.push_back(11); - expected_coboundary.push_back(13); - expected_coboundary.push_back(8); - expected_coboundary.push_back(18); - expected_coboundary.push_back(9); - expected_coboundary.push_back(19); - expected_coboundary.push_back(13); - expected_coboundary.push_back(16); - expected_coboundary.push_back(16); - expected_coboundary.push_back(18); - expected_coboundary.push_back(18); - expected_coboundary.push_back(15); - expected_coboundary.push_back(21); - expected_coboundary.push_back(16); - expected_coboundary.push_back(17); - expected_coboundary.push_back(21); - expected_coboundary.push_back(23); - expected_coboundary.push_back(18); - expected_coboundary.push_back(19); - expected_coboundary.push_back(23); - - - - std::vector< unsigned > sizes(2); - sizes[0] = 2; - sizes[1] = 2; - - std::vector< double > data(4); - data[0] = 0; - data[1] = 1; - data[2] = 2; - data[3] = 3; - - Bitmap_cubical_complex_base ba( sizes , data ); - int i = 0; - int bd_it = 0; - int cbd_it = 0; - - Bitmap_cubical_complex_base::All_cells_range range(&ba); - for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) - { - BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); - BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); - - Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); - for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) - { - BOOST_CHECK( expected_boundary[bd_it] == *bd ); - ++bd_it; - } - - Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); - for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) - { - BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); - ++cbd_it; - } - ++i; - } -} - - - - - - -BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check) -{ - std::vector< double > expected_filtration; - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - - std::vector expected_dimension; - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(2); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - expected_dimension.push_back(1); - expected_dimension.push_back(0); - - std::vector expected_boundary; - expected_boundary.push_back(0); - expected_boundary.push_back(2); - expected_boundary.push_back(2); - expected_boundary.push_back(4); - expected_boundary.push_back(0); - expected_boundary.push_back(10); - expected_boundary.push_back(1); - expected_boundary.push_back(11); - expected_boundary.push_back(5); - expected_boundary.push_back(7); - expected_boundary.push_back(2); - expected_boundary.push_back(12); - expected_boundary.push_back(3); - expected_boundary.push_back(13); - expected_boundary.push_back(7); - expected_boundary.push_back(9); - expected_boundary.push_back(4); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(12); - expected_boundary.push_back(12); - expected_boundary.push_back(14); - expected_boundary.push_back(10); - expected_boundary.push_back(20); - expected_boundary.push_back(11); - expected_boundary.push_back(21); - expected_boundary.push_back(15); - expected_boundary.push_back(17); - expected_boundary.push_back(12); - expected_boundary.push_back(22); - expected_boundary.push_back(13); - expected_boundary.push_back(23); - expected_boundary.push_back(17); - expected_boundary.push_back(19); - expected_boundary.push_back(14); - expected_boundary.push_back(24); - expected_boundary.push_back(20); - expected_boundary.push_back(22); - expected_boundary.push_back(22); - expected_boundary.push_back(24); - - - std::vector expected_coboundary; - expected_coboundary.push_back(5); - expected_coboundary.push_back(1); - expected_coboundary.push_back(6); - expected_coboundary.push_back(7); - expected_coboundary.push_back(1); - expected_coboundary.push_back(3); - expected_coboundary.push_back(8); - expected_coboundary.push_back(9); - expected_coboundary.push_back(3); - expected_coboundary.push_back(6); - expected_coboundary.push_back(6); - expected_coboundary.push_back(8); - expected_coboundary.push_back(8); - expected_coboundary.push_back(5); - expected_coboundary.push_back(15); - expected_coboundary.push_back(11); - expected_coboundary.push_back(6); - expected_coboundary.push_back(16); - expected_coboundary.push_back(7); - expected_coboundary.push_back(17); - expected_coboundary.push_back(11); - expected_coboundary.push_back(13); - expected_coboundary.push_back(8); - expected_coboundary.push_back(18); - expected_coboundary.push_back(9); - expected_coboundary.push_back(19); - expected_coboundary.push_back(13); - expected_coboundary.push_back(16); - expected_coboundary.push_back(16); - expected_coboundary.push_back(18); - expected_coboundary.push_back(18); - expected_coboundary.push_back(15); - expected_coboundary.push_back(21); - expected_coboundary.push_back(16); - expected_coboundary.push_back(17); - expected_coboundary.push_back(21); - expected_coboundary.push_back(23); - expected_coboundary.push_back(18); - expected_coboundary.push_back(19); - expected_coboundary.push_back(23); - - - - std::vector< unsigned > sizes(2); - sizes[0] = 2; - sizes[1] = 2; - - std::vector< double > data(4); - data[0] = 0; - data[1] = 1; - data[2] = 2; - data[3] = 3; - - Bitmap_cubical_complex_base ba( sizes , data ); - int i = 0; - int bd_it = 0; - int cbd_it = 0; - - Bitmap_cubical_complex_base::All_cells_range range = ba.all_cells_range(); - for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) - { - BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); - BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); - - Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); - for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) - { - BOOST_CHECK( expected_boundary[bd_it] == *bd ); - ++bd_it; - } - - Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); - for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) - { - BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); - ++cbd_it; - } - ++i; - } -} - -BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check) -{ - std::vector< double > expected_filtration; - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(0); - expected_filtration.push_back(1); - expected_filtration.push_back(1); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(2); - expected_filtration.push_back(3); - expected_filtration.push_back(3); - - - std::vector< unsigned > sizes(2); - sizes[0] = 2; - sizes[1] = 2; - - std::vector< double > data(4); - data[0] = 0; - data[1] = 1; - data[2] = 2; - data[3] = 3; - - Bitmap_cubical_complex_base ba( sizes , data ); - int i = 0; - - Bitmap_cubical_complex_base::Top_dimensional_cells_range range = ba.top_dimensional_cells_range(); - for ( Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin() ; it != range.end() ; ++it ) - { - BOOST_CHECK( data[i] == ba.get_cell_data( *it ) ); - BOOST_CHECK( ba.get_dimension_of_a_cell( *it ) == 2 ); - ++i; - } -} +} +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + for ( Bitmap_cubical_complex_base::All_cells_iterator it = ba.all_cells_iterator_begin() ; it != ba.all_cells_iterator_end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + + + + + + + + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check_2) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + + Bitmap_cubical_complex_base::All_cells_range range(&ba); + for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + + + + + + +BOOST_AUTO_TEST_CASE(all_cells_iterator_and_boundary_iterators_in_Bitmap_cubical_complex_base_check_range_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + std::vector expected_dimension; + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(2); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + expected_dimension.push_back(1); + expected_dimension.push_back(0); + + std::vector expected_boundary; + expected_boundary.push_back(0); + expected_boundary.push_back(2); + expected_boundary.push_back(2); + expected_boundary.push_back(4); + expected_boundary.push_back(0); + expected_boundary.push_back(10); + expected_boundary.push_back(1); + expected_boundary.push_back(11); + expected_boundary.push_back(5); + expected_boundary.push_back(7); + expected_boundary.push_back(2); + expected_boundary.push_back(12); + expected_boundary.push_back(3); + expected_boundary.push_back(13); + expected_boundary.push_back(7); + expected_boundary.push_back(9); + expected_boundary.push_back(4); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(12); + expected_boundary.push_back(12); + expected_boundary.push_back(14); + expected_boundary.push_back(10); + expected_boundary.push_back(20); + expected_boundary.push_back(11); + expected_boundary.push_back(21); + expected_boundary.push_back(15); + expected_boundary.push_back(17); + expected_boundary.push_back(12); + expected_boundary.push_back(22); + expected_boundary.push_back(13); + expected_boundary.push_back(23); + expected_boundary.push_back(17); + expected_boundary.push_back(19); + expected_boundary.push_back(14); + expected_boundary.push_back(24); + expected_boundary.push_back(20); + expected_boundary.push_back(22); + expected_boundary.push_back(22); + expected_boundary.push_back(24); + + + std::vector expected_coboundary; + expected_coboundary.push_back(5); + expected_coboundary.push_back(1); + expected_coboundary.push_back(6); + expected_coboundary.push_back(7); + expected_coboundary.push_back(1); + expected_coboundary.push_back(3); + expected_coboundary.push_back(8); + expected_coboundary.push_back(9); + expected_coboundary.push_back(3); + expected_coboundary.push_back(6); + expected_coboundary.push_back(6); + expected_coboundary.push_back(8); + expected_coboundary.push_back(8); + expected_coboundary.push_back(5); + expected_coboundary.push_back(15); + expected_coboundary.push_back(11); + expected_coboundary.push_back(6); + expected_coboundary.push_back(16); + expected_coboundary.push_back(7); + expected_coboundary.push_back(17); + expected_coboundary.push_back(11); + expected_coboundary.push_back(13); + expected_coboundary.push_back(8); + expected_coboundary.push_back(18); + expected_coboundary.push_back(9); + expected_coboundary.push_back(19); + expected_coboundary.push_back(13); + expected_coboundary.push_back(16); + expected_coboundary.push_back(16); + expected_coboundary.push_back(18); + expected_coboundary.push_back(18); + expected_coboundary.push_back(15); + expected_coboundary.push_back(21); + expected_coboundary.push_back(16); + expected_coboundary.push_back(17); + expected_coboundary.push_back(21); + expected_coboundary.push_back(23); + expected_coboundary.push_back(18); + expected_coboundary.push_back(19); + expected_coboundary.push_back(23); + + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + int bd_it = 0; + int cbd_it = 0; + + Bitmap_cubical_complex_base::All_cells_range range = ba.all_cells_range(); + for ( Bitmap_cubical_complex_base::All_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( expected_filtration[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( expected_dimension[i] == ba.get_dimension_of_a_cell( *it ) ); + + Bitmap_cubical_complex_base::Boundary_range bdrange = ba.boundary_range(*it); + for ( Bitmap_cubical_complex_base::Boundary_iterator bd = bdrange.begin() ; bd != bdrange.end() ; ++bd ) + { + BOOST_CHECK( expected_boundary[bd_it] == *bd ); + ++bd_it; + } + + Bitmap_cubical_complex_base::Coboundary_range cbdrange = ba.coboundary_range(*it); + for ( Bitmap_cubical_complex_base::Coboundary_iterator cbd = cbdrange.begin() ; cbd != cbdrange.end() ; ++cbd ) + { + BOOST_CHECK( expected_coboundary[cbd_it] == *cbd ); + ++cbd_it; + } + ++i; + } +} + +BOOST_AUTO_TEST_CASE(Top_dimensional_cells_iterator_range_check) +{ + std::vector< double > expected_filtration; + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(0); + expected_filtration.push_back(1); + expected_filtration.push_back(1); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(2); + expected_filtration.push_back(3); + expected_filtration.push_back(3); + + + std::vector< unsigned > sizes(2); + sizes[0] = 2; + sizes[1] = 2; + + std::vector< double > data(4); + data[0] = 0; + data[1] = 1; + data[2] = 2; + data[3] = 3; + + Bitmap_cubical_complex_base ba( sizes , data ); + int i = 0; + + Bitmap_cubical_complex_base::Top_dimensional_cells_range range = ba.top_dimensional_cells_range(); + for ( Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it = range.begin() ; it != range.end() ; ++it ) + { + BOOST_CHECK( data[i] == ba.get_cell_data( *it ) ); + BOOST_CHECK( ba.get_dimension_of_a_cell( *it ) == 2 ); + ++i; + } +} + -- cgit v1.2.3 From 662420055856dde7a95bda6a94d54c84e32a8188 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 29 Mar 2016 19:03:18 +0000 Subject: Add torus files for UT purpose git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1075 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 019717ec3543a7101de65c045038658be287e28b --- data/bitmap/2d_torus.txt | 12 ++++++++++++ data/bitmap/3d_torus.txt | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 data/bitmap/2d_torus.txt create mode 100644 data/bitmap/3d_torus.txt diff --git a/data/bitmap/2d_torus.txt b/data/bitmap/2d_torus.txt new file mode 100644 index 00000000..8ccd45c6 --- /dev/null +++ b/data/bitmap/2d_torus.txt @@ -0,0 +1,12 @@ +2 +-3 +-3 +0 +0 +0 +0 +10 +0 +0 +0 +0 diff --git a/data/bitmap/3d_torus.txt b/data/bitmap/3d_torus.txt new file mode 100644 index 00000000..896e6c61 --- /dev/null +++ b/data/bitmap/3d_torus.txt @@ -0,0 +1,31 @@ +3 +-3 +-3 +-3 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +10 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -- cgit v1.2.3 From 019a4fd1f7e624603f85740cbec859f3daab39d4 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 29 Mar 2016 19:33:05 +0000 Subject: Add include numeric for std::iota git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1076 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6bb361c7ff62c5a8812db125cfd0375d64696504 --- src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 1fd36914..adfe33b5 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -30,6 +30,7 @@ #include // for pair<> #include // for sort #include +#include // for iota namespace Gudhi { -- cgit v1.2.3 From c3f3b627da09dc85616ae4a43787ea5f1fdeaf1f Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 05:45:58 +0000 Subject: Fix cppcheck/cpplint Add TBB for parallel sort git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1077 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8d4692b14e59bf7a6556bc7f69dbdc18582d6c0d --- .../include/gudhi/Bitmap_cubical_complex.h | 16 +- .../include/gudhi/Bitmap_cubical_complex/counter.h | 244 +++++++++------------ .../include/gudhi/Bitmap_cubical_complex_base.h | 40 ++-- ...cal_complex_periodic_boundary_conditions_base.h | 2 +- 4 files changed, 137 insertions(+), 165 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index adfe33b5..86bfbd56 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -26,6 +26,10 @@ #include #include +#ifdef GUDHI_USE_TBB +#include +#endif + #include #include // for pair<> #include // for sort @@ -129,7 +133,7 @@ class Bitmap_cubical_complex : public T { /** * Destructor of the Bitmap_cubical_complex class. **/ - virtual ~Bitmap_cubical_complex(){} + virtual ~Bitmap_cubical_complex() {} //*********************************************// // Other 'easy' functions @@ -259,7 +263,7 @@ class Bitmap_cubical_complex : public T { public: Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { } - Filtration_simplex_iterator() : b(NULL) { } + Filtration_simplex_iterator() : b(NULL), position(0) { } Filtration_simplex_iterator operator++() { if (globalDbg) { @@ -537,9 +541,11 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { } this->simplex_associated_to_key = std::vector(this->data.size()); std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); - std::sort(simplex_associated_to_key.begin(), - simplex_associated_to_key.end(), - is_before_in_filtration(this)); +#ifdef GUDHI_USE_TBB + tbb::parallel_sort(filtration_vect_, is_before_in_filtration(this)); +#else + std::sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), is_before_in_filtration(this)); +#endif // we still need to deal here with a key_associated_to_simplex: for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h index c13d96e1..266ce051 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h @@ -20,152 +20,124 @@ * along with this program. If not, see . */ -#pragma once +#ifndef BITMAP_CUBICAL_COMPLEX_COUNTER_H_ +#define BITMAP_CUBICAL_COMPLEX_COUNTER_H_ #include #include -using namespace std; +namespace Gudhi { -namespace Gudhi -{ - -namespace Cubical_complex -{ +namespace Cubical_complex { /** -* This is an implementation of a counter being a vector of integers. -* The constructor of the class takes as an input two vectors W and V. -* It assumes that W < V coordinatewise. -* If the initial counter W is not specified, it is assumed to be vector of zeros. -* The class allows to iterate between W and V by using increment() function. -* The increment() function returns a bool value. -* The current counter reach the end counter V if the value returned by the increment function is FALSE. -* This class is needed for the implementation of a bitmapCubicalComplex. -**/ - -class counter -{ -public: - /** - * Constructor of a counter class. It takes only the parameter which is the end value of the counter. - * The default beginning value is a vector of the same length as the endd, filled-in with zeros. - **/ - counter(const std::vector& endd): begin(endd.size(),0), end(endd), current(endd.size(),0){} - //counter(std::vector< int >& endd) - //{ - // for ( size_t i = 0 ; i != endd.size() ; ++i ) - // { - // this->current.push_back(0); - // this->begin.push_back(0); - // this->end.push_back( endd[i] ); - // } - //} - - - /** - * Constructor of a counter class. It takes as the input beginn and end vector. - * It assumes that begin vector is lexicographically below the end vector. - **/ - counter(const std::vector< unsigned >& beginn , const std::vector< unsigned >& endd):begin(beginn),end(endd),current(endd.size(),0) - { - if ( beginn.size() != endd.size() ) - throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; - } - - /** - * Function to increment the counter. If the value returned by the function is true, - * then the incrementation process was successful. - * If the value of the function is false, that means, that the counter have reached its end-value. - **/ - bool increment() - { - size_t i = 0; - while( (i != this->end.size()) && (this->current[i] == this->end[i]) ) - { - ++i; - } - - if ( i == this->end.size() )return false; - ++this->current[i]; - for ( size_t j = 0 ; j != i ; ++j ) - { - this->current[j] = this->begin[j]; - } - return true; - } - - /** - * Function to check if we are at the end of counter. - **/ - bool isFinal() - { - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( this->current[i] == this->end[i] )return true; - } - return false; - } - - /** - * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. - * Its aim is to find an counter corresponding to the element the following - * boundary element is identified with when periodic boundary conditions are imposed. - **/ - std::vector< unsigned > find_opposite( const std::vector< bool >& directionsForPeriodicBCond ) - { - std::vector< unsigned > result; - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( (this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true) ) - { - result.push_back( this->begin[i] ); - } - else - { - result.push_back( this->current[i] ); - } - } - return result; + * This is an implementation of a counter being a vector of integers. + * The constructor of the class takes as an input two vectors W and V. + * It assumes that W < V coordinatewise. + * If the initial counter W is not specified, it is assumed to be vector of zeros. + * The class allows to iterate between W and V by using increment() function. + * The increment() function returns a bool value. + * The current counter reach the end counter V if the value returned by the increment function is FALSE. + * This class is needed for the implementation of a bitmapCubicalComplex. + **/ + +class counter { + public: + /** + * Constructor of a counter class. It takes only the parameter which is the end value of the counter. + * The default beginning value is a vector of the same length as the endd, filled-in with zeros. + **/ + counter(const std::vector& endd) : begin(endd.size(), 0), end(endd), current(endd.size(), 0) { } + + /** + * Constructor of a counter class. It takes as the input beginn and end vector. + * It assumes that begin vector is lexicographically below the end vector. + **/ + counter(const std::vector< unsigned >& beginn, const std::vector< unsigned >& endd) : begin(beginn), end(endd), current(endd.size(), 0) { + if (beginn.size() != endd.size()) + throw "In constructor of a counter, begin and end vectors do not have the same size. Program terminate"; + } + + /** + * Function to increment the counter. If the value returned by the function is true, + * then the incrementation process was successful. + * If the value of the function is false, that means, that the counter have reached its end-value. + **/ + bool increment() { + size_t i = 0; + while ((i != this->end.size()) && (this->current[i] == this->end[i])) { + ++i; } - /** - * Function checking at which positions the current value of a counter is the final value of the counter. - **/ - std::vector< bool > directions_of_finals() - { - std::vector< bool > result; - for ( size_t i = 0 ; i != this->current.size() ; ++i ) - { - if ( this->current[i] == this->end[i] ) - { - result.push_back( true ); - } - else - { - result.push_back( false ); - } - } - return result; + if (i == this->end.size())return false; + ++this->current[i]; + for (size_t j = 0; j != i; ++j) { + this->current[j] = this->begin[j]; } - - /** - * Function to write counter to the stream. - **/ - friend std::ostream& operator<<(std::ostream& out , const counter& c ) - { - //cerr << "c.current.size() : " << c.current.size() << endl; - for ( size_t i = 0 ; i != c.current.size() ; ++i ) - { - out << c.current[i] << " "; - } - return out; + return true; + } + + /** + * Function to check if we are at the end of counter. + **/ + bool isFinal() { + for (size_t i = 0; i != this->current.size(); ++i) { + if (this->current[i] == this->end[i])return true; + } + return false; + } + + /** + * Function required in the implementation of bitmapCubicalComplexWPeriodicBoundaryCondition. + * Its aim is to find an counter corresponding to the element the following + * boundary element is identified with when periodic boundary conditions are imposed. + **/ + std::vector< unsigned > find_opposite(const std::vector< bool >& directionsForPeriodicBCond) { + std::vector< unsigned > result; + for (size_t i = 0; i != this->current.size(); ++i) { + if ((this->current[i] == this->end[i]) && (directionsForPeriodicBCond[i] == true)) { + result.push_back(this->begin[i]); + } else { + result.push_back(this->current[i]); + } + } + return result; + } + + /** + * Function checking at which positions the current value of a counter is the final value of the counter. + **/ + std::vector< bool > directions_of_finals() { + std::vector< bool > result; + for (size_t i = 0; i != this->current.size(); ++i) { + if (this->current[i] == this->end[i]) { + result.push_back(true); + } else { + result.push_back(false); + } } -private: - std::vector< unsigned > begin; - std::vector< unsigned > end; - std::vector< unsigned > current; + return result; + } + + /** + * Function to write counter to the stream. + **/ + friend std::ostream& operator<<(std::ostream& out, const counter& c) { + // std::cerr << "c.current.size() : " << c.current.size() << endl; + for (size_t i = 0; i != c.current.size(); ++i) { + out << c.current[i] << " "; + } + return out; + } + + private: + std::vector< unsigned > begin; + std::vector< unsigned > end; + std::vector< unsigned > current; }; -} -} \ No newline at end of file +} // namespace Cubical_complex + +} // namespace Gudhi + +#endif // BITMAP_CUBICAL_COMPLEX_COUNTER_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 62776019..d858f3c5 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -204,7 +204,7 @@ class Bitmap_cubical_complex_base { } All_cells_iterator operator++() { - //first find first element of the counter that can be increased: + // first find first element of the counter that can be increased: ++this->counter; return *this; } @@ -317,14 +317,13 @@ class Bitmap_cubical_complex_base { **/ class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > { public: - Top_dimensional_cells_iterator(Bitmap_cubical_complex_base& b) : b(b) { this->counter = std::vector(b.dimension()); - //std::fill( this->counter.begin() , this->counter.end() , 0 ); + // std::fill( this->counter.begin() , this->counter.end() , 0 ); } Top_dimensional_cells_iterator operator++() { - //first find first element of the counter that can be increased: + // first find first element of the counter that can be increased: size_t dim = 0; while ((dim != this->b.dimension()) && (this->counter[dim] == this->b.sizes[dim] - 1))++dim; @@ -499,7 +498,7 @@ void Bitmap_cubical_complex_base::put_data_to_bins(size_t number_of_bins) { std::pair< T, T > min_max = this->min_max_filtration(); T dx = (min_max.second - min_max.first) / (T) number_of_bins; - //now put the data into the appropriate bins: + // now put the data into the appropriate bins: for (size_t i = 0; i != this->data.size(); ++i) { if (bdg) { std::cerr << "Before binning : " << this->data[i] << std::endl; @@ -518,7 +517,7 @@ void Bitmap_cubical_complex_base::put_data_to_bins(T diameter_of_bin) { std::pair< T, T > min_max = this->min_max_filtration(); size_t number_of_bins = (min_max.second - min_max.first) / diameter_of_bin; - //now put the data into the appropriate bins: + // now put the data into the appropriate bins: for (size_t i = 0; i != this->data.size(); ++i) { if (bdg) { std::cerr << "Before binning : " << this->data[i] << std::endl; @@ -542,7 +541,7 @@ std::pair< T, T > Bitmap_cubical_complex_base::min_max_filtration() { } template -ostream& operator<<(ostream & out, const Bitmap_cubical_complex_base& b) { +std::ostream& operator<<(std::ostream & out, const Bitmap_cubical_complex_base& b) { for (typename Bitmap_cubical_complex_base::all_cells_const_iterator it = b.all_cells_const_begin(); it != b.all_cells_const_end(); ++it) { out << *it << " "; @@ -565,16 +564,13 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells number_of_top_dimensional_elements *= sizes_in_following_directions[i]; } if (number_of_top_dimensional_elements != top_dimensional_cells.size()) { - std::cerr << - "Error in constructor\ - Bitmap_cubical_complex_base\ - ( std::vector sizes_in_following_directions , std::vector top_dimensional_cells ).\ - Number of top dimensional elements that follow from sizes_in_following_directions vector is different\ - than the size of top_dimensional_cells vector." << std::endl; - throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions,\ - std::vector top_dimensional_cells )\ - . Number of top dimensional elements that follow from sizes_in_following_directions vector is different than the\ - size of top_dimensional_cells vector."); + std::cerr << "Error in constructor Bitmap_cubical_complex_base ( std::vector sizes_in_following_directions" + << ", std::vector top_dimensional_cells ). Number of top dimensional elements that follow from " + << "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector." + << std::endl; + throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions," + "std::vector top_dimensional_cells ). Number of top dimensional elements that follow from " + "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector."); } Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); @@ -610,7 +606,6 @@ void Bitmap_cubical_complex_base::read_perseus_style_file(const char* perseus for (size_t i = 0; i != dimensionOfData; ++i) { unsigned size_in_this_dimension; inFiltration >> size_in_this_dimension; - size_in_this_dimension = size_in_this_dimension; sizes.push_back(size_in_this_dimension); if (dbg) { std::cerr << "size_in_this_dimension : " << size_in_this_dimension << std::endl; @@ -738,8 +733,7 @@ template void Bitmap_cubical_complex_base::impose_lower_star_filtration() { bool dbg = false; - //this vector will be used to check which elements have already been taken care of - //in imposing lower star filtration: + // this vector will be used to check which elements have already been taken care of in imposing lower star filtration std::vector is_this_cell_considered(this->data.size(), false); size_t size_to_reserve = 1; @@ -749,8 +743,8 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector indices_to_consider; indices_to_consider.reserve(size_to_reserve); - //we assume here that we already have a filtration on the top dimensional cells and - //we have to extend it to lower ones. + // we assume here that we already have a filtration on the top dimensional cells and + // we have to extend it to lower ones. typename Bitmap_cubical_complex_base::Top_dimensional_cells_iterator it(*this); for (it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { indices_to_consider.push_back(it.compute_index_in_bitmap()); @@ -799,7 +793,7 @@ bool compareFirstElementsOfTuples(const std::pair< std::pair< T, size_t >, char if (first.first.first > second.first.first) { return false; } - //in this case first.first.first == second.first.first, so we need to compare dimensions + // in this case first.first.first == second.first.first, so we need to compare dimensions return first.second < second.second; } } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 2c0d77fe..8afa342e 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -84,7 +84,7 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c /** * Destructor of the Bitmap_cubical_complex_periodic_boundary_conditions_base class. **/ - virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base(){} + virtual ~Bitmap_cubical_complex_periodic_boundary_conditions_base() {} // overwritten methods co compute boundary and coboundary /** -- cgit v1.2.3 From bea7dab826c2dcff4632df3d99480adc94be3f8d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 06:14:43 +0000 Subject: cpplint/cppcheck fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1078 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 794e42d37fa8417489d92d6d67d05399225d6fcd --- .../include/gudhi/Bitmap_cubical_complex.h | 2 + .../include/gudhi/Bitmap_cubical_complex_base.h | 77 +++++++++++++--------- ...cal_complex_periodic_boundary_conditions_base.h | 19 +++--- 3 files changed, 59 insertions(+), 39 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 86bfbd56..de463d8e 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -285,6 +285,7 @@ class Bitmap_cubical_complex : public T { } this->b = rhs.b; this->position = rhs.position; + return (*this); } bool operator==(const Filtration_simplex_iterator& rhs)const { @@ -454,6 +455,7 @@ class Bitmap_cubical_complex : public T { this->b = rhs.b; this->position = rhs.position; this->dimension = rhs.dimension; + return (*this); } bool operator==(const Skeleton_simplex_iterator& rhs)const { diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index d858f3c5..2258b581 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -140,7 +140,7 @@ class Bitmap_cubical_complex_base { * then there is no need to call this function. Call it only if you are putting the filtration * of the cells by your own (for instance by using Top_dimensional_cells_iterator). **/ - void impose_lower_star_filtration(); // assume that top dimensional cells are already set. + void impose_lower_star_filtration(); // assume that top dimensional cells are already set. /** * Returns dimension of a complex. @@ -198,7 +198,6 @@ class Bitmap_cubical_complex_base { **/ class All_cells_iterator : std::iterator< std::input_iterator_tag, T > { public: - All_cells_iterator() { this->counter = 0; } @@ -215,7 +214,7 @@ class Bitmap_cubical_complex_base { return result; } - All_cells_iterator operator=(const All_cells_iterator& rhs) { + All_cells_iterator& operator=(const All_cells_iterator& rhs) { this->counter = rhs.counter; return *this; } @@ -230,8 +229,10 @@ class Bitmap_cubical_complex_base { } /* - * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: - * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as + * an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell + * boundary and coboundary and dimension * and in function get_cell_data to get a filtration of a cell. */ size_t operator*() { @@ -264,8 +265,7 @@ class Bitmap_cubical_complex_base { **/ class All_cells_range { public: - - All_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }; + All_cells_range(Bitmap_cubical_complex_base* b) : b(b) { } All_cells_iterator begin() { return b->all_cells_iterator_begin(); @@ -344,7 +344,7 @@ class Bitmap_cubical_complex_base { return result; } - Top_dimensional_cells_iterator operator=(const Top_dimensional_cells_iterator& rhs) { + Top_dimensional_cells_iterator& operator=(const Top_dimensional_cells_iterator& rhs) { this->counter = rhs.counter; this->b = rhs.b; return *this; @@ -364,8 +364,10 @@ class Bitmap_cubical_complex_base { } /* - * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as an argument of the following functions: - * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell boundary and coboundary and dimension + * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as + * an argument of the following functions: + * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell + * boundary and coboundary and dimension * and in function get_cell_data to get a filtration of a cell. */ size_t operator*() { @@ -416,8 +418,7 @@ class Bitmap_cubical_complex_base { **/ class Top_dimensional_cells_range { public: - - Top_dimensional_cells_range(Bitmap_cubical_complex_base* b) : b(b) { }; + Top_dimensional_cells_range(Bitmap_cubical_complex_base* b) : b(b) { } Top_dimensional_cells_iterator begin() { return b->top_dimensional_cells_iterator_begin(); @@ -485,10 +486,13 @@ class Bitmap_cubical_complex_base { return counter; } void read_perseus_style_file(const char* perseus_style_file); - void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells); + void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, + const std::vector& top_dimensional_cells); Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector directions); Bitmap_cubical_complex_base(const std::vector& sizes, std::vector directions); - Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells, std::vector directions); + Bitmap_cubical_complex_base(const std::vector& dimensions, + const std::vector& top_dimensional_cells, + std::vector directions); }; template @@ -556,7 +560,8 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base } template -void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, const std::vector& top_dimensional_cells) { +void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells_list(const std::vector& sizes_in_following_directions, + const std::vector& top_dimensional_cells) { this->set_up_containers(sizes_in_following_directions); size_t number_of_top_dimensional_elements = 1; @@ -568,7 +573,7 @@ void Bitmap_cubical_complex_base::setup_bitmap_based_on_top_dimensional_cells << ", std::vector top_dimensional_cells ). Number of top dimensional elements that follow from " << "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector." << std::endl; - throw ("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions," + throw("Error in constructor Bitmap_cubical_complex_base( std::vector sizes_in_following_directions," "std::vector top_dimensional_cells ). Number of top dimensional elements that follow from " "sizes_in_following_directions vector is different than the size of top_dimensional_cells vector."); } @@ -591,7 +596,7 @@ Bitmap_cubical_complex_base::Bitmap_cubical_complex_base template void Bitmap_cubical_complex_base::read_perseus_style_file(const char* perseus_style_file) { bool dbg = false; - std::ifstream inFiltration, inIds; + std::ifstream inFiltration; inFiltration.open(perseus_style_file); unsigned dimensionOfData; inFiltration >> dimensionOfData; @@ -634,23 +639,30 @@ void Bitmap_cubical_complex_base::read_perseus_style_file(const char* perseus } template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const char* perseus_style_file, std::vector directions) { - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const char* perseus_style_file, + std::vector directions) { + // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary + // conditions. + // It ignores the last parameter of the function. this->read_perseus_style_file(perseus_style_file); } template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& sizes, std::vector directions) { - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& sizes, + std::vector directions) { + // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary + // conditions. + // It ignores the last parameter of the function. this->set_up_containers(sizes); } template -Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& dimensions, const std::vector& top_dimensional_cells, std::vector directions) { - //this constructor is here just for compatibility with a class that creates cubical complexes with periodic bundary conditions. - //It ignores the last parameter of the function. +Bitmap_cubical_complex_base::Bitmap_cubical_complex_base(const std::vector& dimensions, + const std::vector& top_dimensional_cells, + std::vector directions) { + // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary + // conditions. + // It ignores the last parameter of the function. this->setup_bitmap_based_on_top_dimensional_cells_list(dimensions, top_dimensional_cells); } @@ -663,7 +675,7 @@ template std::vector< size_t > Bitmap_cubical_complex_base::get_boundary_of_a_cell(size_t cell)const { std::vector< size_t > boundary_elements; - //Speed traded of for memory. Check if it is better in practice. + // Speed traded of for memory. Check if it is better in practice. boundary_elements.reserve(this->dimension()*2); size_t cell1 = cell; @@ -763,14 +775,17 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { std::vector bd = this->get_boundary_of_a_cell(indices_to_consider[i]); for (size_t boundaryIt = 0; boundaryIt != bd.size(); ++boundaryIt) { if (dbg) { - std::cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << std::endl; + std::cerr << "filtration of a cell : " << bd[boundaryIt] << " is : " << this->data[ bd[boundaryIt] ] + << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] + << std::endl; getchar(); } if (this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ]) { this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; if (dbg) { - std::cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " << this->data[ indices_to_consider[i] ] << std::endl; + std::cerr << "Setting the value of a cell : " << bd[boundaryIt] << " to : " + << this->data[ indices_to_consider[i] ] << std::endl; getchar(); } } @@ -798,8 +813,8 @@ bool compareFirstElementsOfTuples(const std::pair< std::pair< T, size_t >, char } } -} // namespace Cubical_complex +} // namespace Cubical_complex -} // namespace Gudhi +} // namespace Gudhi #endif // BITMAP_CUBICAL_COMPLEX_BASE_H_ diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 8afa342e..a446c0e8 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -44,9 +44,10 @@ namespace Cubical_complex { * @ingroup cubical_complex */ /** -* This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are identical to the functions from Bitmap_cubical_complex_base. -* The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. -*/ + * This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are + * identical to the functions from Bitmap_cubical_complex_base. + * The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. + */ template class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_cubical_complex_base { public: @@ -88,14 +89,16 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c // overwritten methods co compute boundary and coboundary /** - * A version of a function that return boundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + * A version of a function that return boundary of a given cell for an object of + * Bitmap_cubical_complex_periodic_boundary_conditions_base class. */ - virtual std::vector< size_t > get_boundary_of_a_cell(size_t cell)const; + virtual std::vector< size_t > get_boundary_of_a_cell(size_t cell) const; /** - * A version of a function that return coboundary of a given cell for an object of Bitmap_cubical_complex_periodic_boundary_conditions_base class. + * A version of a function that return coboundary of a given cell for an object of + * Bitmap_cubical_complex_periodic_boundary_conditions_base class. */ - virtual std::vector< size_t > get_coboundary_of_a_cell( size_t cell )const; + virtual std::vector< size_t > get_coboundary_of_a_cell(size_t cell) const; protected: std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed; @@ -132,7 +135,7 @@ void Bitmap_cubical_complex_periodic_boundary_conditions_base::construct_comp this->set_up_containers(dimensions); size_t i = 0; - for (typename Bitmap_cubical_complex_periodic_boundary_conditions_base::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { + for (auto it = this->top_dimensional_cells_iterator_begin(); it != this->top_dimensional_cells_iterator_end(); ++it) { this->get_cell_data(*it) = topDimensionalCells[i]; ++i; } -- cgit v1.2.3 From dea986187f3a214db300a909f8f8a02cf3d9014d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 06:31:24 +0000 Subject: cpplint/cppcheck fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/bitmap@1079 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 812004416560ad653025d02ea7ff05677ec5b3fc --- src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h | 6 +++--- .../include/gudhi/Bitmap_cubical_complex_base.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index de463d8e..7bf9617e 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -397,7 +397,8 @@ class Bitmap_cubical_complex : public T { } // this method returns two first elements from the boundary of sh. if (bdry.size() < 2) - throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the boundary."); + throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the " + "boundary."); return std::make_pair(bdry[0], bdry[1]); } @@ -550,8 +551,7 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { #endif // we still need to deal here with a key_associated_to_simplex: - for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) - { + for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) { this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i; } } diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 2258b581..7294da98 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -779,7 +779,6 @@ void Bitmap_cubical_complex_base::impose_lower_star_filtration() { << " while of a cell: " << indices_to_consider[i] << " is: " << this->data[ indices_to_consider[i] ] << std::endl; getchar(); - } if (this->data[ bd[boundaryIt] ] > this->data[ indices_to_consider[i] ]) { this->data[ bd[boundaryIt] ] = this->data[ indices_to_consider[i] ]; -- cgit v1.2.3 From aa1b1f242900b678e29f93ab3439c59e93fdda4b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 09:20:49 +0000 Subject: Fix use of TBB parallel sort. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1082 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 337109ed520bf0e5836ceb0dba11948b75cafae2 --- .../include/gudhi/Bitmap_cubical_complex.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 7bf9617e..67e1fed3 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -46,9 +46,12 @@ const bool globalDbg = false; template class is_before_in_filtration; /** -* This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and Bitmap_cubical_complex_periodic_boundary_conditions_base classes into -* Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template parameter is supposed to be either Bitmap_cubical_complex_base or Bitmap_cubical_complex_periodic_boundary_conditions_base class. -**/ + * This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and + * Bitmap_cubical_complex_periodic_boundary_conditions_base classes into + * Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template + * parameter is supposed to be either Bitmap_cubical_complex_base or + * Bitmap_cubical_complex_periodic_boundary_conditions_base class. + **/ /** *@class Bitmap_cubical_complex @@ -113,7 +116,8 @@ class Bitmap_cubical_complex : public T { /** * Constructor that requires vector of elements of type unsigned, which gives number of top dimensional cells * in the following directions and vector of element of a type T::filtration_type - * with filtration on top dimensional cells. The last parameter of the constructor is a vector of bools of a length equal to the dimension of cubical complex. + * with filtration on top dimensional cells. The last parameter of the constructor is a vector of boolean of a length + * equal to the dimension of cubical complex. * If the position i on this vector is true, then we impose periodic boundary conditions in this direction. **/ Bitmap_cubical_complex(const std::vector& dimensions, @@ -545,7 +549,7 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { this->simplex_associated_to_key = std::vector(this->data.size()); std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); #ifdef GUDHI_USE_TBB - tbb::parallel_sort(filtration_vect_, is_before_in_filtration(this)); + tbb::parallel_sort(simplex_associated_to_key, is_before_in_filtration(this)); #else std::sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), is_before_in_filtration(this)); #endif -- cgit v1.2.3 From 19fb1ba90b56e120514c98e87fc59bb1635eed29 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 09:26:51 +0000 Subject: Cubical complex for new doxygen version git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1083 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 77e7fa96f9ed2f2ccd9f65bb1f6b325737f863f5 --- .../doc/Cubical_complex_representation.ipe | 732 +++++++++++++++++++++ .../doc/Cubical_complex_representation.png | Bin 0 -> 19167 bytes .../doc/Gudhi_Cubical_Complex_doc.h | 2 +- src/common/doc/main_page.h | 62 +- 4 files changed, 772 insertions(+), 24 deletions(-) create mode 100644 src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe create mode 100644 src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png diff --git a/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe new file mode 100644 index 00000000..bec245e7 --- /dev/null +++ b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.ipe @@ -0,0 +1,732 @@ + + + + + + + +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 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 + + + + +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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +176 496 m +176 480 l +192 480 l +192 496 l +h + +0 + +192 496 m +192 480 l +240 480 l +240 496 l +h + +1 + +176 496 m +176 480 l +192 480 l +192 496 l +h + +2 + +192 496 m +192 480 l +240 480 l +240 496 l +h + +3 + +176 496 m +176 480 l +192 480 l +192 496 l +h + +4 + +192 496 m +192 480 l +240 480 l +240 496 l +h + +5 + +176 496 m +176 480 l +192 480 l +192 496 l +h + +6 + +192 496 m +192 480 l +240 480 l +240 496 l +h + +7 + +176 496 m +176 480 l +192 480 l +192 496 l +h + +8 + +176 496 m +176 480 l +192 480 l +192 496 l +h + +1 + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + +2 + +192 496 m +192 480 l +240 480 l +240 496 l +h + +3 + +176 496 m +176 480 l +192 480 l +192 496 l +h + +4 + +192 496 m +192 480 l +240 480 l +240 496 l +h + +5 + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + +1 +2 +3 + +160 496 m +160 544 l +144 544 l +144 496 l +h + +9 + +160 496 m +160 544 l +144 544 l +144 496 l +h + +11 + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +192 496 m +192 480 l +240 480 l +240 496 l +h + + +176 496 m +176 480 l +192 480 l +192 496 l +h + + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +160 496 m +160 544 l +144 544 l +144 496 l +h + + +192 544 m +192 496 l +240 496 l +240 544 l +h + + +192 544 m +192 496 l +240 496 l +240 544 l +h + + +192 544 m +192 496 l +240 496 l +240 544 l +h + + +192 544 m +192 496 l +240 496 l +240 544 l +h + + +192 544 m +192 496 l +240 496 l +240 544 l +h + + +192 544 m +192 496 l +240 496 l +240 544 l +h + + +192 544 m +192 496 l +240 496 l +240 544 l +h + + +192 544 m +192 496 l +240 496 l +240 544 l +h + +10 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 + +152 456 m +472 456 l + + +152 456 m +152 648 l + + + diff --git a/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png new file mode 100644 index 00000000..afb2a75e Binary files /dev/null and b/src/Bitmap_cubical_complex/doc/Cubical_complex_representation.png differ diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index cde0b2fc..be4caaad 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -76,7 +76,7 @@ namespace Cubical_complex { * directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube \f$C \in * \mathcal{K}\f$. * - * \image html "bitmapAllCubes.png" "Cubical complex. + * \image html "Cubical_complex_representation.png" Cubical complex. * * Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical * complexes in \f$\mathbb{R}\f$. The number of all cubes in each direction is equal \f$2n+1\f$, where \f$n\f$ is the diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 1db1ea8a..56cb82bb 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -3,7 +3,7 @@ * \image html "Gudhi_banner.jpg" "" width=20cm * * \section Introduction Introduction - * The Gudhi library (Geometric Understanding in Higher Dimensions) is a generic open source C++ library for + * The Gudhi library (Geometry Understanding in Higher Dimensions) is a generic open source C++ library for * Computational Topology and Topological Data Analysis * (TDA). * The GUDHI library intends to help the development of new algorithmic solutions in TDA and their transfer to @@ -20,16 +20,32 @@ * We refer to \cite gudhilibrary_ICMS14 for a detailed description of the design of the library. * \section DataStructures Data structures + \subsection CubicalComplexDataStructure Cubical complex + \image html "Cubical_complex_representation.png" "Cubical complex representation" + + + + + +
+ Author: Pawel Dlotko
+ Introduced in: GUDHI 1.3.0
+ Copyright: GPL v3
+
+ The cubical complex is an example of a structured complex useful in computational mathematics (specially + rigorous numerics) and image analysis.
+ User manual: \ref cubical_complex - Reference manual: Gudhi::Cubical_complex::Bitmap_cubical_complex +
\subsection SimplexTreeDataStructure Simplex tree \image html "Simplex_tree_representation.png" "Simplex tree representation"
+ Author: Clément Maria
Introduced in: GUDHI 1.0.0
Copyright: GPL v3
- Clément Maria
The simplex tree is an efficient and flexible data structure for representing general (filtered) simplicial complexes. The data structure is described in \cite boissonnatmariasimplextreealgorithmica .
@@ -42,11 +58,11 @@
+ Author: David Salinas
Introduced in: GUDHI 1.1.0
Copyright: GPL v3
- David Salinas
The Skeleton-Blocker data-structure proposes a light encoding for simplicial complexes by storing only an *implicit* representation of its simplices \cite socg_blockers_2011,\cite blockers2012. Intuitively, it just stores the 1-skeleton of a simplicial complex with a graph and the set of its "missing faces" that is very small in practice. @@ -62,11 +78,11 @@
+ Author: Siargey Kachanovich
Introduced in: GUDHI 1.3.0
Copyright: GPL v3
- Siargey Kachanovich
Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$. The data structure is described in \cite boissonnatmariasimplextreealgorithmica .
User manual: \ref witness_complex - Reference manual: Gudhi::witness_complex::SimplicialComplexForWitness @@ -75,16 +91,34 @@
\section Toolbox Toolbox + \subsection ContractionToolbox Contraction + \image html "sphere_contraction_representation.png" "Sphere contraction example" + + + + + +
+ Author: David Salinas
+ Introduced in: GUDHI 1.1.0
+ Copyright: GPL v3
+
+ The purpose of this package is to offer a user-friendly interface for edge contraction simplification of huge + simplicial complexes. It uses the \ref skbl data-structure whose size remains small during simplification of most + used geometrical complexes of topological data analysis such as the Rips or the Delaunay complexes. In practice, + the size of this data-structure is even much lower than the total number of simplices.
+ User manual: \ref contr +
\subsection PersistentCohomologyToolbox Persistent Cohomology \image html "3DTorus_poch.png" "Rips Persistent Cohomology on a 3D Torus" -
+ Author: Clément Maria
Introduced in: GUDHI 1.0.0
Copyright: GPL v3
- Clément Maria
The theory of homology consists in attaching to a topological space a sequence of (homology) groups, capturing global topological features like connected components, holes, cavities, etc. Persistent homology studies the evolution -- birth, life and death -- of these features when the topological space is changing. Consequently, the @@ -96,24 +130,6 @@ User manual: \ref persistent_cohomology
- \subsection ContractionToolbox Contraction - \image html "sphere_contraction_representation.png" "Sphere contraction example" - - - - -
- Introduced in: GUDHI 1.1.0
- Copyright: GPL v3
-
- David Salinas
- The purpose of this package is to offer a user-friendly interface for edge contraction simplification of huge - simplicial complexes. It uses the \ref skbl data-structure whose size remains small during simplification of most - used geometrical complexes of topological data analysis such as the Rips or the Delaunay complexes. In practice, - the size of this data-structure is even much lower than the total number of simplices.
- User manual: \ref contr -
*/ -- cgit v1.2.3 From 001f501ffa371fc810d4f24812d26845bd61f349 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 30 Mar 2016 10:43:10 +0000 Subject: Add cubical complex to main page Homogeneize the author/copyright sections of modules Exclude data and GudhUI from doxygen git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1085 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1b89161f3253553a02935885334b2fc6cf58055e --- src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h | 3 ++- .../include/gudhi/Bitmap_cubical_complex.h | 11 ++++------- .../include/gudhi/Bitmap_cubical_complex/counter.h | 2 +- .../include/gudhi/Bitmap_cubical_complex_base.h | 7 ++----- ...Bitmap_cubical_complex_periodic_boundary_conditions_base.h | 6 ++---- src/Contraction/include/gudhi/Edge_contraction.h | 1 - src/Doxyfile | 3 ++- .../include/gudhi/Persistent_cohomology.h | 6 +----- src/Simplex_tree/include/gudhi/Simplex_tree.h | 5 +---- src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h | 1 - src/common/doc/main_page.h | 4 ++-- 11 files changed, 17 insertions(+), 32 deletions(-) diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index be4caaad..83921427 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -145,7 +145,8 @@ namespace Cubical_complex { * \section BitmapExamples Examples * End user programs are available in example/Bitmap_cubical_complex folder. - + * + * \copyright GNU General Public License v3. */ /** @} */ // end defgroup cubical_complex diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 67e1fed3..54ae47d0 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -46,18 +46,15 @@ const bool globalDbg = false; template class is_before_in_filtration; /** - * This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and + * @class Bitmap_cubical_complex Bitmap_cubical_complex.h gudhi/Bitmap_cubical_complex.h + * @brief Cubical complex represented as a bitmap. + * @ingroup cubical_complex + * @details This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and * Bitmap_cubical_complex_periodic_boundary_conditions_base classes into * Gudhi persistent homology engine. It is a template class that inherit from its template parameter. The template * parameter is supposed to be either Bitmap_cubical_complex_base or * Bitmap_cubical_complex_periodic_boundary_conditions_base class. **/ - -/** - *@class Bitmap_cubical_complex - *@brief Cubical complex represented as a bitmap. - *@ingroup cubical_complex - */ template class Bitmap_cubical_complex : public T { public: diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h index 266ce051..bee19344 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h @@ -31,6 +31,7 @@ namespace Gudhi { namespace Cubical_complex { /** + * @class counter counter.h gudhi/Bitmap_cubical_complex/counter.h * This is an implementation of a counter being a vector of integers. * The constructor of the class takes as an input two vectors W and V. * It assumes that W < V coordinatewise. @@ -40,7 +41,6 @@ namespace Cubical_complex { * The current counter reach the end counter V if the value returned by the increment function is FALSE. * This class is needed for the implementation of a bitmapCubicalComplex. **/ - class counter { public: /** diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 7294da98..4bdc94ef 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -39,13 +39,10 @@ namespace Gudhi { namespace Cubical_complex { /** - * @class Bitmap_cubical_complex_base + * @class Bitmap_cubical_complex_base Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h * @brief Cubical complex represented as a bitmap, class with basic implementation. * @ingroup cubical_complex - */ - -/** - * This is a class implementing a basic bitmap data structure to store cubical complexes. + * @details This is a class implementing a basic bitmap data structure to store cubical complexes. * It implements only the most basic subroutines. * The idea of the bitmap is the following. Our aim is to have a memory efficient * data structure to store d-dimensional cubical complex diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index a446c0e8..5b7e4115 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -39,12 +39,10 @@ namespace Cubical_complex { // the cells on the right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base /** - * @class Bitmap_cubical_complex_periodic_boundary_conditions_base + * @class Bitmap_cubical_complex_periodic_boundary_conditions_base Bitmap_cubical_complex_periodic_boundary_conditions_base.h gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h * @brief Cubical complex with periodic boundary conditions represented as a bitmap. * @ingroup cubical_complex - */ -/** - * This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are + * @details This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are * identical to the functions from Bitmap_cubical_complex_base. * The ones that needed to be updated are the constructors and get_boundary_of_a_cell and get_coboundary_of_a_cell. */ diff --git a/src/Contraction/include/gudhi/Edge_contraction.h b/src/Contraction/include/gudhi/Edge_contraction.h index 73236db9..1fe563d6 100644 --- a/src/Contraction/include/gudhi/Edge_contraction.h +++ b/src/Contraction/include/gudhi/Edge_contraction.h @@ -226,7 +226,6 @@ Time to simplify and enumerate simplices: \copyright GNU General Public License v3. -\verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim */ /** @} */ // end defgroup } // namespace contraction diff --git a/src/Doxyfile b/src/Doxyfile index 8fe41755..f7fba3e6 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -779,7 +779,8 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = +EXCLUDE = data/ \ + GudhUI/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index 3c331f0f..1b86f1f9 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -48,6 +48,7 @@ namespace persistent_cohomology { /** \defgroup persistent_cohomology Persistent Cohomology * + \author Clément Maria Computation of persistent cohomology using the algorithm of \cite DBLP:journals/dcg/SilvaMV11 and \cite DBLP:journals/corr/abs-1208-5018 @@ -169,11 +170,6 @@ points sampling a Klein bottle in \f$\mathbb{R}^5\f$ with a simplex tree, its co Hasse diagram and the computation of persistent homology and multi-field persistent homology for the different representations. - - - \author Clément Maria - \version 1.0 - \date 2014 \copyright GNU General Public License v3. @{ */ diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 46670b85..ba09db63 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -48,6 +48,7 @@ namespace Gudhi { /** \defgroup simplex_tree Filtered Complexes + * \author Clément Maria * * A simplicial complex \f$\mathbf{K}\f$ * on a set of vertices \f$V = \{1, \cdots ,|V|\}\f$ is a collection of simplices @@ -75,10 +76,6 @@ namespace Gudhi { when accessing the boundary of a simplex, but is less compact and harder to construct from scratch. - - * \author Clément Maria - * \version 1.0 - * \date 2014 * \copyright GNU General Public License v3. * @{ */ diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h index 615b3a81..74c6a71d 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h @@ -240,7 +240,6 @@ their collaboration to write the two initial papers \copyright GNU General Public License v3. -\verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim */ /** @} */ // end defgroup diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 56cb82bb..6f3d8603 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -41,7 +41,7 @@ @@ -114,7 +114,7 @@
- Author: Clément Maria
+ Author: Clément Maria
Introduced in: GUDHI 1.0.0
Copyright: GPL v3
-- cgit v1.2.3 From d29bdae1281bb2b9b9778365c5dc3d44cffa4de4 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 31 Mar 2016 13:03:58 +0000 Subject: Fix TBB issue in CMake Add TBB in Doxygen git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1086 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e3d3251431193d21ebf9344c230d12df624cd905 --- CMakeLists.txt | 4 + src/Bitmap_cubical_complex/example/CMakeLists.txt | 15 +++- .../include/gudhi/Bitmap_cubical_complex.h | 3 +- src/Bitmap_cubical_complex/test/CMakeLists.txt | 3 + src/CMakeLists.txt | 4 + src/Doxyfile | 8 +- src/GudhUI/CMakeLists.txt | 3 + src/Persistent_cohomology/example/CMakeLists.txt | 26 ++++++- src/Persistent_cohomology/test/CMakeLists.txt | 8 +- src/Simplex_tree/example/CMakeLists.txt | 9 +++ src/Simplex_tree/include/gudhi/Simplex_tree.h | 7 +- src/Simplex_tree/test/CMakeLists.txt | 3 + src/common/doc/main_page.h | 89 ++++++++++++++++++++-- 13 files changed, 163 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index abb66ec2..9cb8b86b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,10 @@ else() # Find TBB package for parallel sort - not mandatory, just optional. set(TBB_FIND_QUIETLY ON) find_package(TBB) + if (TBB_FOUND) + message("TBB found in ${TBB_LIBRARY_DIRS}") + add_definitions(-DGUDHI_USE_TBB) + endif() # Required programs for unitary tests purpose FIND_PROGRAM( GCOVR_PATH gcovr ) diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index 8f9cfa80..ad86b763 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -2,16 +2,25 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIBitmap) add_executable ( Bitmap_cubical_complex Bitmap_cubical_complex.cpp ) -target_link_libraries(Bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) +target_link_libraries(Bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(Bitmap_cubical_complex ${TBB_RELEASE_LIBRARY}) +endif() add_test(Bitmap_cubical_complex_one_sphere ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalOneSphere.txt) add_test(Bitmap_cubical_complex_two_sphere ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) add_executable ( Random_bitmap_cubical_complex Random_bitmap_cubical_complex.cpp ) -target_link_libraries(Random_bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) +target_link_libraries(Random_bitmap_cubical_complex ${Boost_SYSTEM_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(Random_bitmap_cubical_complex ${TBB_RELEASE_LIBRARY}) +endif() add_test(Random_bitmap_cubical_complex ${CMAKE_CURRENT_BINARY_DIR}/Random_bitmap_cubical_complex 2 100 100) add_executable ( Bitmap_cubical_complex_periodic_boundary_conditions Bitmap_cubical_complex_periodic_boundary_conditions.cpp ) -target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) +target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${Boost_SYSTEM_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(Bitmap_cubical_complex_periodic_boundary_conditions ${TBB_RELEASE_LIBRARY}) +endif() add_test(Bitmap_cubical_complex_periodic_2d_torus ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex_periodic_boundary_conditions ${CMAKE_SOURCE_DIR}/data/bitmap/2d_torus.txt) add_test(Bitmap_cubical_complex_periodic_3d_torus ${CMAKE_CURRENT_BINARY_DIR}/Bitmap_cubical_complex_periodic_boundary_conditions ${CMAKE_SOURCE_DIR}/data/bitmap/3d_torus.txt) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index 54ae47d0..a6ba60d3 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -546,7 +546,8 @@ void Bitmap_cubical_complex::initialize_simplex_associated_to_key() { this->simplex_associated_to_key = std::vector(this->data.size()); std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0); #ifdef GUDHI_USE_TBB - tbb::parallel_sort(simplex_associated_to_key, is_before_in_filtration(this)); + tbb::parallel_sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), + is_before_in_filtration(this)); #else std::sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), is_before_in_filtration(this)); #endif diff --git a/src/Bitmap_cubical_complex/test/CMakeLists.txt b/src/Bitmap_cubical_complex/test/CMakeLists.txt index 97c374e6..96a41c62 100644 --- a/src/Bitmap_cubical_complex/test/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/test/CMakeLists.txt @@ -16,6 +16,9 @@ endif() add_executable ( BitmapCCUT Bitmap_test.cpp ) target_link_libraries(BitmapCCUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(BitmapCCUT ${TBB_RELEASE_LIBRARY}) +endif() # Unitary tests add_test(NAME BitmapCCUT diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40b7dd58..d4abe96d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,6 +53,10 @@ else() # Find TBB package for parallel sort - not mandatory, just optional. set(TBB_FIND_QUIETLY ON) find_package(TBB) + if (TBB_FOUND) + message("TBB found in ${TBB_LIBRARY_DIRS}") + add_definitions(-DGUDHI_USE_TBB) + endif() # BOOST ISSUE result_of vs C++11 add_definitions(-DBOOST_RESULT_OF_USE_DECLTYPE) diff --git a/src/Doxyfile b/src/Doxyfile index f7fba3e6..63e7145c 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -780,7 +780,8 @@ RECURSIVE = YES # run. EXCLUDE = data/ \ - GudhUI/ + example/ \ + GudhUI/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -813,14 +814,15 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = biblio/ +EXAMPLE_PATH = biblio/ \ + example/ # 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 # files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index 1ee43d91..fd7397ea 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -57,6 +57,9 @@ if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND ) target_link_libraries( GudhUI ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} ) target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) +if (TBB_FOUND) + target_link_libraries( GudhUI ${TBB_RELEASE_LIBRARY}) +endif() else() message(STATUS "NOTICE: GudhUI requires CGAL, the QGLViewer, OpenGL and Qt4, and will not be compiled.") diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index 95506631..9702a5f9 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -7,24 +7,37 @@ add_definitions( -DBOOST_ALL_DYN_LINK ) add_executable(plain_homology plain_homology.cpp) target_link_libraries(plain_homology ${Boost_SYSTEM_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(plain_homology ${TBB_RELEASE_LIBRARY}) +endif() add_test(plain_homology ${CMAKE_CURRENT_BINARY_DIR}/plain_homology) add_executable(persistence_from_simple_simplex_tree persistence_from_simple_simplex_tree.cpp) target_link_libraries(persistence_from_simple_simplex_tree ${Boost_SYSTEM_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(persistence_from_simple_simplex_tree ${TBB_RELEASE_LIBRARY}) +endif() add_test(persistence_from_simple_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_simple_simplex_tree 1 0) add_executable(rips_persistence rips_persistence.cpp) target_link_libraries(rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) - +if (TBB_FOUND) + target_link_libraries(rips_persistence ${TBB_RELEASE_LIBRARY}) +endif() add_test(rips_persistence_3 ${CMAKE_CURRENT_BINARY_DIR}/rips_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.2 -d 3 -p 3 -m 100) add_executable(parallel_rips_persistence parallel_rips_persistence.cpp) target_link_libraries(parallel_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) - +if (TBB_FOUND) + target_link_libraries(parallel_rips_persistence ${TBB_RELEASE_LIBRARY}) +endif() add_test(parallel_rips_persistence_3 ${CMAKE_CURRENT_BINARY_DIR}/parallel_rips_persistence ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.txt -r 0.3 -d 3 -p 3 -m 100) add_executable(persistence_from_file persistence_from_file.cpp) target_link_libraries(persistence_from_file ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(persistence_from_file ${TBB_RELEASE_LIBRARY}) +endif() add_test(persistence_from_file_3_2_0 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 2 -m 0) add_test(persistence_from_file_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) @@ -34,10 +47,16 @@ if(GMPXX_FOUND AND GMP_FOUND) add_executable(rips_multifield_persistence rips_multifield_persistence.cpp ) target_link_libraries(rips_multifield_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) + if (TBB_FOUND) + target_link_libraries(rips_multifield_persistence ${TBB_RELEASE_LIBRARY}) + endif() add_test(rips_multifield_persistence_2_71 ${CMAKE_CURRENT_BINARY_DIR}/rips_multifield_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.2 -d 3 -p 2 -q 71 -m 100) add_executable ( performance_rips_persistence performance_rips_persistence.cpp ) target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) + if (TBB_FOUND) + target_link_libraries(performance_rips_persistence ${TBB_RELEASE_LIBRARY}) + endif() if(CGAL_FOUND) if (CMAKE_BUILD_TYPE MATCHES Debug) @@ -46,6 +65,9 @@ if(GMPXX_FOUND AND GMP_FOUND) 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}) + if (TBB_FOUND) + target_link_libraries(alpha_shapes_persistence ${TBB_RELEASE_LIBRARY}) + endif() 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) #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) endif() diff --git a/src/Persistent_cohomology/test/CMakeLists.txt b/src/Persistent_cohomology/test/CMakeLists.txt index d16be5be..459cc000 100644 --- a/src/Persistent_cohomology/test/CMakeLists.txt +++ b/src/Persistent_cohomology/test/CMakeLists.txt @@ -12,6 +12,9 @@ endif() add_executable ( PersistentCohomologyUT persistent_cohomology_unit_test.cpp ) target_link_libraries(PersistentCohomologyUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(PersistentCohomologyUT ${TBB_RELEASE_LIBRARY}) +endif() # Unitary tests add_test(NAME PersistentCohomologyUT @@ -22,7 +25,10 @@ add_test(NAME PersistentCohomologyUT if(GMPXX_FOUND AND GMP_FOUND) add_executable ( PersistentCohomologyMultiFieldUT persistent_cohomology_unit_test_multi_field.cpp ) - target_link_libraries(PersistentCohomologyMultiFieldUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) +target_link_libraries(PersistentCohomologyMultiFieldUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) +if (TBB_FOUND) + target_link_libraries(PersistentCohomologyMultiFieldUT ${TBB_RELEASE_LIBRARY}) +endif() # Unitary tests add_test(NAME PersistentCohomologyMultiFieldUT diff --git a/src/Simplex_tree/example/CMakeLists.txt b/src/Simplex_tree/example/CMakeLists.txt index 200161a6..89a4e053 100644 --- a/src/Simplex_tree/example/CMakeLists.txt +++ b/src/Simplex_tree/example/CMakeLists.txt @@ -2,10 +2,16 @@ cmake_minimum_required(VERSION 2.6) project(GUDHISimplexTreeFromFile) add_executable ( simplex_tree_from_cliques_of_graph simplex_tree_from_cliques_of_graph.cpp ) +if (TBB_FOUND) + target_link_libraries(simplex_tree_from_cliques_of_graph ${TBB_RELEASE_LIBRARY}) +endif() add_test(simplex_tree_from_cliques_of_graph_2 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_cliques_of_graph ${CMAKE_SOURCE_DIR}/data/points/Klein_bottle_complex.txt 2) add_test(simplex_tree_from_cliques_of_graph_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_cliques_of_graph ${CMAKE_SOURCE_DIR}/data/points/Klein_bottle_complex.txt 3) add_executable ( simple_simplex_tree simple_simplex_tree.cpp ) +if (TBB_FOUND) + target_link_libraries(simple_simplex_tree ${TBB_RELEASE_LIBRARY}) +endif() add_test(simple_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/simple_simplex_tree) add_executable ( mini_simplex_tree mini_simplex_tree.cpp ) @@ -16,5 +22,8 @@ add_test(mini_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/mini_simplex_tree) if(GMP_FOUND AND CGAL_FOUND) add_executable ( simplex_tree_from_alpha_shapes_3 simplex_tree_from_alpha_shapes_3.cpp ) target_link_libraries(simplex_tree_from_alpha_shapes_3 ${GMP_LIBRARIES} ${CGAL_LIBRARY} ${Boost_SYSTEM_LIBRARY}) + if (TBB_FOUND) + target_link_libraries(simplex_tree_from_alpha_shapes_3 ${TBB_RELEASE_LIBRARY}) + endif() add_test(simplex_tree_from_alpha_shapes_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_alpha_shapes_3 ${CMAKE_SOURCE_DIR}/data/points/bunny_5000) endif() diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index ba09db63..dea475ac 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -797,10 +797,11 @@ class Simplex_tree { * possible. */ #ifdef GUDHI_USE_TBB - tbb::parallel_sort(filtration_vect_, is_before_in_filtration(this)); + std::cout << "TBB is ON !!!" << std::endl; + tbb::parallel_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(this)); #else - std::stable_sort(filtration_vect_.begin(), filtration_vect_.end(), - is_before_in_filtration(this)); + std::cout << "TBB is OFF..." << std::endl; + std::stable_sort(filtration_vect_.begin(), filtration_vect_.end(), is_before_in_filtration(this)); #endif } diff --git a/src/Simplex_tree/test/CMakeLists.txt b/src/Simplex_tree/test/CMakeLists.txt index 1f2f7d33..609d8669 100644 --- a/src/Simplex_tree/test/CMakeLists.txt +++ b/src/Simplex_tree/test/CMakeLists.txt @@ -12,6 +12,9 @@ endif() add_executable ( SimplexTreeUT simplex_tree_unit_test.cpp ) target_link_libraries(SimplexTreeUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(SimplexTreeUT ${TBB_RELEASE_LIBRARY}) +endif() # Do not forget to copy test files in current binary dir file(COPY "simplex_tree_for_unit_test.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 6f3d8603..1e088552 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -148,21 +148,72 @@ * * The following example requires the GNU Multiple Precision Arithmetic * Library (GMP) and will not be built if GMP is not installed: - * \li Persistent_cohomology/rips_multifield_persistence + * \li + * Persistent_cohomology/alpha_shapes_persistence.cpp + * \li + * Persistent_cohomology/performance_rips_persistence.cpp + * \li + * Persistent_cohomology/rips_multifield_persistence.cpp + * \li + * Simplex_tree/simplex_tree_from_alpha_shapes_3.cpp * * Having GMP version 4.2 or higher installed is recommended. * * \subsection cgal CGAL: * CGAL is a C++ library which provides easy access to efficient and reliable geometric algorithms. * + * Having CGAL version 4.4 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 + * * The following examples require the Computational Geometry Algorithms * Library (CGAL) 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 + * \li + * Persistent_cohomology/alpha_shapes_persistence.cpp + * \li + * Simplex_tree/simplex_tree_from_alpha_shapes_3.cpp * - * Having CGAL version 4.4 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 + * The following example requires CGAL version ≥ 4.6: + * \li + * Witness_complex/witness_complex_sphere.cpp + * + * \subsection tbb Threading Building Blocks: + * Intel® TBB lets you easily write parallel + * C++ programs that take full advantage of multicore performance, that are portable and composable, and that have + * future-proof scalability. + * + * Having Intel® TBB installed is recommended to parallelize and accelerate some GUDHI computations. + * + * The following examples are using Intel® TBB if installed: + * \li + * Bitmap_cubical_complex/Bitmap_cubical_complex.cpp + * \li + * Bitmap_cubical_complex/Bitmap_cubical_complex_periodic_boundary_conditions.cpp + * \li + * Bitmap_cubical_complex/Random_bitmap_cubical_complex.cpp + * \li + * Persistent_cohomology/alpha_shapes_persistence.cpp + * \li + * Simplex_tree/simple_simplex_tree.cpp + * \li + * Simplex_tree/simplex_tree_from_alpha_shapes_3.cpp + * \li + * Simplex_tree/simplex_tree_from_cliques_of_graph.cpp + * \li + * Persistent_cohomology/alpha_shapes_persistence.cpp + * \li + * Persistent_cohomology/parallel_rips_persistence.cpp + * \li + * Persistent_cohomology/performance_rips_persistence.cpp + * \li + * Persistent_cohomology/persistence_from_file.cpp + * \li + * Persistent_cohomology/persistence_from_simple_simplex_tree.cpp + * \li + * Persistent_cohomology/plain_homology.cpp + * \li + * Persistent_cohomology/rips_multifield_persistence.cpp + * \li + * Persistent_cohomology/rips_persistence.cpp * * \subsection demos Demos and examples * To build the demos and libraries, run the following commands in a terminal: @@ -206,3 +257,29 @@ make \endverbatim * \verbinclude biblio/how_to_cite_gudhi.bib */ +// List of Gudhi examples - Doxygen needs at least a file tag to analyse comments +/*! @file Examples + * @example Bitmap_cubical_complex/Bitmap_cubical_complex.cpp + * @example Bitmap_cubical_complex/Bitmap_cubical_complex_periodic_boundary_conditions.cpp + * @example Bitmap_cubical_complex/Random_bitmap_cubical_complex.cpp + * @example Contraction/Garland_heckbert.cpp + * @example Contraction/Rips_contraction.cpp + * @example Persistent_cohomology/alpha_shapes_persistence.cpp + * @example Persistent_cohomology/parallel_rips_persistence.cpp + * @example Persistent_cohomology/performance_rips_persistence.cpp + * @example Persistent_cohomology/persistence_from_file.cpp + * @example Persistent_cohomology/persistence_from_simple_simplex_tree.cpp + * @example Persistent_cohomology/plain_homology.cpp + * @example Persistent_cohomology/rips_multifield_persistence.cpp + * @example Persistent_cohomology/rips_persistence.cpp + * @example Simplex_tree/mini_simplex_tree.cpp + * @example Simplex_tree/simple_simplex_tree.cpp + * @example Simplex_tree/simplex_tree_from_alpha_shapes_3.cpp + * @example Simplex_tree/simplex_tree_from_cliques_of_graph.cpp + * @example Skeleton_blocker/Skeleton_blocker_from_simplices.cpp + * @example Skeleton_blocker/Skeleton_blocker_iteration.cpp + * @example Skeleton_blocker/Skeleton_blocker_link.cpp + * @example Witness_complex/witness_complex_from_file.cpp + * @example Witness_complex/witness_complex_sphere.cpp + */ + -- cgit v1.2.3 From 1233e7dc721673853c9484569e0828b92cb06f09 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 31 Mar 2016 14:46:01 +0000 Subject: Fix #include issue in generated documentation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1087 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2b837671f261bb093f599f6c421a3cf21f52b423 --- .../include/gudhi/Bitmap_cubical_complex.h | 6 ++++-- .../include/gudhi/Bitmap_cubical_complex_base.h | 12 ++++++++---- .../include/gudhi/Persistent_cohomology.h | 3 ++- .../include/gudhi/Persistent_cohomology/Field_Zp.h | 3 ++- .../include/gudhi/Persistent_cohomology/Multi_field.h | 3 ++- src/common/doc/main_page.h | 5 +++-- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index a6ba60d3..c1a3af5c 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -318,7 +318,8 @@ class Bitmap_cubical_complex : public T { }; /** - * Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. + * @class Filtration_simplex_range Bitmap_cubical_complex.h gudhi/Bitmap_cubical_complex.h + * @brief Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. **/ class Filtration_simplex_range { // Range over the simplices of the complex in the order of the filtration. @@ -489,7 +490,8 @@ class Bitmap_cubical_complex : public T { }; /** - * Class needed for compatibility with Gudhi. Not useful for other purposes. + * @class Skeleton_simplex_range Bitmap_cubical_complex.h gudhi/Bitmap_cubical_complex.h + * @brief Class needed for compatibility with Gudhi. Not useful for other purposes. **/ class Skeleton_simplex_range { // Range over the simplices of the complex in the order of the filtration. diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 4bdc94ef..7904eb5b 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -190,7 +190,8 @@ class Bitmap_cubical_complex_base { // ITERATORS /** - * Iterator through all cells in the complex (in order they appear in the structure -- i.e. + * @class All_cells_iterator Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h + * @brief Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ class All_cells_iterator : std::iterator< std::input_iterator_tag, T > { @@ -258,7 +259,8 @@ class Bitmap_cubical_complex_base { } /** - * All_cells_range class provides ranges for All_cells_iterator + * @class All_cells_range Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h + * @brief All_cells_range class provides ranges for All_cells_iterator **/ class All_cells_range { public: @@ -309,7 +311,8 @@ class Bitmap_cubical_complex_base { } /** - * Iterator through top dimensional cells of the complex. The cells appear in order they are stored + * @class Top_dimensional_cells_iterator Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h + * @brief Iterator through top dimensional cells of the complex. The cells appear in order they are stored * in the structure (i.e. in lexicographical order) **/ class Top_dimensional_cells_iterator : std::iterator< std::input_iterator_tag, T > { @@ -411,7 +414,8 @@ class Bitmap_cubical_complex_base { } /** - * Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range + * @class Top_dimensional_cells_range Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h + * @brief Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range **/ class Top_dimensional_cells_range { public: diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index 1b86f1f9..d77b993e 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -174,7 +174,8 @@ different representations. @{ */ -/** \brief Computes the persistent cohomology of a filtered complex. +/** \class Persistent_cohomology Persistent_cohomology.h gudhi/Persistent_cohomology.h + * \brief Computes the persistent cohomology of a filtered complex. * * The computation is implemented with a Compressed Annotation Matrix * (CAM)\cite DBLP:conf/esa/BoissonnatDM13, diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Field_Zp.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Field_Zp.h index 6db16e69..458dff98 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Field_Zp.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Field_Zp.h @@ -30,7 +30,8 @@ namespace Gudhi { namespace persistent_cohomology { -/** \brief Structure representing the coefficient field \f$\mathbb{Z}/p\mathbb{Z}\f$ +/** \class Field_Zp Field_Zp.h gudhi/Persistent_cohomology/Field_Zp.h + * \brief Structure representing the coefficient field \f$\mathbb{Z}/p\mathbb{Z}\f$ * * \implements CoefficientField * \ingroup persistent_cohomology diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h index 38bc08d1..5f987545 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h @@ -32,7 +32,8 @@ namespace Gudhi { namespace persistent_cohomology { -/** \brief Structure representing coefficients in a set of finite fields simultaneously +/** \class Multi_field Multi_field.h gudhi/Persistent_cohomology/Multi_field.h + * \brief Structure representing coefficients in a set of finite fields simultaneously * using the chinese remainder theorem. * * \implements CoefficientField diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 1e088552..af7be0bf 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -127,7 +127,7 @@ Computation of persistent cohomology using the algorithm of \cite DBLP:journals/dcg/SilvaMV11 and \cite DBLP:journals/corr/abs-1208-5018 and the Compressed Annotation Matrix implementation of \cite DBLP:conf/esa/BoissonnatDM13 .
- User manual: \ref persistent_cohomology + User manual: \ref persistent_cohomology - Reference manual: Gudhi::persistent_cohomology::Persistent_cohomology
- Author: Clément Maria
+ Author: Clément Maria
Introduced in: GUDHI 1.0.0
Copyright: GPL v3
@@ -216,12 +216,13 @@ * Persistent_cohomology/rips_persistence.cpp * * \subsection demos Demos and examples - * To build the demos and libraries, run the following commands in a terminal: + * To build the demos and examples, run the following commands in a terminal: \verbatim cd /path-to-gudhi/ mkdir build cd build/ cmake .. make \endverbatim + * A list of examples is available here. * * \subsection testsuites Test suites * To test your build, run the following command in a terminal: -- cgit v1.2.3 From 5aee0d98ee764381f9af75f52fc747cefd3848cb Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 31 Mar 2016 14:49:42 +0000 Subject: Remove Upcoming page. Now available on Gudhi web site git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1088 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 09edbd70b95b6bd60f1324faebda1e24533be9a9 --- src/common/doc/main_page.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index af7be0bf..2f52fd7e 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -236,17 +236,6 @@ make \endverbatim * */ -/*! \page Upcoming Upcoming - * - * The library is under active development. New packages to be released next include: - * \li Alpha complex. - * \li Bottleneck distance. - * \li Zig zag persistence. - * \li Witness complex. - * \li Tangential complex. - * \li Clustering. -*/ - /*! \page Citation Acknowledging the GUDHI library * We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use * of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages. -- cgit v1.2.3 From 713749e0b82988106d8e4d296a87f0594e759ce0 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 31 Mar 2016 15:40:49 +0000 Subject: Unset CGAL_FOUND if CGAL version is less than 4.4 to fix compilation issue with CGAL 4.2. Documentation says CGAL > 4.4 is recommended. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1089 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b20d01d56e080572b067898df94ebe2eebd5893d --- CMakeLists.txt | 5 +++++ src/CMakeLists.txt | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cb8b86b..94336e19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,11 @@ else() # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html # but it implies to use cmake version 3.1 at least. find_package(CGAL) + # Only CGAL versions > 4.4 supports what Gudhi uses from CGAL + if (CGAL_VERSION VERSION_LESS 4.4.0) + message("CGAL version ${CGAL_VERSION} is considered too old to be used by Gudhi.") + unset(CGAL_FOUND) + endif() if(CGAL_FOUND) include( ${CGAL_USE_FILE} ) endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d4abe96d..60315338 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,11 @@ else() # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html # but it implies to use cmake version 3.1 at least. find_package(CGAL) + # Only CGAL versions > 4.4 supports what Gudhi uses from CGAL + if (CGAL_VERSION VERSION_LESS 4.4.0) + message("CGAL version ${CGAL_VERSION} is considered too old to be used by Gudhi.") + unset(CGAL_FOUND) + endif() if(CGAL_FOUND) include( ${CGAL_USE_FILE} ) endif() -- cgit v1.2.3 From 178b86f53cb16964de4365948ada341b7012c1da Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 1 Apr 2016 07:56:34 +0000 Subject: Rollback of class #include. Done from Doxyfile with STRIP_FROM_INC_PATH. Modified Gudhi banner to fix "Geometric Uderstanding" into "Geometry Uderstanding" git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Doxygen_for_GUDHI_1.3.0@1090 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c5830fb6f583118a5078254fde5d4a97210c10b7 --- .../include/gudhi/Bitmap_cubical_complex.h | 3 --- .../include/gudhi/Bitmap_cubical_complex/counter.h | 5 ++--- .../include/gudhi/Bitmap_cubical_complex_base.h | 5 ----- ..._cubical_complex_periodic_boundary_conditions_base.h | 1 - src/Doxyfile | 2 +- .../include/gudhi/Persistent_cohomology.h | 3 +-- .../include/gudhi/Persistent_cohomology/Field_Zp.h | 3 +-- .../include/gudhi/Persistent_cohomology/Multi_field.h | 3 +-- src/common/doc/Gudhi_banner.jpg | Bin 34437 -> 0 bytes src/common/doc/Gudhi_banner.png | Bin 0 -> 34877 bytes src/common/doc/main_page.h | 2 +- 11 files changed, 7 insertions(+), 20 deletions(-) delete mode 100644 src/common/doc/Gudhi_banner.jpg create mode 100644 src/common/doc/Gudhi_banner.png diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h index c1a3af5c..56fa297c 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex.h @@ -46,7 +46,6 @@ const bool globalDbg = false; template class is_before_in_filtration; /** - * @class Bitmap_cubical_complex Bitmap_cubical_complex.h gudhi/Bitmap_cubical_complex.h * @brief Cubical complex represented as a bitmap. * @ingroup cubical_complex * @details This is a Bitmap_cubical_complex class. It joints a functionalities of Bitmap_cubical_complex_base and @@ -318,7 +317,6 @@ class Bitmap_cubical_complex : public T { }; /** - * @class Filtration_simplex_range Bitmap_cubical_complex.h gudhi/Bitmap_cubical_complex.h * @brief Filtration_simplex_range provides the ranges for Filtration_simplex_iterator. **/ class Filtration_simplex_range { @@ -490,7 +488,6 @@ class Bitmap_cubical_complex : public T { }; /** - * @class Skeleton_simplex_range Bitmap_cubical_complex.h gudhi/Bitmap_cubical_complex.h * @brief Class needed for compatibility with Gudhi. Not useful for other purposes. **/ class Skeleton_simplex_range { diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h index bee19344..3a8c3988 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex/counter.h @@ -31,9 +31,8 @@ namespace Gudhi { namespace Cubical_complex { /** - * @class counter counter.h gudhi/Bitmap_cubical_complex/counter.h - * This is an implementation of a counter being a vector of integers. - * The constructor of the class takes as an input two vectors W and V. + * @brief This is an implementation of a counter being a vector of integers. + * @details The constructor of the class takes as an input two vectors W and V. * It assumes that W < V coordinatewise. * If the initial counter W is not specified, it is assumed to be vector of zeros. * The class allows to iterate between W and V by using increment() function. diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h index 7904eb5b..2f74ba9e 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_base.h @@ -39,7 +39,6 @@ namespace Gudhi { namespace Cubical_complex { /** - * @class Bitmap_cubical_complex_base Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h * @brief Cubical complex represented as a bitmap, class with basic implementation. * @ingroup cubical_complex * @details This is a class implementing a basic bitmap data structure to store cubical complexes. @@ -190,7 +189,6 @@ class Bitmap_cubical_complex_base { // ITERATORS /** - * @class All_cells_iterator Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h * @brief Iterator through all cells in the complex (in order they appear in the structure -- i.e. * in lexicographical order). **/ @@ -259,7 +257,6 @@ class Bitmap_cubical_complex_base { } /** - * @class All_cells_range Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h * @brief All_cells_range class provides ranges for All_cells_iterator **/ class All_cells_range { @@ -311,7 +308,6 @@ class Bitmap_cubical_complex_base { } /** - * @class Top_dimensional_cells_iterator Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h * @brief Iterator through top dimensional cells of the complex. The cells appear in order they are stored * in the structure (i.e. in lexicographical order) **/ @@ -414,7 +410,6 @@ class Bitmap_cubical_complex_base { } /** - * @class Top_dimensional_cells_range Bitmap_cubical_complex_base.h gudhi/Bitmap_cubical_complex_base.h * @brief Top_dimensional_cells_iterator_range class provides ranges for Top_dimensional_cells_iterator_range **/ class Top_dimensional_cells_range { diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 5b7e4115..0d0f2f84 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -39,7 +39,6 @@ namespace Cubical_complex { // the cells on the right / top are not in the Bitmap_cubical_complex_periodic_boundary_conditions_base /** - * @class Bitmap_cubical_complex_periodic_boundary_conditions_base Bitmap_cubical_complex_periodic_boundary_conditions_base.h gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h * @brief Cubical complex with periodic boundary conditions represented as a bitmap. * @ingroup cubical_complex * @details This is a class implementing a bitmap data structure with periodic boundary conditions. Most of the functions are diff --git a/src/Doxyfile b/src/Doxyfile index 63e7145c..abafdf16 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -153,7 +153,7 @@ STRIP_FROM_PATH = # specify the list of include paths that are normally passed to the compiler # using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = include concept # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index d77b993e..1b86f1f9 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -174,8 +174,7 @@ different representations. @{ */ -/** \class Persistent_cohomology Persistent_cohomology.h gudhi/Persistent_cohomology.h - * \brief Computes the persistent cohomology of a filtered complex. +/** \brief Computes the persistent cohomology of a filtered complex. * * The computation is implemented with a Compressed Annotation Matrix * (CAM)\cite DBLP:conf/esa/BoissonnatDM13, diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Field_Zp.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Field_Zp.h index 458dff98..6db16e69 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Field_Zp.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Field_Zp.h @@ -30,8 +30,7 @@ namespace Gudhi { namespace persistent_cohomology { -/** \class Field_Zp Field_Zp.h gudhi/Persistent_cohomology/Field_Zp.h - * \brief Structure representing the coefficient field \f$\mathbb{Z}/p\mathbb{Z}\f$ +/** \brief Structure representing the coefficient field \f$\mathbb{Z}/p\mathbb{Z}\f$ * * \implements CoefficientField * \ingroup persistent_cohomology diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h index 5f987545..38bc08d1 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h @@ -32,8 +32,7 @@ namespace Gudhi { namespace persistent_cohomology { -/** \class Multi_field Multi_field.h gudhi/Persistent_cohomology/Multi_field.h - * \brief Structure representing coefficients in a set of finite fields simultaneously +/** \brief Structure representing coefficients in a set of finite fields simultaneously * using the chinese remainder theorem. * * \implements CoefficientField diff --git a/src/common/doc/Gudhi_banner.jpg b/src/common/doc/Gudhi_banner.jpg deleted file mode 100644 index ebd3d8af..00000000 Binary files a/src/common/doc/Gudhi_banner.jpg and /dev/null differ diff --git a/src/common/doc/Gudhi_banner.png b/src/common/doc/Gudhi_banner.png new file mode 100644 index 00000000..18e8a672 Binary files /dev/null and b/src/common/doc/Gudhi_banner.png differ diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 2f52fd7e..1e0dbcda 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -1,6 +1,6 @@ /*! \mainpage * \tableofcontents - * \image html "Gudhi_banner.jpg" "" width=20cm + * \image html "Gudhi_banner.png" "" width=20cm * * \section Introduction Introduction * The Gudhi library (Geometry Understanding in Higher Dimensions) is a generic open source C++ library for -- cgit v1.2.3 From fde42a187d4a1a7abb4eaa3239cd884f8731b08a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 1 Apr 2016 08:50:48 +0000 Subject: cpplint/cppcheck fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1091 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1c274cd8c8a3c76fe35f96c7186bcbf3d8bee3e8 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 14 +++++++------- src/common/include/gudhi/reader_utils.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index f5bc0a11..afc7d613 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -955,7 +955,7 @@ class Simplex_tree { bool operator()(const Simplex_handle sh1, const Simplex_handle sh2) const { // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. if (sh1->second.filtration() != sh2->second.filtration()) { - return sh1->second.filtration() < sh2->second.filtration(); + return sh1->second.filtration() < sh2->second.filtration(); } // is sh1 a proper subface of sh2 return st_->reverse_lexicographic_order(sh1, sh2); @@ -1194,16 +1194,16 @@ class Simplex_tree { bool prune_above_filtration(Filtration_value filt) { return rec_prune_above_filtration(root(), filt); } - + private: bool rec_prune_above_filtration(Siblings* sib, Filtration_value filt) { - auto&& list=sib->members(); + auto&& list = sib->members(); auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) { - if (simplex.second.filtration()<=filt) return false; + if (simplex.second.filtration() <= filt) return false; if (has_children(&simplex)) rec_delete(simplex.second.children()); return true; }); - + bool modified = (last != list.end()); if (last == list.begin() && sib != root()) { // Removing the whole siblings, parent becomes a leaf. @@ -1213,8 +1213,8 @@ class Simplex_tree { } else { // Keeping some elements of siblings. Remove the others, and recurse in the remaining ones. list.erase(last, list.end()); - for(auto&& simplex : list) - if(has_children(&simplex)) + for (auto&& simplex : list) + if (has_children(&simplex)) modified |= rec_prune_above_filtration(simplex.second.children(), filt); } return modified; diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index da2c2c36..899f9df6 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -161,7 +161,7 @@ bool read_simplex(std::istream & in_, std::vector< Vertex_handle > & simplex, Fi simplex.push_back(v); } in_ >> fil; - in_.ignore((std::numeric_limits::max)(), '\n'); // ignore until the carriage return + in_.ignore((std::numeric_limits::max)(), '\n'); // ignore until the carriage return return true; } -- cgit v1.2.3 From 3d592b82f837219ee9ecd8e33120563edb4e76ab Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 06:19:05 +0000 Subject: Last modif git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1097 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d02c8b6bf27616ef515464a35e48b7871a69f9a8 --- .../include/gudhi/Delaunay_triangulation_off_io.h | 47 ++++++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 7bf5569e..50be9a59 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -27,6 +27,10 @@ #include #include +#include + +#include + #include "gudhi/Off_reader.h" namespace Gudhi { @@ -42,8 +46,9 @@ template class Delaunay_triangulation_off_visitor_reader { private: Complex* complex_; - typedef typename Complex::Point Point; - std::vector point_cloud; + 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. @@ -98,7 +103,7 @@ class Delaunay_triangulation_off_visitor_reader { std::cout << std::endl; #endif // DEBUG_TRACES // Fill the point cloud - point_cloud.push_back(Point(point.size(), point.begin(), point.end())); + point_cloud.push_back(Point_d(point.size(), point.begin(), point.end())); } // Off_reader visitor maximal_face implementation - not used @@ -110,7 +115,11 @@ class Delaunay_triangulation_off_visitor_reader { 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 - complex_->insert(point_cloud.begin(), point_cloud.end()); + 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. @@ -120,6 +129,36 @@ class Delaunay_triangulation_off_visitor_reader { 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); + } + }; /** -- 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 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 01d50e3c77a6f8a2aa7e538f90512482af85d317 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 11:18:19 +0000 Subject: CGAL version requires 4.7 to access CGAL Point_d dimension() function git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1099 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fe6bb4958f7d98427fb705b7c02b64bddb7e190d --- src/common/example/CMakeLists.txt | 4 ++-- src/common/test/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index 2914756e..5aeaa8c6 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -1,9 +1,9 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIDelaunayTriangulationOffFileReadWrite) -# need CGAL 4.6 +# need CGAL 4.7 if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 6205f0e4..789546ae 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -10,9 +10,9 @@ if (GPROF_PATH) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") endif() -# need CGAL 4.6 +# need CGAL 4.7 if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") -- cgit v1.2.3 From 94638281f656211b429ee20ed6be25a84db8074c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 19:21:39 +0000 Subject: GUDHIConfig.cmake fix Modules were missing in src/CMakeLists.txt generate_version.sh must copy GUDHIConfig.cmake and not GUDHIConfig.cmake.in nor CMakeGUDHIVersion.txt git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1100 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2b618b7a395017cb1bde8a9a7afd7c9e54c29710 --- CMakeLists.txt | 2 +- scripts/generate_version.sh | 3 +-- src/CMakeLists.txt | 10 ++++------ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index abb66ec2..e35da63e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project(GUDHIdev) include(CMakeGUDHIVersion.txt) # Generate GUDHI official version file -configure_file(GUDHIVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIVersion.cmake" @ONLY) +configure_file(GUDHIVersion.cmake.in "${CMAKE_SOURCE_DIR}/GUDHIVersion.cmake" @ONLY) find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework chrono timer program_options thread REQUIRED) diff --git a/scripts/generate_version.sh b/scripts/generate_version.sh index 323396dc..4482c506 100755 --- a/scripts/generate_version.sh +++ b/scripts/generate_version.sh @@ -45,7 +45,6 @@ mkdir "$VERSION_DIR" # TOP LEVEL FILE COPY cp $VERSION_FILE $VERSION_DIR -cp $ROOT_DIR/CMakeGUDHIVersion.txt $VERSION_DIR cp $ROOT_DIR/README $VERSION_DIR cp $ROOT_DIR/Conventions.txt $VERSION_DIR cp $ROOT_DIR/COPYING $VERSION_DIR @@ -55,7 +54,7 @@ cp $ROOT_DIR/src/Doxyfile $VERSION_DIR cp -R $ROOT_DIR/biblio $VERSION_DIR cp $ROOT_DIR/src/GUDHIConfigVersion.cmake.in $VERSION_DIR cp $ROOT_DIR/src/GUDHIConfig.cmake.in $VERSION_DIR -cp $ROOT_DIR/GUDHIVersion.cmake.in $VERSION_DIR +cp $ROOT_DIR/GUDHIVersion.cmake $VERSION_DIR # PACKAGE LEVEL COPY PACKAGE_INC_DIR="/include" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40b7dd58..42d3755a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 2.6) project(GUDHI) -include("CMakeGUDHIVersion.txt") - enable_testing() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") @@ -66,10 +64,10 @@ else() # Gudhi compilation part include_directories(include) - #add_subdirectory(example/Simplex_tree) - #add_subdirectory(example/Persistent_cohomology) - #add_subdirectory(example/Skeleton_blocker) - #add_subdirectory(example/Contraction) + add_subdirectory(example/Simplex_tree) + add_subdirectory(example/Persistent_cohomology) + add_subdirectory(example/Skeleton_blocker) + add_subdirectory(example/Contraction) add_subdirectory(example/Bitmap_cubical_complex) add_subdirectory(example/Witness_complex) -- 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(-) 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(-) 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 e61484887ab37b1295114eca0c8996e98a72e41e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 7 Apr 2016 15:52:20 +0000 Subject: Fix Doxygen warning git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1104 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c5873a4a207f01e20729d3ce964ae67f6cf55331 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index afc7d613..f60e5c72 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1191,8 +1191,8 @@ class Simplex_tree { * 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 filt) { - return rec_prune_above_filtration(root(), filt); + bool prune_above_filtration(Filtration_value filtration) { + return rec_prune_above_filtration(root(), filtration); } private: -- cgit v1.2.3 From 3cabde73eaf1a29f36a6014bccc795349666346c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 7 Apr 2016 16:07:03 +0000 Subject: get_point_cloud can be const git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1105 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c9b905e8f01c671964b4151883a6385e47adaa06 --- src/common/include/gudhi/Points_off_io.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h index 79287e3c..1bd5c1e6 100644 --- a/src/common/include/gudhi/Points_off_io.h +++ b/src/common/include/gudhi/Points_off_io.h @@ -92,7 +92,7 @@ class Points_off_visitor_reader { * * @return point_cloud. */ - const std::vector& get_point_cloud() { + const std::vector& get_point_cloud() const { return point_cloud; } }; @@ -161,7 +161,7 @@ class Points_off_reader { * * @return point_cloud. */ - const std::vector& get_point_cloud() { + const std::vector& get_point_cloud() const { return point_cloud; } -- cgit v1.2.3 From 0ca1fbeb35a9a681320186f63a7cf26256ebf05a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 8 Apr 2016 08:44:07 +0000 Subject: GUDHIConfig.cmake fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1106 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 79bac32f28985e759f0e3c04a470e29325ecd64f --- scripts/generate_version.sh | 5 ++--- src/CMakeLists.txt | 7 ++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/generate_version.sh b/scripts/generate_version.sh index 4482c506..6f66a638 100755 --- a/scripts/generate_version.sh +++ b/scripts/generate_version.sh @@ -44,7 +44,6 @@ echo $VERSION_DIR mkdir "$VERSION_DIR" # TOP LEVEL FILE COPY -cp $VERSION_FILE $VERSION_DIR cp $ROOT_DIR/README $VERSION_DIR cp $ROOT_DIR/Conventions.txt $VERSION_DIR cp $ROOT_DIR/COPYING $VERSION_DIR @@ -54,11 +53,11 @@ cp $ROOT_DIR/src/Doxyfile $VERSION_DIR cp -R $ROOT_DIR/biblio $VERSION_DIR cp $ROOT_DIR/src/GUDHIConfigVersion.cmake.in $VERSION_DIR cp $ROOT_DIR/src/GUDHIConfig.cmake.in $VERSION_DIR -cp $ROOT_DIR/GUDHIVersion.cmake $VERSION_DIR +cp $ROOT_DIR/CMakeGUDHIVersion.txt $VERSION_DIR +cp $ROOT_DIR/GUDHIVersion.cmake.in $VERSION_DIR # PACKAGE LEVEL COPY PACKAGE_INC_DIR="/include" -#PACKAGE_SRC_DIR="/source" PACKAGE_EX_DIR="/example" PACKAGE_CONCEPT_DIR="/concept" PACKAGE_DOC_DIR="/doc" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 42d3755a..00bdf800 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,10 @@ cmake_minimum_required(VERSION 2.6) project(GUDHI) +include("CMakeGUDHIVersion.txt") +# Generate GUDHI official version file +configure_file(GUDHIVersion.cmake.in "${CMAKE_SOURCE_DIR}/GUDHIVersion.cmake" @ONLY) + enable_testing() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") @@ -85,8 +89,9 @@ else() # (this registers the build-tree with a global CMake-registry) export(PACKAGE GUDHI) + message("++ make install will install ${PROJECT_NAME} in the following directory : ${CMAKE_INSTALL_PREFIX}") # Create the GUDHIConfig.cmake and GUDHIConfigVersion files - set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include") + set(CONF_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/include") configure_file(GUDHIConfig.cmake.in "${PROJECT_BINARY_DIR}/GUDHIConfig.cmake" @ONLY) configure_file(GUDHIConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIConfigVersion.cmake" @ONLY) -- cgit v1.2.3 From 607fc8aa10122089aa2b3debf36e48250e2dfb5b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 8 Apr 2016 13:34:12 +0000 Subject: Modification on CMakeLists.txt for code coverage were not propagated on these 2 test files git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@1109 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8dc143d808040f903ac9c5e0b967fcf3fc4c9ba4 --- src/Bitmap_cubical_complex/test/CMakeLists.txt | 4 ---- src/Witness_complex/test/CMakeLists.txt | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/Bitmap_cubical_complex/test/CMakeLists.txt b/src/Bitmap_cubical_complex/test/CMakeLists.txt index 97c374e6..b6fc8a3b 100644 --- a/src/Bitmap_cubical_complex/test/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/test/CMakeLists.txt @@ -4,14 +4,10 @@ project(GUDHIBitmapCCUT) if (GCOVR_PATH) # for gcovr to make coverage reports - Corbera Jenkins plugin set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage") endif() if (GPROF_PATH) # for gprof to make coverage reports - Jenkins set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pg") endif() add_executable ( BitmapCCUT Bitmap_test.cpp ) diff --git a/src/Witness_complex/test/CMakeLists.txt b/src/Witness_complex/test/CMakeLists.txt index 9422c152..37bef2d0 100644 --- a/src/Witness_complex/test/CMakeLists.txt +++ b/src/Witness_complex/test/CMakeLists.txt @@ -4,14 +4,10 @@ project(GUDHIWitnessComplexUT) if (GCOVR_PATH) # for gcovr to make coverage reports - Corbera Jenkins plugin set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage") endif() if (GPROF_PATH) # for gprof to make coverage reports - Jenkins set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pg") endif() add_executable ( simple_witness_complexUT simple_witness_complex.cpp ) -- cgit v1.2.3