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 --- data/points/generator/hypergenerator.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'data') 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 -- cgit v1.2.3 From 56e89b6b7666dec86a70f6a30f08ef8b7960eb21 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 Jun 2015 14:21:31 +0000 Subject: Moved alphashapedoc.off in data/points Moved Delaunay triangulation OFF files read and write in src/common Delaunay triangulation OFF files read and write documentation, examples and tests git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@623 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e03902736a79436e97dbf77a88504f3faa8bd9c6 --- CMakeLists.txt | 9 +- data/points/alphashapedoc.off | 10 + src/Alpha_complex/example/CMakeLists.txt | 9 +- .../example/Delaunay_triangulation_off_rw.cpp | 79 ------ .../Simplex_tree_from_delaunay_triangulation.cpp | 27 +- src/Alpha_complex/example/alphashapedoc.off | 10 - src/Alpha_complex/include/gudhi/Alpha_complex.h | 70 +++-- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 210 -------------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 71 ++--- src/Alpha_complex/test/CMakeLists.txt | 2 +- src/Alpha_complex/test/README | 2 +- src/Alpha_complex/test/S4_100.off | 4 +- src/Alpha_complex/test/S8_10.off | 4 +- src/CMakeLists.txt | 1 + src/Doxyfile | 3 +- src/common/example/CMakeLists.txt | 26 ++ .../example/Delaunay_triangulation_off_rw.cpp | 55 ++++ .../include/gudhi/Delaunay_triangulation_off_io.h | 308 +++++++++++++++++++++ src/common/include/gudhi/Off_reader.h | 291 ++++++++++--------- src/common/test/CMakeLists.txt | 44 +++ src/common/test/README | 14 + src/common/test/dtoffrw_alphashapedoc_result.off | 15 + src/common/test/dtoffrw_alphashapedoc_result.txt | 3 + src/common/test/dtoffrw_unit_test.cpp | 91 ++++++ 24 files changed, 790 insertions(+), 568 deletions(-) create mode 100755 data/points/alphashapedoc.off delete mode 100644 src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp delete mode 100755 src/Alpha_complex/example/alphashapedoc.off delete mode 100644 src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h create mode 100644 src/common/example/CMakeLists.txt create mode 100644 src/common/example/Delaunay_triangulation_off_rw.cpp create mode 100644 src/common/include/gudhi/Delaunay_triangulation_off_io.h create mode 100644 src/common/test/CMakeLists.txt create mode 100644 src/common/test/README create mode 100644 src/common/test/dtoffrw_alphashapedoc_result.off create mode 100644 src/common/test/dtoffrw_alphashapedoc_result.txt create mode 100644 src/common/test/dtoffrw_unit_test.cpp (limited to 'data') 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 01b0bf84f780b9998a48f0dbe338319da1c6d6f2 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 23 Jun 2015 13:50:46 +0000 Subject: Alpha complex documentation - 2nd part git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@633 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 023b5aaa57593a4e8e77cf12f388559b638f0eb1 --- data/points/alphacomplexdoc.off | 10 + data/points/alphashapedoc.off | 10 - src/Alpha_complex/doc/alpha_complex_doc.ipe | 438 ++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc.png | Bin 0 -> 46226 bytes src/Alpha_complex/doc/alpha_complex_doc_135.ipe | 514 +++++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 0 -> 94098 bytes .../doc/alpha_complex_doc_alpha_shape.ipe | 493 ++++++++++++++++++++ .../doc/alpha_complex_doc_alpha_shape.png | Bin 0 -> 70425 bytes src/Alpha_complex/include/gudhi/Alpha_complex.h | 90 +++- src/Doxyfile | 3 +- 10 files changed, 1531 insertions(+), 27 deletions(-) create mode 100755 data/points/alphacomplexdoc.off delete mode 100755 data/points/alphashapedoc.off create mode 100644 src/Alpha_complex/doc/alpha_complex_doc.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc.png create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.png create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png (limited to 'data') 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: 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 (limited to 'data') 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 c85b24f7e0c489093e0c5ccca934eb53fafab623 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 4 Feb 2016 16:11:42 +0000 Subject: CMake strategy modification git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Win64_Boost_Xunit_fix@1003 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c917934525e020b54b2f4506b5c9d060a28c9d89 --- CMakeLists.txt | 105 +++++++++++++++----------- data/points/generator/CMakeLists.txt | 16 ---- src/Bottleneck/test/CMakeLists.txt | 4 - src/CMakeLists.txt | 67 ++++++++++------ src/GudhUI/CMakeLists.txt | 20 ----- src/Persistent_cohomology/test/CMakeLists.txt | 4 - src/Simplex_tree/example/CMakeLists.txt | 17 ----- src/Simplex_tree/test/CMakeLists.txt | 4 - src/Skeleton_blocker/test/CMakeLists.txt | 4 - 9 files changed, 105 insertions(+), 136 deletions(-) (limited to 'data') diff --git a/CMakeLists.txt b/CMakeLists.txt index edf7e63f..8ced7b0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,52 +7,71 @@ configure_file(GUDHIVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIVersion.cmake" find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework chrono timer program_options thread REQUIRED) -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() - -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_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") -endif() - -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) -set(Boost_USE_STATIC_RUNTIME OFF) - -find_package(GMP) -if(GMP_FOUND) - find_package(GMPXX) -endif() - -find_package(CGAL) - -# Find TBB package for parallel sort - not mandatory, just optional. -set(TBB_FIND_QUIETLY ON) -find_package(TBB) - -# Required programs for unitary tests purpose -FIND_PROGRAM( GCOVR_PATH gcovr ) -if (GCOVR_PATH) - message("gcovr found in ${GCOVR_PATH}") -endif() -# Required programs for unitary tests purpose -FIND_PROGRAM( GPROF_PATH gprof ) -if (GPROF_PATH) - message("gprof found in ${GPROF_PATH}") -endif() - - if(NOT Boost_FOUND) message(FATAL_ERROR "NOTICE: This demo requires Boost and will not be compiled.") else() + + 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() + + find_package(GMP) + if(GMP_FOUND) + INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) + find_package(GMPXX) + if(GMPXX_FOUND) + INCLUDE_DIRECTORIES(${GMPXX_INCLUDE_DIR}) + endif() + endif() + + # find CGAL package before set of CXX flags because + # in CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + set(CGAL_DONT_OVERRIDE_CMAKE_FLAGS TRUE CACHE BOOL "Force CGAL to maintain CMAKE flags") + find_package(CGAL) + if(CGAL_FOUND) + include( ${CGAL_USE_FILE} ) + set(CMAKE_CXX_CGAL_FOR_GUDHI_FLAGS "-frounding-math") + endif() + + 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} -std=c++11 -Wall -Wpedantic -Wsign-compare ${CMAKE_CXX_CGAL_FOR_GUDHI_FLAGS}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O0") + # set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + endif() + + if(CMAKE_BUILD_TYPE MATCHES Debug) + message("Compilation flags are: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}") + else() + message("Compilation flags are: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}") + endif() + + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) + set(Boost_USE_STATIC_RUNTIME OFF) + + # Find TBB package for parallel sort - not mandatory, just optional. + set(TBB_FIND_QUIETLY ON) + find_package(TBB) + + # Required programs for unitary tests purpose + FIND_PROGRAM( GCOVR_PATH gcovr ) + if (GCOVR_PATH) + message("gcovr found in ${GCOVR_PATH}") + endif() + # Required programs for unitary tests purpose + FIND_PROGRAM( GPROF_PATH gprof ) + if (GPROF_PATH) + message("gprof found in ${GPROF_PATH}") + endif() + + # BOOST ISSUE result_of vs C++11 add_definitions(-DBOOST_RESULT_OF_USE_DECLTYPE) # BOOST ISSUE with Libraries name resolution under Windows diff --git a/data/points/generator/CMakeLists.txt b/data/points/generator/CMakeLists.txt index 26b44446..c01a380d 100644 --- a/data/points/generator/CMakeLists.txt +++ b/data/points/generator/CMakeLists.txt @@ -5,22 +5,6 @@ if(CGAL_FOUND) if (NOT CGAL_VERSION VERSION_LESS 4.6.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) include( ${EIGEN3_USE_FILE} ) diff --git a/src/Bottleneck/test/CMakeLists.txt b/src/Bottleneck/test/CMakeLists.txt index 3dfd80cd..ad63c080 100644 --- a/src/Bottleneck/test/CMakeLists.txt +++ b/src/Bottleneck/test/CMakeLists.txt @@ -4,14 +4,10 @@ project(GUDHIBottleneckUT) 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 ( BottleneckUT bottleneck_unit_test.cpp ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3c38483c..a67e7c92 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,33 +9,52 @@ 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() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -endif() - -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) -set(Boost_USE_STATIC_RUNTIME OFF) - -find_package(GMP) -if(GMP_FOUND) - find_package(GMPXX) -endif() - -find_package(CGAL) - -# Find TBB package for parallel sort - not mandatory, just optional. -set(TBB_FIND_QUIETLY ON) -find_package(TBB) - if(NOT Boost_FOUND) message(FATAL_ERROR "NOTICE: This demo requires Boost and will not be compiled.") else() + + find_package(GMP) + if(GMP_FOUND) + INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) + find_package(GMPXX) + if(GMPXX_FOUND) + INCLUDE_DIRECTORIES(${GMPXX_INCLUDE_DIR}) + endif() + endif() + + # find CGAL package before set of CXX flags because + # in CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + set(CGAL_DONT_OVERRIDE_CMAKE_FLAGS TRUE CACHE BOOL "Force CGAL to maintain CMAKE flags") + find_package(CGAL) + if(CGAL_FOUND) + include( ${CGAL_USE_FILE} ) + set(CMAKE_CXX_CGAL_FOR_GUDHI_FLAGS "-frounding-math") + endif() + + 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() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CMAKE_CXX_CGAL_FOR_GUDHI_FLAGS}") + endif() + + if(CMAKE_BUILD_TYPE MATCHES Debug) + message("Compilation flags are: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}") + else() + message("Compilation flags are: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}") + endif() + + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) + set(Boost_USE_STATIC_RUNTIME OFF) + + # Find TBB package for parallel sort - not mandatory, just optional. + set(TBB_FIND_QUIETLY ON) + find_package(TBB) + # BOOST ISSUE result_of vs C++11 add_definitions(-DBOOST_RESULT_OF_USE_DECLTYPE) # BOOST ISSUE with Libraries name resolution under Windows diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index 71f4fd1a..1ee43d91 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required(VERSION 2.8) project(GudhUI) -find_package(CGAL COMPONENTS Qt4) find_package(Qt4) find_package(QGLViewer) find_package(OpenGL) @@ -14,27 +13,8 @@ if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND ) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREAD OFF) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) - LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) - include(${QT_USE_FILE}) - 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 - include_directories (${QGLVIEWER_INCLUDE_DIR}) include_directories(.) diff --git a/src/Persistent_cohomology/test/CMakeLists.txt b/src/Persistent_cohomology/test/CMakeLists.txt index ed63a6ac..d16be5be 100644 --- a/src/Persistent_cohomology/test/CMakeLists.txt +++ b/src/Persistent_cohomology/test/CMakeLists.txt @@ -4,14 +4,10 @@ project(GUDHIPersistentCohomologyUT) 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 ( PersistentCohomologyUT persistent_cohomology_unit_test.cpp ) diff --git a/src/Simplex_tree/example/CMakeLists.txt b/src/Simplex_tree/example/CMakeLists.txt index a86b99a1..200161a6 100644 --- a/src/Simplex_tree/example/CMakeLists.txt +++ b/src/Simplex_tree/example/CMakeLists.txt @@ -14,23 +14,6 @@ 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) - 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 - - INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) 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}) 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) diff --git a/src/Simplex_tree/test/CMakeLists.txt b/src/Simplex_tree/test/CMakeLists.txt index c9eae163..1f2f7d33 100644 --- a/src/Simplex_tree/test/CMakeLists.txt +++ b/src/Simplex_tree/test/CMakeLists.txt @@ -4,14 +4,10 @@ project(GUDHISimplexTreeUT) 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 ( SimplexTreeUT simplex_tree_unit_test.cpp ) diff --git a/src/Skeleton_blocker/test/CMakeLists.txt b/src/Skeleton_blocker/test/CMakeLists.txt index 8b6fb672..5e063845 100644 --- a/src/Skeleton_blocker/test/CMakeLists.txt +++ b/src/Skeleton_blocker/test/CMakeLists.txt @@ -4,14 +4,10 @@ project(GUDHIskbl) 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(TestSkeletonBlockerComplex TestSkeletonBlockerComplex.cpp) -- 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 (limited to 'data') 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