From f9c64afdd4c0fcfa291e59ea179b7272ec5932af Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 3 Apr 2015 08:43:14 +0000 Subject: Build was failed (no propagation of -std=c++11) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@541 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0848ecde6740c37ba0f2e8a69890908a065b5228 --- src/Alpha_shapes/example/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Alpha_shapes/example/CMakeLists.txt b/src/Alpha_shapes/example/CMakeLists.txt index fb94ca05..dab3861c 100644 --- a/src/Alpha_shapes/example/CMakeLists.txt +++ b/src/Alpha_shapes/example/CMakeLists.txt @@ -13,7 +13,6 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - include_directories (BEFORE "../../include") add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) -- cgit v1.2.3 From 7f8b2a07a463fdcec12430abe2119d4f86a72517 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 29 May 2015 10:34:14 +0000 Subject: Alpha_shapes filtration value git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@599 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 303ed34da0718312e4bab3f50b7196acded94cec --- src/Alpha_shapes/example/CMakeLists.txt | 9 +- .../example/Delaunay_triangulation_off_rw.cpp | 2 +- .../Simplex_tree_from_delaunay_triangulation.cpp | 32 +----- src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 89 +++++++++++----- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 113 +++++++-------------- src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp | 2 +- src/Alpha_shapes/test/CMakeLists.txt | 6 +- 7 files changed, 112 insertions(+), 141 deletions(-) diff --git a/src/Alpha_shapes/example/CMakeLists.txt b/src/Alpha_shapes/example/CMakeLists.txt index dab3861c..582a9322 100644 --- a/src/Alpha_shapes/example/CMakeLists.txt +++ b/src/Alpha_shapes/example/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIAlphaShapesExample) -# need CGAL 4.6 -# cmake -DCGAL_DIR=~/workspace/CGAL-4.6-beta1 ../../.. +# need CGAL 4.7 +# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) message(STATUS "CGAL version: ${CGAL_VERSION}.") include( ${CGAL_USE_FILE} ) @@ -13,12 +13,13 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) + + add_definitions(-DDEBUG_TRACES) add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(dtoffrw_tore3D ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off 3) - #add_definitions(-DDEBUG_TRACES) add_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) else() diff --git a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp index 03f6440d..a31c44ab 100644 --- a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp +++ b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp @@ -63,7 +63,7 @@ int main(int argc, char **argv) { T dt(dimension); std::string offFileName(argv[1]); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(offFileName, dt, true, true); + Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(offFileName, dt); if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << offFileName << std::endl; exit(-1); // ----- >> diff --git a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp index 3a17b519..11079a03 100644 --- a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -48,50 +48,24 @@ typedef CGAL::Delaunay_triangulation T; // TriangulationDataStructure template parameter void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off dimension" << std::endl; + std::cerr << "Usage: " << progName << " filename.off" << std::endl; exit(-1); // ----- >> } int main(int argc, char **argv) { - if (argc != 3) { + if (argc != 2) { std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; usage(argv[0]); } - int dimension = 0; - int returnedScanValue = sscanf(argv[2], "%d", &dimension); - if ((returnedScanValue == EOF) || (dimension <= 0)) { - std::cerr << "Error: " << argv[2] << " is not correct" << std::endl; - usage(argv[0]); - } - - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a Delaunay triangulation - // - // ---------------------------------------------------------------------------- - T dt(dimension); std::string off_file_name(argv[1]); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt, false, false); - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << off_file_name << std::endl; - exit(-1); // ----- >> - } - - std::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; - std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; - - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_dt(dt); - //std::cout << alpha_shapes_from_dt << std::endl; - // ---------------------------------------------------------------------------- // // Init of an alpha-shape from a OFF file // // ---------------------------------------------------------------------------- - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name, dimension); + Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); //std::cout << alpha_shapes_from_file << std::endl; std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index b8efdb4d..6f290938 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -47,6 +47,8 @@ namespace Gudhi { namespace alphashapes { +#define Kinit(f) =k.f() + /** \defgroup alpha_shapes Alpha shapes in dimension N *
Implementations:
@@ -86,16 +88,22 @@ class Alpha_shapes { */ typedef CGAL::Delaunay_triangulation Delaunay_triangulation; + typedef typename Kernel::Compute_squared_radius_d Squared_Radius; + typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; + + /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + typedef std::vector typeVectorPoint; + private: /** \brief Upper bound on the simplex tree of the simplicial complex.*/ Gudhi::Simplex_tree<> _st; public: - Alpha_shapes(std::string off_file_name, int dimension) { - Delaunay_triangulation dt(dimension); - Gudhi::alphashapes::Delaunay_triangulation_off_reader - off_reader(off_file_name, dt, true, true); + Alpha_shapes(std::string off_file_name) { + // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function + Delaunay_triangulation dt(3); + Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << off_file_name << std::endl; exit(-1); // ----- >> @@ -120,45 +128,70 @@ class Alpha_shapes { template void init(T triangulation) { _st.set_dimension(triangulation.maximal_dimension()); - _st.set_filtration(0.0); - // triangulation points list - for (auto vit = triangulation.finite_vertices_begin(); - vit != triangulation.finite_vertices_end(); ++vit) { - typeVectorVertex vertexVector; - Vertex_handle vertexHdl = std::distance(triangulation.finite_vertices_begin(), vit); - vertexVector.push_back(vertexHdl); + Filtration_value filtration_max = 0.0; - // Insert each point in the simplex tree - _st.insert_simplex(vertexVector, 0.0); + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + // triangulation full cells list + for (auto cit = triangulation.full_cells_begin(); cit != triangulation.full_cells_end(); ++cit) { + typeVectorVertex vertexVector; + typeVectorPoint pointVector; + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + if (!triangulation.is_infinite(*vit)) { + // Vector of vertex construction for simplex_tree structure + // Vertex handle is distance - 1 + Vertex_handle vertexHdl = std::distance(triangulation.vertices_begin(), *vit) - 1; + // infinite cell is -1 for infinite + vertexVector.push_back(vertexHdl); + // Vector of points for alpha_shapes filtration value computation + pointVector.push_back((*vit)->point()); #ifdef DEBUG_TRACES - std::cout << "P" << vertexHdl << ":"; - for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { - std::cout << *Coord << " "; + std::cout << "Point "; + for (auto Coord = (*vit)->point().cartesian_begin(); Coord != (*vit)->point().cartesian_end(); ++Coord) { + std::cout << *Coord << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + } } - std::cout << std::endl; + Filtration_value alpha_shapes_filtration = 0.0; + + if (!triangulation.is_infinite(cit)) { + alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); +#ifdef DEBUG_TRACES + std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; #endif // DEBUG_TRACES - } - // triangulation finite full cells list - for (auto cit = triangulation.finite_full_cells_begin(); - cit != triangulation.finite_full_cells_end(); ++cit) { - typeVectorVertex vertexVector; - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - // Vertex handle is distance - 1 - Vertex_handle vertexHdl = std::distance(triangulation.vertices_begin(), *vit) - 1; - vertexVector.push_back(vertexHdl); + } else { + Filtration_value tmp_filtration = 0.0; + bool is_gab = true; + for (auto vit = triangulation.finite_vertices_begin(); vit != triangulation.finite_vertices_end(); ++vit) { + if (CGAL::ON_UNBOUNDED_SIDE != is_gabriel(pointVector.begin(), pointVector.end(), vit->point())) { + is_gab = false; + // TODO(VR) : Compute minimum + + } + } + if (true == is_gab) { + alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); +#ifdef DEBUG_TRACES + std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; +#endif // DEBUG_TRACES + } } // Insert each point in the simplex tree - _st.insert_simplex_and_subfaces(vertexVector, 0.0); + _st.insert_simplex_and_subfaces(vertexVector, alpha_shapes_filtration); #ifdef DEBUG_TRACES - std::cout << "C" << std::distance(triangulation.finite_full_cells_begin(), cit) << ":"; + std::cout << "C" << std::distance(triangulation.full_cells_begin(), cit) << ":"; for (auto value : vertexVector) { std::cout << value << ' '; } std::cout << std::endl; #endif // DEBUG_TRACES } + _st.set_filtration(filtration_max); } public: diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h index 693b393e..3215c8f6 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h @@ -36,27 +36,35 @@ namespace alphashapes { *@brief Off reader visitor with flag that can be passed to Off_reader to read a Delaunay_triangulation_complex. */ template -class Delaunay_triangulation_off_flag_visitor_reader { +class Delaunay_triangulation_off_visitor_reader { Complex& complex_; typedef typename Complex::Point Point; - const bool load_only_points_; - public: - explicit Delaunay_triangulation_off_flag_visitor_reader(Complex& complex, bool load_only_points = false) : - complex_(complex), - load_only_points_(load_only_points) { } + + explicit Delaunay_triangulation_off_visitor_reader(Complex& complex) : + complex_(complex) { } void init(int dim, int num_vertices, int num_faces, int num_edges) { #ifdef DEBUG_TRACES - std::cout << "init" << std::endl; + std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; #endif // DEBUG_TRACES + if (num_faces > 0) { + std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << + "file for Delaunay triangulation - faces are computed." << std::endl; + } + if (num_edges > 0) { + std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << + "file for Delaunay triangulation - edges are computed." << std::endl; + } + //complex_.set_current_dimension(dim); } void point(const std::vector& point) { #ifdef DEBUG_TRACES - std::cout << "p "; - for (auto coordinate: point) { + std::cout << "Delaunay_triangulation_off_visitor_reader::point "; + for (auto coordinate : point) { std::cout << coordinate << " | "; } std::cout << std::endl; @@ -65,62 +73,19 @@ class Delaunay_triangulation_off_flag_visitor_reader { } void maximal_face(const std::vector& face) { - // For alpha shapes, only points are read - } - - void done() { + // For Delaunay Triangulation, only points are read #ifdef DEBUG_TRACES - std::cout << "done" << std::endl; -#endif // DEBUG_TRACES - } -}; - -/** - *@brief Off reader visitor that can be passed to Off_reader to read a Delaunay_triangulation_complex. - */ -template -class Delaunay_triangulation_off_visitor_reader { - Complex& complex_; - // typedef typename Complex::Vertex_handle Vertex_handle; - // typedef typename Complex::Simplex_handle Simplex_handle; - typedef typename Complex::Point Point; - - const bool load_only_points_; - std::vector points_; - // std::vector maximal_faces_; - - public: - explicit Delaunay_triangulation_off_visitor_reader(Complex& complex, bool load_only_points = false) : - complex_(complex), - load_only_points_(load_only_points) { } - - void init(int dim, int num_vertices, int num_faces, int num_edges) { -#ifdef DEBUG_TRACES - std::cout << "init - " << num_vertices << std::endl; -#endif // DEBUG_TRACES - // maximal_faces_.reserve(num_faces); - points_.reserve(num_vertices); - } - - void point(const std::vector& point) { -#ifdef DEBUG_TRACES - std::cout << "p "; - for (auto coordinate: point) { - std::cout << coordinate << " | "; + std::cout << "Delaunay_triangulation_off_visitor_reader::face "; + for (auto vertex : face) { + std::cout << vertex << " | "; } std::cout << std::endl; #endif // DEBUG_TRACES - points_.emplace_back(Point(point.size(), point.begin(), point.end())); - } - - void maximal_face(const std::vector& face) { - // For alpha shapes, only points are read } void done() { - complex_.insert(points_.begin(), points_.end()); #ifdef DEBUG_TRACES - std::cout << "done" << std::endl; + std::cout << "Delaunay_triangulation_off_visitor_reader::done" << std::endl; #endif // DEBUG_TRACES } }; @@ -131,27 +96,23 @@ class Delaunay_triangulation_off_visitor_reader { template class Delaunay_triangulation_off_reader { public: + /** * name_file : file to read * read_complex : complex that will receive the file content * read_only_points : specify true if only the points must be read */ - Delaunay_triangulation_off_reader(const std::string & name_file, Complex& read_complex, bool read_only_points = false, - bool is_flag = false) : valid_(false) { + Delaunay_triangulation_off_reader(const std::string & name_file, Complex& read_complex) : valid_(false) { std::ifstream stream(name_file); if (stream.is_open()) { - if (is_flag) { - // For alpha shapes, only points are read - Delaunay_triangulation_off_flag_visitor_reader off_visitor(read_complex, true); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - } else { - // For alpha shapes, only points are read - Delaunay_triangulation_off_visitor_reader off_visitor(read_complex, true); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - } + Delaunay_triangulation_off_visitor_reader off_visitor(read_complex); + Off_reader off_reader(stream); + valid_ = off_reader.read(off_visitor); + } else { + std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << + name_file << std::endl; } + } /** @@ -160,7 +121,7 @@ class Delaunay_triangulation_off_reader { bool is_valid() const { return valid_; } - + private: bool valid_; }; @@ -168,6 +129,7 @@ class Delaunay_triangulation_off_reader { template class Delaunay_triangulation_off_writer { public: + /** * name_file : file where the off will be written * save_complex : complex that be outputted in the file @@ -191,7 +153,7 @@ class Delaunay_triangulation_off_writer { // Finite cells list for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.finite_full_cells_end(); ++cit) { - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension + stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { auto vertexHdl = *vit; // auto vertexHdl = std::distance(save_complex.vertices_begin(), *vit) - 1; @@ -201,13 +163,14 @@ class Delaunay_triangulation_off_writer { } stream.close(); } else { - std::cerr << "could not open file " << name_file << std::endl; + std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << + name_file << std::endl; } } }; -} // namespace alphashapes +} // namespace alphashapes -} // namespace Gudhi +} // namespace Gudhi #endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp b/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp index a90704b6..d5db3bfa 100644 --- a/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp +++ b/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { std::string off_file_name("S8_10.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt, true, true); + Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); std::cout << "off_reader.is_valid()=" << off_reader.is_valid() << std::endl; BOOST_CHECK(off_reader.is_valid()); diff --git a/src/Alpha_shapes/test/CMakeLists.txt b/src/Alpha_shapes/test/CMakeLists.txt index a48c1a8f..3cf97b71 100644 --- a/src/Alpha_shapes/test/CMakeLists.txt +++ b/src/Alpha_shapes/test/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIAlphaShapesTest) -# need CGAL 4.6 -# cmake -DCGAL_DIR=~/workspace/CGAL-4.6-beta1 ../../.. +# need CGAL 4.7 +# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) message(STATUS "CGAL version: ${CGAL_VERSION}.") include( ${CGAL_USE_FILE} ) -- cgit v1.2.3 From 2445eaa9d34272832a8edd680e30c2b8b3298242 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 9 Jun 2015 11:20:14 +0000 Subject: Checkin for rollback purpose. Compiles but do not work. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@607 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e163ca16ebc76a13cec21bf881fe3b03e0617711 --- .../example/Delaunay_triangulation_off_rw.cpp | 4 +- .../Simplex_tree_from_delaunay_triangulation.cpp | 2 +- src/Alpha_shapes/example/alphashapedoc.off | 10 ++++ src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 45 ++++++++++-------- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 54 +++++++++++++++++----- 5 files changed, 80 insertions(+), 35 deletions(-) create mode 100755 src/Alpha_shapes/example/alphashapedoc.off diff --git a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp index a31c44ab..6c9fcdab 100644 --- a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp +++ b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp @@ -82,7 +82,7 @@ int main(int argc, char **argv) { } std::cout << std::endl;*/ - int i = 0, j = 0; + /*int i = 0, j = 0; typedef T::Full_cell_iterator Full_cell_iterator; typedef T::Facet Facet; @@ -96,7 +96,7 @@ int main(int argc, char **argv) { } std::cout << "There are " << i << " facets on the convex hull." << std::endl; std::cout << "There are " << j << " facets not on the convex hull." << std::endl; - +*/ std::string offOutputFile("out.off"); Gudhi::alphashapes::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); diff --git a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp index 11079a03..0a24fb56 100644 --- a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -66,12 +66,12 @@ int main(int argc, char **argv) { // // ---------------------------------------------------------------------------- Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); - //std::cout << alpha_shapes_from_file << std::endl; std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; + //std::cout << alpha_shapes_from_file << std::endl; return 0; } \ No newline at end of file diff --git a/src/Alpha_shapes/example/alphashapedoc.off b/src/Alpha_shapes/example/alphashapedoc.off new file mode 100755 index 00000000..bb790193 --- /dev/null +++ b/src/Alpha_shapes/example/alphashapedoc.off @@ -0,0 +1,10 @@ +nOFF +2 7 0 0 +1.0 1.0 +7.0 0.0 +4.0 6.0 +9.0 6.0 +0.0 14.0 +2.0 19.0 +9.0 17.0 + diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index 6f290938..6de675f6 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -96,13 +96,13 @@ class Alpha_shapes { private: /** \brief Upper bound on the simplex tree of the simplicial complex.*/ - Gudhi::Simplex_tree<> _st; + Gudhi::Simplex_tree<> st_; public: - Alpha_shapes(std::string off_file_name) { + Alpha_shapes(std::string& off_file_name) { // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function - Delaunay_triangulation dt(3); + Delaunay_triangulation dt(2); Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << off_file_name << std::endl; @@ -117,7 +117,7 @@ class Alpha_shapes { } template - Alpha_shapes(T triangulation) { + Alpha_shapes(T& triangulation) { init(triangulation); } @@ -126,8 +126,8 @@ class Alpha_shapes { private: template - void init(T triangulation) { - _st.set_dimension(triangulation.maximal_dimension()); + void init(T& triangulation) { + st_.set_dimension(triangulation.maximal_dimension()); Filtration_value filtration_max = 0.0; Kernel k; @@ -148,11 +148,11 @@ class Alpha_shapes { // Vector of points for alpha_shapes filtration value computation pointVector.push_back((*vit)->point()); #ifdef DEBUG_TRACES - std::cout << "Point "; + /*std::cout << "Point "; for (auto Coord = (*vit)->point().cartesian_begin(); Coord != (*vit)->point().cartesian_end(); ++Coord) { std::cout << *Coord << " | "; } - std::cout << std::endl; + std::cout << std::endl;*/ #endif // DEBUG_TRACES } } @@ -161,66 +161,71 @@ class Alpha_shapes { if (!triangulation.is_infinite(cit)) { alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); #ifdef DEBUG_TRACES - std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; + //std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; #endif // DEBUG_TRACES } else { Filtration_value tmp_filtration = 0.0; bool is_gab = true; - for (auto vit = triangulation.finite_vertices_begin(); vit != triangulation.finite_vertices_end(); ++vit) { + /*for (auto vit = triangulation.finite_vertices_begin(); vit != triangulation.finite_vertices_end(); ++vit) { if (CGAL::ON_UNBOUNDED_SIDE != is_gabriel(pointVector.begin(), pointVector.end(), vit->point())) { is_gab = false; // TODO(VR) : Compute minimum } - } + }*/ if (true == is_gab) { alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); #ifdef DEBUG_TRACES - std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; + //std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; #endif // DEBUG_TRACES } } // Insert each point in the simplex tree - _st.insert_simplex_and_subfaces(vertexVector, alpha_shapes_filtration); + st_.insert_simplex_and_subfaces(vertexVector, alpha_shapes_filtration); #ifdef DEBUG_TRACES std::cout << "C" << std::distance(triangulation.full_cells_begin(), cit) << ":"; for (auto value : vertexVector) { std::cout << value << ' '; } - std::cout << std::endl; + std::cout << " | alpha=" << alpha_shapes_filtration << std::endl; #endif // DEBUG_TRACES } - _st.set_filtration(filtration_max); + st_.set_filtration(filtration_max); + } + + template + void recursive_init(T& triangulation, typeVectorVertex vertexVector) { + } public: /** \brief Returns the number of vertices in the complex. */ size_t num_vertices() { - return _st.num_vertices(); + return st_.num_vertices(); } /** \brief Returns the number of simplices in the complex. * * Does not count the empty simplex. */ const unsigned int& num_simplices() const { - return _st.num_simplices(); + return st_.num_simplices(); } /** \brief Returns an upper bound on the dimension of the simplicial complex. */ int dimension() { - return _st.dimension(); + return st_.dimension(); } /** \brief Returns an upper bound of the filtration values of the simplices. */ Filtration_value filtration() { - return _st.filtration(); + return st_.filtration(); } friend std::ostream& operator<<(std::ostream& os, const Alpha_shapes& alpha_shape) { // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor - Gudhi::Simplex_tree<> st = alpha_shape._st; + Gudhi::Simplex_tree<> st = alpha_shape.st_; os << st << std::endl; return os; } diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h index 3215c8f6..1413ad89 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h @@ -25,6 +25,7 @@ #include #include #include +#include // std::distance #include "gudhi/Off_reader.h" @@ -47,7 +48,7 @@ class Delaunay_triangulation_off_visitor_reader { void init(int dim, int num_vertices, int num_faces, int num_edges) { #ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; #endif // DEBUG_TRACES if (num_faces > 0) { @@ -121,7 +122,7 @@ class Delaunay_triangulation_off_reader { bool is_valid() const { return valid_; } - + private: bool valid_; }; @@ -138,10 +139,19 @@ class Delaunay_triangulation_off_writer { Delaunay_triangulation_off_writer(const std::string & name_file, const Complex& save_complex) { std::ofstream stream(name_file); if (stream.is_open()) { - // OFF header - stream << "OFF" << std::endl; - // no endl on next line - don't know why... - stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; + if (save_complex.current_dimension() == 3) { + // OFF header + stream << "OFF" << std::endl; + // no endl on next line - don't know why... + stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; + } else { + // nOFF header + stream << "nOFF" << std::endl; + // no endl on next line - don't know why... + stream << save_complex.current_dimension() << " " << save_complex.number_of_vertices() << " " << + save_complex.number_of_finite_full_cells() << " 0"; + + } // Points list for (auto vit = save_complex.vertices_begin(); vit != save_complex.vertices_end(); ++vit) { @@ -151,16 +161,36 @@ class Delaunay_triangulation_off_writer { stream << std::endl; } - // Finite cells list - for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.finite_full_cells_end(); ++cit) { - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension + + for (auto cit = save_complex.full_cells_begin(); cit != save_complex.full_cells_end(); ++cit) { + std::vector vertexVector; + stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - auto vertexHdl = *vit; - // auto vertexHdl = std::distance(save_complex.vertices_begin(), *vit) - 1; - // stream << std::distance(save_complex.vertices_begin(), *(vit)) - 1 << " "; + // Vector of vertex construction for simplex_tree structure + // Vertex handle is distance - 1 + //int vertexHdl = std::distance(save_complex.vertices_begin(), *vit); + // infinite cell is -1 for infinite + //vertexVector.push_back(vertexHdl); + // Vector of points for alpha_shapes filtration value computation } stream << std::endl; } + + + + + + /* + // Finite cells list + for (auto cit = save_complex.full_cells_begin(); cit != save_complex.full_cells_end(); ++cit) { + stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + //auto vertexHdl = *vit; + auto vertexHdl = std::distance(save_complex.vertices_begin(), vit) - 1; + // stream << std::distance(save_complex.vertices_begin(), *(vit)) - 1 << " "; + } + stream << std::endl; + }*/ stream.close(); } else { std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << -- cgit v1.2.3 From 844d6205eb6705935417b0ab45b0c71230bd9ed6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 10 Jun 2015 15:00:47 +0000 Subject: alpha shapes computation in progress but not finished git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@608 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d52ab152c6f765721657eaf5cbf07303a6c6c515 --- src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 69 +++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index 6de675f6..841c883a 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -42,6 +42,8 @@ #include #include #include +#include +#include namespace Gudhi { @@ -79,6 +81,8 @@ class Alpha_shapes { /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ typedef std::vector typeVectorVertex; + typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; + // From CGAL /** \brief Kernel for the Delaunay_triangulation. * Dimension can be set dynamically. @@ -126,13 +130,13 @@ class Alpha_shapes { private: template - void init(T& triangulation) { + void initial_init(T& triangulation) { st_.set_dimension(triangulation.maximal_dimension()); Filtration_value filtration_max = 0.0; Kernel k; Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); // triangulation full cells list for (auto cit = triangulation.full_cells_begin(); cit != triangulation.full_cells_end(); ++cit) { @@ -195,8 +199,67 @@ class Alpha_shapes { } template - void recursive_init(T& triangulation, typeVectorVertex vertexVector) { + void init(T& triangulation) { + st_.set_dimension(triangulation.maximal_dimension()); + Filtration_value filtration_max = 0.0; + Filtration_value filtration_unknown = std::numeric_limits::quiet_NaN(); + + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + + std::map points_to_vh; + // Start to insert at handle = 0 - default integer value + Vertex_handle vertex_handle = Vertex_handle(); + // Loop on triangulation vertices list + for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { + points_to_vh[vit->point()] = vertex_handle; + vertex_handle++; + } + + // Loop on triangulation finite full cells list + for (auto cit = triangulation.finite_full_cells_begin(); cit != triangulation.finite_full_cells_end(); ++cit) { + typeVectorVertex vertexVector; + typeVectorPoint pointVector; + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { +#ifdef DEBUG_TRACES + std::cout << "points_to_vh=" << points_to_vh[(*vit)->point()] << std::endl; +#endif // DEBUG_TRACES + // Vector of vertex construction for simplex_tree structure + vertexVector.push_back(points_to_vh[(*vit)->point()]); + // Vector of points for alpha_shapes filtration value computation + pointVector.push_back((*vit)->point()); + } + Filtration_value alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); + // Insert each simplex and its subfaces in the simplex tree - filtration is NaN + std::pair insert_result = st_.insert_simplex_and_subfaces(vertexVector, filtration_unknown); + + if (insert_result.second == true) { + // Only top-level cell must have the correct alpha value + st_.assign_filtration(insert_result.first, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << "alpha_shapes_filtration=" << st_.filtration(insert_result.first) << std::endl; +#endif // DEBUG_TRACES + + filtration_max = fmax(filtration_max, alpha_shapes_filtration); + } + } + // Loop on triangulation finite full cells list + for (auto f_simplex : st_.skeleton_simplex_range(st_.dimension() - 1)) { + std::cout << "vertex = [" << st_.filtration(f_simplex) << "] "; + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; + if (st_.filtration(f_simplex) == filtration_unknown) + st_.assign_filtration(f_simplex, filtration_max); // TODO(VR) Compute filtration value from simplex + } + +#ifdef DEBUG_TRACES + std::cout << "filtration_max=" << filtration_max << std::endl; +#endif // DEBUG_TRACES + st_.set_filtration(filtration_max); } public: -- cgit v1.2.3 From 24ed9e6896b0aafcaeaf19e5d2970915282fa7b7 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 12 Jun 2015 10:47:38 +0000 Subject: delaunay off reader/writer fix. alpha complex algo seems ok. tests are Nok. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@611 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 37cea3b33d783a77a23fa3a54a1bee106508d981 --- .../example/Delaunay_triangulation_off_rw.cpp | 38 +----- src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 109 +++++++++++++-- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 36 ++--- src/Simplex_tree/include/gudhi/Simplex_tree.h | 150 +++++++++++++++++---- src/common/include/gudhi/Off_reader.h | 4 +- 5 files changed, 242 insertions(+), 95 deletions(-) diff --git a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp index 6c9fcdab..fe889ec0 100644 --- a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp +++ b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp @@ -44,12 +44,12 @@ typedef CGAL::Delaunay_triangulation T; // TriangulationDataStructure template parameter void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off dimension" << std::endl; + std::cerr << "Usage: " << progName << " inputFile.off dimension outputFile.off" << std::endl; exit(-1); // ----- >> } int main(int argc, char **argv) { - if (argc != 3) { + if (argc != 4) { std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; usage(argv[0]); } @@ -68,37 +68,11 @@ int main(int argc, char **argv) { std::cerr << "Unable to read file " << offFileName << std::endl; exit(-1); // ----- >> } + + std::cout << "number_of_finite_full_cells= " << dt.number_of_finite_full_cells() << std::endl; - std::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; - std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; - - // Points list - /*for (T::Vertex_iterator vit = dt.vertices_begin(); vit != dt.vertices_end(); ++vit) { - for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { - std::cout << *Coord << " "; - } - std::cout << std::endl; - } - std::cout << std::endl;*/ - - /*int i = 0, j = 0; - typedef T::Full_cell_iterator Full_cell_iterator; - typedef T::Facet Facet; - - for (Full_cell_iterator cit = dt.full_cells_begin(); cit != dt.full_cells_end(); ++cit) { - if (!dt.is_infinite(cit)) { - j++; - continue; - } - Facet fct(cit, cit->index(dt.infinite_vertex())); - i++; - } - std::cout << "There are " << i << " facets on the convex hull." << std::endl; - std::cout << "There are " << j << " facets not on the convex hull." << std::endl; -*/ - - std::string offOutputFile("out.off"); + std::string outFileName(argv[3]); + std::string offOutputFile(outFileName); Gudhi::alphashapes::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); return 0; diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index 841c883a..2bc8b221 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -32,6 +32,9 @@ #include #include +#include // isnan, fmax + +#include #include #include @@ -208,12 +211,14 @@ class Alpha_shapes { Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); - std::map points_to_vh; + // bimap to retrieve vertex handles from points and vice versa + typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; + bimap_points_vh points_to_vh; // Start to insert at handle = 0 - default integer value Vertex_handle vertex_handle = Vertex_handle(); // Loop on triangulation vertices list for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { - points_to_vh[vit->point()] = vertex_handle; + points_to_vh.insert(bimap_points_vh::value_type(vit->point(), vertex_handle)); vertex_handle++; } @@ -223,10 +228,10 @@ class Alpha_shapes { typeVectorPoint pointVector; for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { #ifdef DEBUG_TRACES - std::cout << "points_to_vh=" << points_to_vh[(*vit)->point()] << std::endl; + std::cout << "points_to_vh=" << points_to_vh.left.at((*vit)->point()) << std::endl; #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(points_to_vh[(*vit)->point()]); + vertexVector.push_back(points_to_vh.left.at((*vit)->point())); // Vector of points for alpha_shapes filtration value computation pointVector.push_back((*vit)->point()); } @@ -244,17 +249,99 @@ class Alpha_shapes { filtration_max = fmax(filtration_max, alpha_shapes_filtration); } } - - // Loop on triangulation finite full cells list - for (auto f_simplex : st_.skeleton_simplex_range(st_.dimension() - 1)) { - std::cout << "vertex = [" << st_.filtration(f_simplex) << "] "; + + // ### For i : d -> 0 + for (int decr_dim = st_.dimension(); decr_dim >= 0; decr_dim--) { + // ### Foreach Sigma of dim i + for (auto f_simplex : st_.skeleton_simplex_range(decr_dim)) { + int f_simplex_dim = st_.dimension(f_simplex); +#ifdef DEBUG_TRACES + std::cout << "f_simplex_dim= " << f_simplex_dim << " - decr_dim= " << decr_dim << std::endl; +#endif // DEBUG_TRACES + if (decr_dim == f_simplex_dim) { + typeVectorPoint pointVector; +#ifdef DEBUG_TRACES + std::cout << "vertex "; +#endif // DEBUG_TRACES + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + pointVector.push_back(points_to_vh.right.at(vertex)); +#ifdef DEBUG_TRACES + std::cout << (int) vertex << " "; +#endif // DEBUG_TRACES + } +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES + // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) + if (isnan(st_.filtration(f_simplex))) { + Filtration_value alpha_shapes_filtration = 0.0; + // No need to compute squared_radius on a single point - alpha is 0.0 + if (f_simplex_dim > 0) { + alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); + } + st_.assign_filtration(f_simplex, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << "From NaN to alpha_shapes_filtration=" << st_.filtration(f_simplex) << std::endl; +#endif // DEBUG_TRACES + } + + // ### Foreach Tau face of Sigma + for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { +#ifdef DEBUG_TRACES + std::cout << "Sigma "; + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << " - Tau "; + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + // insert the Tau points in a vector for is_gabriel function + typeVectorPoint pointVector; + Vertex_handle vertexForGabriel = Vertex_handle(); + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + pointVector.push_back(points_to_vh.right.at(vertex)); + } + // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + if (std::find(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertex)) == pointVector.end()) { + // vertex is not found in Tau + vertexForGabriel = vertex; + // No need to continue loop + break; + } + } + // ### If filt(Tau) is not NaN + // ### or Tau is not Gabriel of Sigma + if (!isnan(st_.filtration(f_boundary)) || + !is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) + ) { + // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) + Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); + st_.assign_filtration(f_boundary, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << "From Boundary to alpha_shapes_filtration=" << st_.filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES + } + } + } + } + } + +#ifdef DEBUG_TRACES + std::cout << "The complex contains " << st_.num_simplices() << " simplices" << std::endl; + std::cout << " - dimension " << st_.dimension() << " - filtration " << st_.filtration() << std::endl; + std::cout << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + for (auto f_simplex : st_.filtration_simplex_range()) { + std::cout << " " << "[" << st_.filtration(f_simplex) << "] "; for (auto vertex : st_.simplex_vertex_range(f_simplex)) { std::cout << (int) vertex << " "; } std::cout << std::endl; - if (st_.filtration(f_simplex) == filtration_unknown) - st_.assign_filtration(f_simplex, filtration_max); // TODO(VR) Compute filtration value from simplex } +#endif // DEBUG_TRACES #ifdef DEBUG_TRACES std::cout << "filtration_max=" << filtration_max << std::endl; @@ -286,7 +373,7 @@ class Alpha_shapes { return st_.filtration(); } - friend std::ostream& operator<<(std::ostream& os, const Alpha_shapes& alpha_shape) { + friend std::ostream& operator<<(std::ostream& os, const Alpha_shapes & alpha_shape) { // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor Gudhi::Simplex_tree<> st = alpha_shape.st_; os << st << std::endl; diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h index 1413ad89..a4e5e2fe 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h @@ -25,7 +25,7 @@ #include #include #include -#include // std::distance +#include #include "gudhi/Off_reader.h" @@ -130,6 +130,7 @@ class Delaunay_triangulation_off_reader { template class Delaunay_triangulation_off_writer { public: + typedef typename Complex::Point Point; /** * name_file : file where the off will be written @@ -153,44 +154,29 @@ class Delaunay_triangulation_off_writer { } + // bimap to retrieve vertex handles from points and vice versa + std::map< Point, int > points_to_vh; + // Start to insert at default handle value + int vertex_handle = int(); + // Points list for (auto vit = save_complex.vertices_begin(); vit != save_complex.vertices_end(); ++vit) { for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { stream << *Coord << " "; } stream << std::endl; + points_to_vh[vit->point()] = vertex_handle; + vertex_handle++; } - - for (auto cit = save_complex.full_cells_begin(); cit != save_complex.full_cells_end(); ++cit) { + for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.finite_full_cells_end(); ++cit) { std::vector vertexVector; stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - // Vector of vertex construction for simplex_tree structure - // Vertex handle is distance - 1 - //int vertexHdl = std::distance(save_complex.vertices_begin(), *vit); - // infinite cell is -1 for infinite - //vertexVector.push_back(vertexHdl); - // Vector of points for alpha_shapes filtration value computation + stream << points_to_vh[(*vit)->point()] << " "; } stream << std::endl; } - - - - - - /* - // Finite cells list - for (auto cit = save_complex.full_cells_begin(); cit != save_complex.full_cells_end(); ++cit) { - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; // Dimension - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - //auto vertexHdl = *vit; - auto vertexHdl = std::distance(save_complex.vertices_begin(), vit) - 1; - // stream << std::distance(save_complex.vertices_begin(), *(vit)) - 1 << " "; - } - stream << std::endl; - }*/ stream.close(); } else { std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index b79e3c8f..32fb2f43 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -37,7 +37,6 @@ #include namespace Gudhi { - /** \defgroup simplex_tree Filtered Complexes * * A simplicial complex \f$\mathbf{K}\f$ @@ -84,8 +83,8 @@ namespace Gudhi { * */ template class Simplex_tree { @@ -245,6 +244,7 @@ class Simplex_tree { Filtration_simplex_range filtration_simplex_range() { return filtration_simplex_range(Indexing_tag()); } + /** \brief Returns a range over the vertices of a simplex. * * The order in which the vertices are visited is the decreasing order for < on Vertex_handles, @@ -316,12 +316,14 @@ class Simplex_tree { Simplex_key key(Simplex_handle sh) { return sh->second.key(); } + /** \brief Returns the simplex associated to a key. * * The filtration must be initialized. */ Simplex_handle simplex(Simplex_key key) { return filtration_vect_[key]; } + /** \brief Returns the filtration value of a simplex. * * Called on the null_simplex, returns INFINITY. */ @@ -330,12 +332,23 @@ class Simplex_tree { return sh->second.filtration(); } else { return INFINITY; - } // filtration(); } + } + } + + /** \brief Sets the filtration value of a simplex. + * + * No action if called on the null_simplex*/ + void assign_filtration(Simplex_handle sh, Filtration_value fv) { + if (sh != null_simplex()) { + sh->second.assign_filtration(fv); + } } + /** \brief Returns an upper bound of the filtration values of the simplices. */ Filtration_value filtration() { return threshold_; } + /** \brief Returns a Simplex_handle different from all Simplex_handles * associated to the simplices in the simplicial complex. * @@ -343,20 +356,24 @@ class Simplex_tree { Simplex_handle null_simplex() { return Dictionary_it(NULL); } + /** \brief Returns a key different for all keys associated to the * simplices of the simplicial complex. */ Simplex_key null_key() { return -1; } + /** \brief Returns a Vertex_handle different from all Vertex_handles associated * to the vertices of the simplicial complex. */ Vertex_handle null_vertex() { return null_vertex_; } + /** \brief Returns the number of vertices in the complex. */ size_t num_vertices() { return root_.members_.size(); } + /** \brief Returns the number of simplices in the complex. * * Does not count the empty simplex. */ @@ -376,6 +393,7 @@ class Simplex_tree { } return dim - 1; } + /** \brief Returns an upper bound on the dimension of the simplicial complex. */ int dimension() { return dimension_; @@ -423,7 +441,6 @@ class Simplex_tree { Simplex_handle find_vertex(Vertex_handle v) { return root_.members_.begin() + v; } -//{ return root_.members_.find(v); } /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. * @@ -479,7 +496,6 @@ class Simplex_tree { return res_insert; } - /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of * Vertex_handles, in the simplicial complex. * @@ -487,33 +503,35 @@ class Simplex_tree { * @param[in] filtration the filtration value assigned to the new N-simplex. */ template - void insert_simplex_and_subfaces(RandomAccessVertexRange& Nsimplex, - Filtration_value filtration = 0.0) { + std::pair insert_simplex_and_subfaces(RandomAccessVertexRange& Nsimplex, + Filtration_value filtration = 0.0) { + std::pair returned; if (Nsimplex.size() > 1) { for (unsigned int NIndex = 0; NIndex < Nsimplex.size(); NIndex++) { // insert N (N-1)-Simplex RandomAccessVertexRange NsimplexMinusOne; for (unsigned int NListIter = 0; NListIter < Nsimplex.size() - 1; NListIter++) { // (N-1)-Simplex creation - NsimplexMinusOne.push_back( Nsimplex[(NIndex + NListIter) % Nsimplex.size()]); + NsimplexMinusOne.push_back(Nsimplex[(NIndex + NListIter) % Nsimplex.size()]); } // (N-1)-Simplex recursive call - insert_simplex_and_subfaces(NsimplexMinusOne, filtration); + returned = insert_simplex_and_subfaces(NsimplexMinusOne, filtration); } // N-Simplex insert - std::pair returned = insert_simplex(Nsimplex, filtration); + returned = insert_simplex(Nsimplex, filtration); if (returned.second == true) { num_simplices_++; } } else if (Nsimplex.size() == 1) { // 1-Simplex insert - End of recursivity - std::pair returned = insert_simplex(Nsimplex, filtration); + returned = insert_simplex(Nsimplex, filtration); if (returned.second == true) { num_simplices_++; } } else { // Nothing to insert - empty vector } + return returned; } /** \brief Assign a value 'key' to the key of the simplex @@ -540,17 +558,6 @@ class Simplex_tree { return sh->second.children(); } -// void display_simplex(Simplex_handle sh) -// { -// std::cout << " " << "[" << filtration(sh) << "] "; -// for( auto vertex : simplex_vertex_range(sh) ) -// { std::cout << vertex << " "; } -// } - - // void print(Simplex_handle sh, std::ostream& os = std::cout) - // { for(auto v : simplex_vertex_range(sh)) {os << v << " ";} - // os << std::endl; } - public: /** Returns a pointer to the root nodes of the simplex tree. */ Siblings * root() { @@ -562,10 +569,12 @@ class Simplex_tree { void set_filtration(Filtration_value fil) { threshold_ = fil; } + /** Set a number of simplices for the simplicial complex. */ void set_num_simplices(const unsigned int& num_simplices) { num_simplices_ = num_simplices; } + /** Set a dimension for the simplicial complex. */ void set_dimension(int dimension) { dimension_ = dimension; @@ -623,6 +632,7 @@ class Simplex_tree { } return ((it1 == rg1.end()) && (it2 != rg2.end())); } + /** \brief StrictWeakOrdering, for the simplices, defined by the filtration. * * It corresponds to the partial order @@ -631,8 +641,7 @@ class Simplex_tree { * to be smaller. The filtration function must be monotonic. */ struct is_before_in_filtration { explicit is_before_in_filtration(Simplex_tree * st) - : st_(st) { - } + : st_(st) { } bool operator()(const Simplex_handle sh1, const Simplex_handle sh2) const { if (st_->filtration(sh1) != st_->filtration(sh2)) { @@ -708,6 +717,7 @@ class Simplex_tree { } } } + /** \brief Expands the Simplex_tree containing only its one skeleton * until dimension max_dim. * @@ -731,6 +741,7 @@ class Simplex_tree { } private: + /** \brief Recursive expansion of the simplex tree.*/ void siblings_expansion(Siblings * siblings, // must contain elements int k) { @@ -769,6 +780,7 @@ class Simplex_tree { } } } + /** \brief Intersects Dictionary 1 [begin1;end1) with Dictionary 2 [begin2,end2) * and assigns the maximal possible Filtration_value to the Nodes. */ void intersection(std::vector >& intersection, @@ -800,6 +812,7 @@ class Simplex_tree { } } } + /** Maximum over 3 values.*/ Filtration_value maximum(Filtration_value a, Filtration_value b, Filtration_value c) { @@ -824,6 +837,92 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } + //---------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------- + private: + + /** Recursive search of cofaces + */ + template + void rec_coface(RandomAccessVertexRange &vertices, Siblings *curr_sib, Dictionary *curr_res, std::vector& cofaces, unsigned int length, unsigned long codimension) { + for (auto sib = curr_sib->members().begin(); sib != curr_sib->members().end() && (vertices.empty() || sib->first <= vertices[vertices.size() - 1]); ++sib) { + bool continueRecursion = (codimension == length || curr_res->size() <= codimension); // dimension of actual simplex <= codimension + if (vertices.empty()) { + if (curr_res->size() >= length && continueRecursion) + // If we reached the end of the vertices, and the simplex has more vertices than the given simplex, we found a coface + { + curr_res->emplace(sib->first, sib->second); + bool egalDim = (codimension == length || curr_res->size() == codimension); // dimension of actual simplex == codimension + if (egalDim) + cofaces.push_back(*curr_res); + if (has_children(sib)) + rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); + curr_res->erase(curr_res->end() - 1); + } + } else if (continueRecursion) { + if (sib->first == vertices[vertices.size() - 1]) // If curr_sib matches with the top vertex + { + curr_res->emplace(sib->first, sib->second); + bool egalDim = (codimension == length || curr_res->size() == codimension); // dimension of actual simplex == codimension + if (vertices.size() == 1 && curr_res->size() > length && egalDim) + cofaces.push_back(*curr_res); + if (has_children(sib)) { // Rec call + Vertex_handle tmp = vertices[vertices.size() - 1]; + vertices.pop_back(); + rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); + vertices.push_back(tmp); + } + curr_res->erase(curr_res->end() - 1); + } else // (sib->first < vertices[vertices.size()-1]) + { + if (has_children(sib)) { + curr_res->emplace(sib->first, sib->second); + rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); + curr_res->erase(curr_res->end() - 1); + } + } + } + } + } + + public: + + /** \brief Compute the cofaces of a n simplex + * \param vertices List of vertices which represent the n simplex. + * \param codimension The function returns the n+codimension-simplices. If codimension = 0, return all cofaces + * \return Vector of Dictionary, empty vector if no cofaces found. + * \warning n+codimension must be lower than Simplex_tree dimension, otherwise an an empty vector is returned. + */ + + template + std::vector coface(const RandomAccessVertexRange &vertices, int codimension) { + RandomAccessVertexRange copy = vertices; + std::vector cofaces; + std::sort(copy.begin(), copy.end(), std::greater()); // must be sorted in decreasing order + if (root_.members().empty()) { + std::cerr << "Simplex_tree::coface - empty Simplex_tree" << std::endl; + return cofaces; // ----->> + } + if (vertices.empty()) { + std::cerr << "Simplex_tree::coface - empty vertices list" << std::endl; + return cofaces; // ----->> + } + if (codimension < 0) { + std::cerr << "Simplex_tree::coface - codimension is empty" << std::endl; + return cofaces; // ----->> + } + if (codimension + vertices.size() >= (unsigned long) dimension_) { + std::cerr << "Simplex_tree::coface - codimension + vertices list size cannot be greater than Simplex_tree dimension" << std::endl; + return cofaces; // ----->> + } + std::sort(copy.begin(), copy.end(), std::greater()); // must be sorted in decreasing order + Dictionary res; + rec_coface(copy, &root_, &res, cofaces, vertices.size(), codimension + vertices.size()); + return cofaces; + } + + //---------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------- private: Vertex_handle null_vertex_; @@ -851,6 +950,7 @@ std::ostream& operator<<(std::ostream & os, Simplex_tree & st) { } return os; } + template std::istream& operator>>(std::istream & is, Simplex_tree & st) { // assert(st.num_simplices() == 0); diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index e29218d8..618d1b4d 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -7,7 +7,7 @@ * * Author(s): David Salinas * - * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France) + * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -121,7 +121,7 @@ private: if(!goto_next_uncomment_line(line)) return false; std::istringstream iss(line); - if(is_off_file){ + if((is_off_file) && (!is_noff_file)) { off_info_.dim = 3; if(!(iss >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)){ std::cerr << "incorrect number of vertices/faces/edges\n"; -- cgit v1.2.3 From 853eb92146a6d473337fed8ef57f77bee8efd356 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 15 Jun 2015 09:28:06 +0000 Subject: 1st version of alpha complex - compilation and tests are OK git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@613 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4bcf44466cce7d3dfd62e2e8a74b8c3e1f4808dd --- src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 159 +++++++------------------- 1 file changed, 41 insertions(+), 118 deletions(-) diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h index 2bc8b221..f23df51a 100644 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,7 @@ class Alpha_shapes { typedef std::vector typeVectorVertex; typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; + typedef typename std::pair Simplex_result; // From CGAL /** \brief Kernel for the Delaunay_triangulation. @@ -132,85 +134,11 @@ class Alpha_shapes { private: - template - void initial_init(T& triangulation) { - st_.set_dimension(triangulation.maximal_dimension()); - Filtration_value filtration_max = 0.0; - - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); - - // triangulation full cells list - for (auto cit = triangulation.full_cells_begin(); cit != triangulation.full_cells_end(); ++cit) { - typeVectorVertex vertexVector; - typeVectorPoint pointVector; - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - if (!triangulation.is_infinite(*vit)) { - // Vector of vertex construction for simplex_tree structure - // Vertex handle is distance - 1 - Vertex_handle vertexHdl = std::distance(triangulation.vertices_begin(), *vit) - 1; - // infinite cell is -1 for infinite - vertexVector.push_back(vertexHdl); - // Vector of points for alpha_shapes filtration value computation - pointVector.push_back((*vit)->point()); -#ifdef DEBUG_TRACES - /*std::cout << "Point "; - for (auto Coord = (*vit)->point().cartesian_begin(); Coord != (*vit)->point().cartesian_end(); ++Coord) { - std::cout << *Coord << " | "; - } - std::cout << std::endl;*/ -#endif // DEBUG_TRACES - } - } - Filtration_value alpha_shapes_filtration = 0.0; - - if (!triangulation.is_infinite(cit)) { - alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); -#ifdef DEBUG_TRACES - //std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; -#endif // DEBUG_TRACES - } else { - Filtration_value tmp_filtration = 0.0; - bool is_gab = true; - /*for (auto vit = triangulation.finite_vertices_begin(); vit != triangulation.finite_vertices_end(); ++vit) { - if (CGAL::ON_UNBOUNDED_SIDE != is_gabriel(pointVector.begin(), pointVector.end(), vit->point())) { - is_gab = false; - // TODO(VR) : Compute minimum - - } - }*/ - if (true == is_gab) { - alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); -#ifdef DEBUG_TRACES - //std::cout << "Alpha_shape filtration value = " << alpha_shapes_filtration << std::endl; -#endif // DEBUG_TRACES - } - } - // Insert each point in the simplex tree - st_.insert_simplex_and_subfaces(vertexVector, alpha_shapes_filtration); - -#ifdef DEBUG_TRACES - std::cout << "C" << std::distance(triangulation.full_cells_begin(), cit) << ":"; - for (auto value : vertexVector) { - std::cout << value << ' '; - } - std::cout << " | alpha=" << alpha_shapes_filtration << std::endl; -#endif // DEBUG_TRACES - } - st_.set_filtration(filtration_max); - } - template void init(T& triangulation) { st_.set_dimension(triangulation.maximal_dimension()); - Filtration_value filtration_max = 0.0; - Filtration_value filtration_unknown = std::numeric_limits::quiet_NaN(); - - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + // -------------------------------------------------------------------------------------------- // bimap to retrieve vertex handles from points and vice versa typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; bimap_points_vh points_to_vh; @@ -221,52 +149,54 @@ class Alpha_shapes { points_to_vh.insert(bimap_points_vh::value_type(vit->point(), vertex_handle)); vertex_handle++; } + // -------------------------------------------------------------------------------------------- - // Loop on triangulation finite full cells list + // -------------------------------------------------------------------------------------------- + // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation.finite_full_cells_begin(); cit != triangulation.finite_full_cells_end(); ++cit) { typeVectorVertex vertexVector; - typeVectorPoint pointVector; +#ifdef DEBUG_TRACES + std::cout << "Simplex_tree insertion "; +#endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { #ifdef DEBUG_TRACES - std::cout << "points_to_vh=" << points_to_vh.left.at((*vit)->point()) << std::endl; + std::cout << " " << points_to_vh.left.at((*vit)->point()); #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure vertexVector.push_back(points_to_vh.left.at((*vit)->point())); - // Vector of points for alpha_shapes filtration value computation - pointVector.push_back((*vit)->point()); } - Filtration_value alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); - // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - std::pair insert_result = st_.insert_simplex_and_subfaces(vertexVector, filtration_unknown); - - if (insert_result.second == true) { - // Only top-level cell must have the correct alpha value - st_.assign_filtration(insert_result.first, alpha_shapes_filtration); #ifdef DEBUG_TRACES - std::cout << "alpha_shapes_filtration=" << st_.filtration(insert_result.first) << std::endl; + std::cout << std::endl; #endif // DEBUG_TRACES - - filtration_max = fmax(filtration_max, alpha_shapes_filtration); + // Insert each simplex and its subfaces in the simplex tree - filtration is NaN + Simplex_result insert_result = st_.insert_simplex_and_subfaces(vertexVector, + std::numeric_limits::quiet_NaN()); + if (!insert_result.second) { + std::cerr << "Alpha_shapes::init insert_simplex_and_subfaces failed" << std::endl; } } + // -------------------------------------------------------------------------------------------- + + Filtration_value filtration_max = 0.0; + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + // -------------------------------------------------------------------------------------------- // ### For i : d -> 0 for (int decr_dim = st_.dimension(); decr_dim >= 0; decr_dim--) { // ### Foreach Sigma of dim i for (auto f_simplex : st_.skeleton_simplex_range(decr_dim)) { int f_simplex_dim = st_.dimension(f_simplex); -#ifdef DEBUG_TRACES - std::cout << "f_simplex_dim= " << f_simplex_dim << " - decr_dim= " << decr_dim << std::endl; -#endif // DEBUG_TRACES if (decr_dim == f_simplex_dim) { typeVectorPoint pointVector; #ifdef DEBUG_TRACES - std::cout << "vertex "; + std::cout << "Sigma of dim " << decr_dim << " is"; #endif // DEBUG_TRACES for (auto vertex : st_.simplex_vertex_range(f_simplex)) { pointVector.push_back(points_to_vh.right.at(vertex)); #ifdef DEBUG_TRACES - std::cout << (int) vertex << " "; + std::cout << " " << vertex; #endif // DEBUG_TRACES } #ifdef DEBUG_TRACES @@ -280,23 +210,21 @@ class Alpha_shapes { alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); } st_.assign_filtration(f_simplex, alpha_shapes_filtration); + filtration_max = fmax(filtration_max, alpha_shapes_filtration); #ifdef DEBUG_TRACES - std::cout << "From NaN to alpha_shapes_filtration=" << st_.filtration(f_simplex) << std::endl; + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; #endif // DEBUG_TRACES } // ### Foreach Tau face of Sigma for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { #ifdef DEBUG_TRACES - std::cout << "Sigma "; - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { - std::cout << (int) vertex << " "; - } - std::cout << " - Tau "; + std::cout << " | --------------------------------------------------" << std::endl; + std::cout << " | Tau "; for (auto vertex : st_.simplex_vertex_range(f_boundary)) { - std::cout << (int) vertex << " "; + std::cout << vertex << " "; } - std::cout << std::endl; + std::cout << "is a face of Sigma" << std::endl; #endif // DEBUG_TRACES // insert the Tau points in a vector for is_gabriel function typeVectorPoint pointVector; @@ -313,35 +241,30 @@ class Alpha_shapes { break; } } +#ifdef DEBUG_TRACES + std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) + != CGAL::ON_BOUNDED_SIDE; + std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; +#endif // DEBUG_TRACES // ### If filt(Tau) is not NaN // ### or Tau is not Gabriel of Sigma if (!isnan(st_.filtration(f_boundary)) || - !is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) + (is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) == CGAL::ON_BOUNDED_SIDE) ) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); st_.assign_filtration(f_boundary, alpha_shapes_filtration); + filtration_max = fmax(filtration_max, alpha_shapes_filtration); #ifdef DEBUG_TRACES - std::cout << "From Boundary to alpha_shapes_filtration=" << st_.filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; #endif // DEBUG_TRACES } } } } } - -#ifdef DEBUG_TRACES - std::cout << "The complex contains " << st_.num_simplices() << " simplices" << std::endl; - std::cout << " - dimension " << st_.dimension() << " - filtration " << st_.filtration() << std::endl; - std::cout << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; - for (auto f_simplex : st_.filtration_simplex_range()) { - std::cout << " " << "[" << st_.filtration(f_simplex) << "] "; - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { - std::cout << (int) vertex << " "; - } - std::cout << std::endl; - } -#endif // DEBUG_TRACES + // -------------------------------------------------------------------------------------------- #ifdef DEBUG_TRACES std::cout << "filtration_max=" << filtration_max << std::endl; -- cgit v1.2.3 From 17fd245908ba07d6bad974efa0be1ec6093262ec Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 15 Jun 2015 09:31:02 +0000 Subject: Alpha_shapes renamed Alpha_complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@614 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ede5d1c1175f9d314e23bc0b76f7376b3de90c93 --- src/Alpha_complex/example/CMakeLists.txt | 31 ++ .../example/Delaunay_triangulation_off_rw.cpp | 79 ++++++ .../Simplex_tree_from_delaunay_triangulation.cpp | 77 +++++ src/Alpha_complex/example/alphashapedoc.off | 10 + src/Alpha_complex/include/gudhi/Alpha_shapes.h | 311 +++++++++++++++++++++ .../Alpha_shapes/Delaunay_triangulation_off_io.h | 192 +++++++++++++ src/Alpha_complex/test/Alpha_shapes_unit_test.cpp | 126 +++++++++ src/Alpha_complex/test/CMakeLists.txt | 31 ++ src/Alpha_complex/test/README | 12 + src/Alpha_complex/test/S4_100.off | 102 +++++++ src/Alpha_complex/test/S8_10.off | 12 + src/Alpha_shapes/example/CMakeLists.txt | 31 -- .../example/Delaunay_triangulation_off_rw.cpp | 79 ------ .../Simplex_tree_from_delaunay_triangulation.cpp | 77 ----- src/Alpha_shapes/example/alphashapedoc.off | 10 - src/Alpha_shapes/include/gudhi/Alpha_shapes.h | 311 --------------------- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 192 ------------- src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp | 126 --------- src/Alpha_shapes/test/CMakeLists.txt | 31 -- src/Alpha_shapes/test/README | 12 - src/Alpha_shapes/test/S4_100.off | 102 ------- src/Alpha_shapes/test/S8_10.off | 12 - 22 files changed, 983 insertions(+), 983 deletions(-) create mode 100644 src/Alpha_complex/example/CMakeLists.txt create mode 100644 src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp create mode 100644 src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp create mode 100755 src/Alpha_complex/example/alphashapedoc.off create mode 100644 src/Alpha_complex/include/gudhi/Alpha_shapes.h create mode 100644 src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h create mode 100644 src/Alpha_complex/test/Alpha_shapes_unit_test.cpp create mode 100644 src/Alpha_complex/test/CMakeLists.txt create mode 100644 src/Alpha_complex/test/README create mode 100644 src/Alpha_complex/test/S4_100.off create mode 100644 src/Alpha_complex/test/S8_10.off delete mode 100644 src/Alpha_shapes/example/CMakeLists.txt delete mode 100644 src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp delete mode 100644 src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp delete mode 100755 src/Alpha_shapes/example/alphashapedoc.off delete mode 100644 src/Alpha_shapes/include/gudhi/Alpha_shapes.h delete mode 100644 src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h delete mode 100644 src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp delete mode 100644 src/Alpha_shapes/test/CMakeLists.txt delete mode 100644 src/Alpha_shapes/test/README delete mode 100644 src/Alpha_shapes/test/S4_100.off delete mode 100644 src/Alpha_shapes/test/S8_10.off diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt new file mode 100644 index 00000000..582a9322 --- /dev/null +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIAlphaShapesExample) + +# need CGAL 4.7 +# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + + add_definitions(-DDEBUG_TRACES) + + add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) + target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(dtoffrw_tore3D ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off 3) + + add_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) + target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () +endif() diff --git a/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp new file mode 100644 index 00000000..fe889ec0 --- /dev/null +++ b/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp @@ -0,0 +1,79 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2014 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; +typedef CGAL::Delaunay_triangulation T; +// The triangulation uses the default instanciation of the +// TriangulationDataStructure template parameter + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " inputFile.off dimension outputFile.off" << std::endl; + exit(-1); // ----- >> +} + +int main(int argc, char **argv) { + if (argc != 4) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + int dimension = 0; + int returnedScanValue = sscanf(argv[2], "%d", &dimension); + if ((returnedScanValue == EOF) || (dimension <= 0)) { + std::cerr << "Error: " << argv[2] << " is not correct" << std::endl; + usage(argv[0]); + } + + T dt(dimension); + std::string offFileName(argv[1]); + Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(offFileName, dt); + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << offFileName << std::endl; + exit(-1); // ----- >> + } + + std::cout << "number_of_finite_full_cells= " << dt.number_of_finite_full_cells() << std::endl; + + std::string outFileName(argv[3]); + std::string offOutputFile(outFileName); + Gudhi::alphashapes::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); + + return 0; +} \ No newline at end of file diff --git a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp new file mode 100644 index 00000000..0a24fb56 --- /dev/null +++ b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -0,0 +1,77 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2014 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_shapes.h" + +// to construct a simplex_tree from Delaunay_triangulation +#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Simplex_tree.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; +typedef CGAL::Delaunay_triangulation T; +// The triangulation uses the default instanciation of the +// TriangulationDataStructure template parameter + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " filename.off" << std::endl; + exit(-1); // ----- >> +} + +int main(int argc, char **argv) { + if (argc != 2) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + std::string off_file_name(argv[1]); + + // ---------------------------------------------------------------------------- + // + // Init of an alpha-shape from a OFF file + // + // ---------------------------------------------------------------------------- + Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); + + std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; + std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; + std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; + std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; + //std::cout << alpha_shapes_from_file << std::endl; + + return 0; +} \ No newline at end of file diff --git a/src/Alpha_complex/example/alphashapedoc.off b/src/Alpha_complex/example/alphashapedoc.off new file mode 100755 index 00000000..bb790193 --- /dev/null +++ b/src/Alpha_complex/example/alphashapedoc.off @@ -0,0 +1,10 @@ +nOFF +2 7 0 0 +1.0 1.0 +7.0 0.0 +4.0 6.0 +9.0 6.0 +0.0 14.0 +2.0 19.0 +9.0 17.0 + diff --git a/src/Alpha_complex/include/gudhi/Alpha_shapes.h b/src/Alpha_complex/include/gudhi/Alpha_shapes.h new file mode 100644 index 00000000..f23df51a --- /dev/null +++ b/src/Alpha_complex/include/gudhi/Alpha_shapes.h @@ -0,0 +1,311 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ +#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ + +// to construct a Delaunay_triangulation from a OFF file +#include + +// to construct a simplex_tree from Delaunay_triangulation +#include +#include + +#include +#include +#include // isnan, fmax + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Gudhi { + +namespace alphashapes { + +#define Kinit(f) =k.f() + +/** \defgroup alpha_shapes Alpha shapes in dimension N + * +
Implementations:
+ Alpha shapes in dimension N are a subset of Delaunay Triangulation in dimension N. + + + * \author Vincent Rouvreau + * \version 1.0 + * \date 2015 + * \copyright GNU General Public License v3. + * @{ + */ + +/** + * \brief Alpha shapes data structure. + * + * \details Every simplex \f$[v_0, \cdots ,v_d]\f$ admits a canonical orientation + * induced by the order relation on vertices \f$ v_0 < \cdots < v_d \f$. + * + * Details may be found in \cite boissonnatmariasimplextreealgorithmica. + * + * \implements FilteredComplex + * + */ +class Alpha_shapes { + private: + // From Simplex_tree + /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + typedef std::vector typeVectorVertex; + + typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; + typedef typename std::pair Simplex_result; + + // From CGAL + /** \brief Kernel for the Delaunay_triangulation. + * Dimension can be set dynamically. + */ + typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + /** \brief Delaunay_triangulation type required to create an alpha-shape. + */ + typedef CGAL::Delaunay_triangulation Delaunay_triangulation; + + typedef typename Kernel::Compute_squared_radius_d Squared_Radius; + typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; + + /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + typedef std::vector typeVectorPoint; + + private: + /** \brief Upper bound on the simplex tree of the simplicial complex.*/ + Gudhi::Simplex_tree<> st_; + + public: + + Alpha_shapes(std::string& off_file_name) { + // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function + Delaunay_triangulation dt(2); + Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << off_file_name << std::endl; + exit(-1); // ----- >> + } +#ifdef DEBUG_TRACES + std::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; + std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; + std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; +#endif // DEBUG_TRACES + init(dt); + } + + template + Alpha_shapes(T& triangulation) { + init(triangulation); + } + + ~Alpha_shapes() { } + + private: + + template + void init(T& triangulation) { + st_.set_dimension(triangulation.maximal_dimension()); + + // -------------------------------------------------------------------------------------------- + // bimap to retrieve vertex handles from points and vice versa + typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; + bimap_points_vh points_to_vh; + // Start to insert at handle = 0 - default integer value + Vertex_handle vertex_handle = Vertex_handle(); + // Loop on triangulation vertices list + for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { + points_to_vh.insert(bimap_points_vh::value_type(vit->point(), vertex_handle)); + vertex_handle++; + } + // -------------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------------- + // Simplex_tree construction from loop on triangulation finite full cells list + for (auto cit = triangulation.finite_full_cells_begin(); cit != triangulation.finite_full_cells_end(); ++cit) { + typeVectorVertex vertexVector; +#ifdef DEBUG_TRACES + std::cout << "Simplex_tree insertion "; +#endif // DEBUG_TRACES + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { +#ifdef DEBUG_TRACES + std::cout << " " << points_to_vh.left.at((*vit)->point()); +#endif // DEBUG_TRACES + // Vector of vertex construction for simplex_tree structure + vertexVector.push_back(points_to_vh.left.at((*vit)->point())); + } +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES + // Insert each simplex and its subfaces in the simplex tree - filtration is NaN + Simplex_result insert_result = st_.insert_simplex_and_subfaces(vertexVector, + std::numeric_limits::quiet_NaN()); + if (!insert_result.second) { + std::cerr << "Alpha_shapes::init insert_simplex_and_subfaces failed" << std::endl; + } + } + // -------------------------------------------------------------------------------------------- + + Filtration_value filtration_max = 0.0; + + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + // -------------------------------------------------------------------------------------------- + // ### For i : d -> 0 + for (int decr_dim = st_.dimension(); decr_dim >= 0; decr_dim--) { + // ### Foreach Sigma of dim i + for (auto f_simplex : st_.skeleton_simplex_range(decr_dim)) { + int f_simplex_dim = st_.dimension(f_simplex); + if (decr_dim == f_simplex_dim) { + typeVectorPoint pointVector; +#ifdef DEBUG_TRACES + std::cout << "Sigma of dim " << decr_dim << " is"; +#endif // DEBUG_TRACES + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + pointVector.push_back(points_to_vh.right.at(vertex)); +#ifdef DEBUG_TRACES + std::cout << " " << vertex; +#endif // DEBUG_TRACES + } +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES + // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) + if (isnan(st_.filtration(f_simplex))) { + Filtration_value alpha_shapes_filtration = 0.0; + // No need to compute squared_radius on a single point - alpha is 0.0 + if (f_simplex_dim > 0) { + alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); + } + st_.assign_filtration(f_simplex, alpha_shapes_filtration); + filtration_max = fmax(filtration_max, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; +#endif // DEBUG_TRACES + } + + // ### Foreach Tau face of Sigma + for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { +#ifdef DEBUG_TRACES + std::cout << " | --------------------------------------------------" << std::endl; + std::cout << " | Tau "; + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + std::cout << vertex << " "; + } + std::cout << "is a face of Sigma" << std::endl; +#endif // DEBUG_TRACES + // insert the Tau points in a vector for is_gabriel function + typeVectorPoint pointVector; + Vertex_handle vertexForGabriel = Vertex_handle(); + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + pointVector.push_back(points_to_vh.right.at(vertex)); + } + // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + if (std::find(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertex)) == pointVector.end()) { + // vertex is not found in Tau + vertexForGabriel = vertex; + // No need to continue loop + break; + } + } +#ifdef DEBUG_TRACES + std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) + != CGAL::ON_BOUNDED_SIDE; + std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; +#endif // DEBUG_TRACES + // ### If filt(Tau) is not NaN + // ### or Tau is not Gabriel of Sigma + if (!isnan(st_.filtration(f_boundary)) || + (is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) == CGAL::ON_BOUNDED_SIDE) + ) { + // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) + Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); + st_.assign_filtration(f_boundary, alpha_shapes_filtration); + filtration_max = fmax(filtration_max, alpha_shapes_filtration); +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES + } + } + } + } + } + // -------------------------------------------------------------------------------------------- + +#ifdef DEBUG_TRACES + std::cout << "filtration_max=" << filtration_max << std::endl; +#endif // DEBUG_TRACES + st_.set_filtration(filtration_max); + } + + public: + + /** \brief Returns the number of vertices in the complex. */ + size_t num_vertices() { + return st_.num_vertices(); + } + + /** \brief Returns the number of simplices in the complex. + * + * Does not count the empty simplex. */ + const unsigned int& num_simplices() const { + return st_.num_simplices(); + } + + /** \brief Returns an upper bound on the dimension of the simplicial complex. */ + int dimension() { + return st_.dimension(); + } + + /** \brief Returns an upper bound of the filtration values of the simplices. */ + Filtration_value filtration() { + return st_.filtration(); + } + + friend std::ostream& operator<<(std::ostream& os, const Alpha_shapes & alpha_shape) { + // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor + Gudhi::Simplex_tree<> st = alpha_shape.st_; + os << st << std::endl; + return os; + } +}; + +} // namespace alphashapes + +} // namespace Gudhi + +#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ diff --git a/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h new file mode 100644 index 00000000..a4e5e2fe --- /dev/null +++ b/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h @@ -0,0 +1,192 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ +#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ + +#include +#include +#include +#include + +#include "gudhi/Off_reader.h" + +namespace Gudhi { + +namespace alphashapes { + +/** + *@brief Off reader visitor with flag that can be passed to Off_reader to read a Delaunay_triangulation_complex. + */ +template +class Delaunay_triangulation_off_visitor_reader { + Complex& complex_; + typedef typename Complex::Point Point; + + public: + + explicit Delaunay_triangulation_off_visitor_reader(Complex& complex) : + complex_(complex) { } + + void init(int dim, int num_vertices, int num_faces, int num_edges) { +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; +#endif // DEBUG_TRACES + if (num_faces > 0) { + std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << + "file for Delaunay triangulation - faces are computed." << std::endl; + } + if (num_edges > 0) { + std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << + "file for Delaunay triangulation - edges are computed." << std::endl; + } + //complex_.set_current_dimension(dim); + } + + void point(const std::vector& point) { +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::point "; + for (auto coordinate : point) { + std::cout << coordinate << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + complex_.insert(Point(point.size(), point.begin(), point.end())); + } + + void maximal_face(const std::vector& face) { + // For Delaunay Triangulation, only points are read +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::face "; + for (auto vertex : face) { + std::cout << vertex << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + } + + void done() { +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::done" << std::endl; +#endif // DEBUG_TRACES + } +}; + +/** + *@brief Class that allows to load a Delaunay_triangulation_complex from an off file. + */ +template +class Delaunay_triangulation_off_reader { + public: + + /** + * name_file : file to read + * read_complex : complex that will receive the file content + * read_only_points : specify true if only the points must be read + */ + Delaunay_triangulation_off_reader(const std::string & name_file, Complex& read_complex) : valid_(false) { + std::ifstream stream(name_file); + if (stream.is_open()) { + Delaunay_triangulation_off_visitor_reader off_visitor(read_complex); + Off_reader off_reader(stream); + valid_ = off_reader.read(off_visitor); + } else { + std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << + name_file << std::endl; + } + + } + + /** + * return true if reading did not meet problems. + */ + bool is_valid() const { + return valid_; + } + + private: + bool valid_; +}; + +template +class Delaunay_triangulation_off_writer { + public: + typedef typename Complex::Point Point; + + /** + * name_file : file where the off will be written + * save_complex : complex that be outputted in the file + * for now only save triangles. + */ + Delaunay_triangulation_off_writer(const std::string & name_file, const Complex& save_complex) { + std::ofstream stream(name_file); + if (stream.is_open()) { + if (save_complex.current_dimension() == 3) { + // OFF header + stream << "OFF" << std::endl; + // no endl on next line - don't know why... + stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; + } else { + // nOFF header + stream << "nOFF" << std::endl; + // no endl on next line - don't know why... + stream << save_complex.current_dimension() << " " << save_complex.number_of_vertices() << " " << + save_complex.number_of_finite_full_cells() << " 0"; + + } + + // bimap to retrieve vertex handles from points and vice versa + std::map< Point, int > points_to_vh; + // Start to insert at default handle value + int vertex_handle = int(); + + // Points list + for (auto vit = save_complex.vertices_begin(); vit != save_complex.vertices_end(); ++vit) { + for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { + stream << *Coord << " "; + } + stream << std::endl; + points_to_vh[vit->point()] = vertex_handle; + vertex_handle++; + } + + for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.finite_full_cells_end(); ++cit) { + std::vector vertexVector; + stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + stream << points_to_vh[(*vit)->point()] << " "; + } + stream << std::endl; + } + stream.close(); + } else { + std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << + name_file << std::endl; + } + } +}; + +} // namespace alphashapes + +} // namespace Gudhi + +#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp b/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp new file mode 100644 index 00000000..d5db3bfa --- /dev/null +++ b/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp @@ -0,0 +1,126 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define BOOST_TEST_MODULE alpha_shapes +#include +#include +#include +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_shapes.h" + +// to construct a simplex_tree from Delaunay_triangulation +#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Simplex_tree.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; +typedef CGAL::Delaunay_triangulation T; +// The triangulation uses the default instanciation of the +// TriangulationDataStructure template parameter + +BOOST_AUTO_TEST_CASE( OFF_file ) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-shape from a OFF file + // + // ---------------------------------------------------------------------------- + std::string off_file_name("S4_100.off"); + std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + + Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name, 4); + + const int DIMENSION = 4; + std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; + BOOST_CHECK(alpha_shapes_from_file.dimension() == DIMENSION); + + const double FILTRATION = 0.0; + std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; + BOOST_CHECK(alpha_shapes_from_file.filtration() == FILTRATION); + + const int NUMBER_OF_VERTICES = 100; + std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_shapes_from_file.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 6779; + std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; + BOOST_CHECK(alpha_shapes_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + +} + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-shape from a Delauny triangulation + // + // ---------------------------------------------------------------------------- + T dt(8); + std::string off_file_name("S8_10.off"); + std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + + Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); + std::cout << "off_reader.is_valid()=" << off_reader.is_valid() << std::endl; + BOOST_CHECK(off_reader.is_valid()); + + const int NUMBER_OF_VERTICES = 10; + std::cout << "dt.number_of_vertices()=" << dt.number_of_vertices() << std::endl; + BOOST_CHECK(dt.number_of_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_FULL_CELLS = 30; + std::cout << "dt.number_of_full_cells()=" << dt.number_of_full_cells() << std::endl; + BOOST_CHECK(dt.number_of_full_cells() == NUMBER_OF_FULL_CELLS); + + const int NUMBER_OF_FINITE_FULL_CELLS = 6; + std::cout << "dt.number_of_finite_full_cells()=" << dt.number_of_finite_full_cells() << std::endl; + BOOST_CHECK(dt.number_of_finite_full_cells() == NUMBER_OF_FINITE_FULL_CELLS); + + Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_dt(dt); + + const int DIMENSION = 8; + std::cout << "alpha_shapes_from_dt.dimension()=" << alpha_shapes_from_dt.dimension() << std::endl; + BOOST_CHECK(alpha_shapes_from_dt.dimension() == DIMENSION); + + const double FILTRATION = 0.0; + std::cout << "alpha_shapes_from_dt.filtration()=" << alpha_shapes_from_dt.filtration() << std::endl; + BOOST_CHECK(alpha_shapes_from_dt.filtration() == FILTRATION); + + std::cout << "alpha_shapes_from_dt.num_vertices()=" << alpha_shapes_from_dt.num_vertices() << std::endl; + BOOST_CHECK(alpha_shapes_from_dt.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 997; + std::cout << "alpha_shapes_from_dt.num_simplices()=" << alpha_shapes_from_dt.num_simplices() << std::endl; + BOOST_CHECK(alpha_shapes_from_dt.num_simplices() == NUMBER_OF_SIMPLICES); +} + diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt new file mode 100644 index 00000000..3cf97b71 --- /dev/null +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIAlphaShapesTest) + +# need CGAL 4.7 +# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + include_directories (BEFORE "../../include") + + add_definitions(-DDEBUG_TRACES) + add_executable ( AlphaShapesUnitTest Alpha_shapes_unit_test.cpp ) + target_link_libraries(AlphaShapesUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_test(AlphaShapesUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaShapesUnitTest) + + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () +endif() + +cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/Alpha_shapes/include/gudhi") diff --git a/src/Alpha_complex/test/README b/src/Alpha_complex/test/README new file mode 100644 index 00000000..244a2b84 --- /dev/null +++ b/src/Alpha_complex/test/README @@ -0,0 +1,12 @@ +To compile: +*********** + +cmake . +make + +To launch with details: +*********************** + +./AlphaShapesUnitTest --report_level=detailed --log_level=all + + ==> echo $? returns 0 in case of success (non-zero otherwise) diff --git a/src/Alpha_complex/test/S4_100.off b/src/Alpha_complex/test/S4_100.off new file mode 100644 index 00000000..0a5dc58c --- /dev/null +++ b/src/Alpha_complex/test/S4_100.off @@ -0,0 +1,102 @@ +OFF +100 0 0 +0.562921 -0.735261 -0.256472 0.277007 +-0.803733 -0.0527915 -0.315125 0.501918 +-0.24946 -0.354982 -0.410773 -0.801887 +0.916381 -0.0512295 0.371049 0.141223 +0.182222 0.940836 -0.171362 -0.228599 +-0.787145 -0.129213 0.568102 -0.202402 +0.0187866 -0.22093 -0.832882 -0.507095 +-0.4702 -0.533814 0.353776 0.607286 +-0.159798 -0.504771 0.263586 0.806346 +0.295546 0.162541 0.452931 0.825279 +0.242043 -0.107437 -0.913612 -0.308521 +0.875759 -0.113035 -0.469189 -0.0114505 +0.547877 -0.762247 -0.256972 -0.229729 +-0.172302 0.521057 0.412013 -0.727363 +-0.724729 -0.0574074 -0.0290602 0.686023 +0.700434 -0.102636 0.687285 0.162779 +-0.681386 0.0946893 0.610047 0.393178 +-0.847553 -0.357132 0.383743 0.0827718 +0.72297 -0.161631 -0.608517 0.284424 +0.757394 0.141549 0.196065 -0.606528 +0.78094 0.00901997 0.434536 0.448586 +0.14166 -0.619339 0.614589 -0.467582 +0.473105 -0.537832 -0.0103746 0.697711 +-0.208004 0.536218 0.818027 0.00605288 +0.743694 -0.628926 0.188072 0.126488 +-0.462228 -0.278147 0.35514 -0.76345 +-0.17361 0.249211 0.758567 -0.57648 +0.416958 -0.254924 -0.576373 -0.654946 +-0.590751 -0.286089 -0.424896 0.623402 +-0.639538 -0.739693 -0.203745 0.0482932 +0.0731787 0.132121 0.864022 0.480266 +-0.149644 -0.164724 -0.249746 -0.94239 +-0.348592 0.0120379 -0.928656 -0.126239 +0.395328 -0.54513 0.149976 -0.723917 +-0.974164 0.14707 0.157191 0.068302 +-0.166425 0.119943 -0.627304 -0.751269 +0.031947 -0.358518 -0.708301 -0.607251 +0.93781 -0.155368 -0.30951 0.0240237 +0.276094 -0.753155 -0.597088 -0.00387459 +-0.642876 -0.200551 -0.263517 -0.690687 +0.178711 0.604987 -0.262989 0.729993 +-0.520347 0.497922 -0.676144 0.155374 +-0.703999 0.500219 -0.484381 0.139789 +-0.131013 0.835735 0.506779 0.166004 +-0.536116 -0.566557 0.229226 0.582279 +-0.334105 0.158252 0.926091 0.0754059 +-0.0362677 0.296076 0.897108 0.325915 +-0.57486 0.798575 0.15324 -0.0912754 +0.498602 0.0186805 0.72824 0.469801 +-0.960329 0.0473356 0.261005 -0.0860505 +0.899134 -0.381392 -0.214508 0.00921711 +0.570576 0.567224 0.393019 -0.445237 +-0.761763 -0.614589 -0.0546476 -0.197513 +0.188584 0.289531 0.174031 0.922129 +-0.458506 -0.583876 0.639297 -0.2004 +0.785343 -0.21571 0.0794082 -0.574804 +0.0819036 0.65961 -0.247426 0.704973 +0.573125 0.49706 0.373026 0.534145 +-0.513286 -0.626226 0.208535 -0.548536 +0.460558 0.468686 0.507832 -0.55707 +0.716158 -0.488201 0.388209 -0.313164 +0.881074 0.152441 0.380128 -0.236589 +0.885793 0.0386389 0.161009 -0.433537 +-0.365162 0.298384 0.292846 0.831784 +0.364934 0.632269 -0.197205 -0.654346 +-0.31469 -0.429991 0.665304 -0.522923 +-0.734198 0.462914 -0.135691 -0.477756 +-0.422885 0.674444 -0.364143 -0.483419 +0.829218 -0.154622 -0.381147 0.378439 +0.887881 0.310479 -0.109528 0.321363 +-0.354398 -0.693974 0.456019 -0.429941 +-0.492045 -0.160008 0.044387 0.854587 +0.0595532 0.158421 0.412577 -0.895062 +-0.211441 0.491794 -0.153521 0.83058 +-0.33558 -0.504711 0.353831 -0.71236 +-0.735211 -0.197714 0.525626 0.379593 +0.465818 -0.424245 0.769469 -0.104627 +-0.641071 -0.286339 -0.704442 -0.103923 +-0.00446569 0.0249849 -0.194417 -0.980591 +-0.610081 -0.252448 0.176698 -0.729966 +-0.0859217 -0.154471 0.715027 0.676382 +0.091315 0.0723382 -0.855023 -0.505337 +0.165362 0.200983 -0.428242 -0.865373 +-0.587465 0.303019 -0.152442 0.734729 +0.454946 -0.319828 0.437063 -0.706902 +-0.384368 0.277509 0.879225 -0.0470385 +0.523335 -0.330233 -0.208592 0.757335 +0.895086 0.0448492 0.268089 -0.353466 +-0.0272491 -0.567336 -0.72254 -0.39411 +-0.0745014 -0.121818 -0.882466 0.448179 +0.382304 -0.240135 0.851109 -0.267941 +-0.418057 -0.852847 -0.3128 0.00606452 +-0.554046 0.304237 0.272381 -0.725453 +0.155115 -0.0894732 -0.245017 -0.952838 +0.114459 -0.130722 0.953669 0.245614 +0.0913002 -0.462466 0.244433 0.847374 +-0.198849 0.0785111 0.131441 -0.967997 +-0.303154 -0.686484 0.639333 0.167604 +0.521455 0.256835 -0.0584503 -0.811606 +-0.109787 0.870544 0.161523 0.451676 diff --git a/src/Alpha_complex/test/S8_10.off b/src/Alpha_complex/test/S8_10.off new file mode 100644 index 00000000..1d67e10f --- /dev/null +++ b/src/Alpha_complex/test/S8_10.off @@ -0,0 +1,12 @@ +OFF +10 0 0 +0.440036 -0.574754 -0.200485 0.216537 -0.501251 -0.0329236 -0.196529 0.313023 +-0.129367 -0.184089 -0.213021 -0.415848 0.783529 -0.0438025 0.317256 0.120749 +0.132429 0.683748 -0.124536 -0.166133 -0.540695 -0.0887576 0.390234 -0.139031 +0.0137399 -0.161581 -0.609142 -0.370872 -0.320669 -0.364053 0.24127 0.41416 +-0.115313 -0.36425 0.190208 0.581871 0.204605 0.112527 0.313562 0.571337 +0.168272 -0.0746917 -0.635156 -0.214488 0.629498 -0.0812499 -0.337255 -0.00823068 +0.369896 -0.514626 -0.173493 -0.1551 -0.127105 0.384377 0.303936 -0.536566 +-0.49013 -0.0388242 -0.0196532 0.463953 0.515962 -0.0756047 0.506276 0.119908 +-0.434258 0.060347 0.388793 0.250579 -0.653127 -0.275207 0.295714 0.0637842 +0.596172 -0.133284 -0.501793 0.234541 0.428452 0.0800735 0.110912 -0.343109 diff --git a/src/Alpha_shapes/example/CMakeLists.txt b/src/Alpha_shapes/example/CMakeLists.txt deleted file mode 100644 index 582a9322..00000000 --- a/src/Alpha_shapes/example/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -cmake_minimum_required(VERSION 2.6) -project(GUDHIAlphaShapesExample) - -# need CGAL 4.7 -# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. -if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.7.0) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - - include( ${CGAL_USE_FILE} ) - - find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) - message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") - include( ${EIGEN3_USE_FILE} ) - - add_definitions(-DDEBUG_TRACES) - - add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) - target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(dtoffrw_tore3D ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off 3) - - add_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) - target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") - endif() - else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") - endif () -endif() diff --git a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp deleted file mode 100644 index fe889ec0..00000000 --- a/src/Alpha_shapes/example/Delaunay_triangulation_off_rw.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2014 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instanciation of the -// TriangulationDataStructure template parameter - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " inputFile.off dimension outputFile.off" << std::endl; - exit(-1); // ----- >> -} - -int main(int argc, char **argv) { - if (argc != 4) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - int dimension = 0; - int returnedScanValue = sscanf(argv[2], "%d", &dimension); - if ((returnedScanValue == EOF) || (dimension <= 0)) { - std::cerr << "Error: " << argv[2] << " is not correct" << std::endl; - usage(argv[0]); - } - - T dt(dimension); - std::string offFileName(argv[1]); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(offFileName, dt); - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << offFileName << std::endl; - exit(-1); // ----- >> - } - - std::cout << "number_of_finite_full_cells= " << dt.number_of_finite_full_cells() << std::endl; - - std::string outFileName(argv[3]); - std::string offOutputFile(outFileName); - Gudhi::alphashapes::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); - - return 0; -} \ No newline at end of file diff --git a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp deleted file mode 100644 index 0a24fb56..00000000 --- a/src/Alpha_shapes/example/Simplex_tree_from_delaunay_triangulation.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2014 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_shapes.h" - -// to construct a simplex_tree from Delaunay_triangulation -#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Simplex_tree.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instanciation of the -// TriangulationDataStructure template parameter - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off" << std::endl; - exit(-1); // ----- >> -} - -int main(int argc, char **argv) { - if (argc != 2) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - std::string off_file_name(argv[1]); - - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a OFF file - // - // ---------------------------------------------------------------------------- - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); - - std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; - std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; - std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; - std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; - //std::cout << alpha_shapes_from_file << std::endl; - - return 0; -} \ No newline at end of file diff --git a/src/Alpha_shapes/example/alphashapedoc.off b/src/Alpha_shapes/example/alphashapedoc.off deleted file mode 100755 index bb790193..00000000 --- a/src/Alpha_shapes/example/alphashapedoc.off +++ /dev/null @@ -1,10 +0,0 @@ -nOFF -2 7 0 0 -1.0 1.0 -7.0 0.0 -4.0 6.0 -9.0 6.0 -0.0 14.0 -2.0 19.0 -9.0 17.0 - diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes.h deleted file mode 100644 index f23df51a..00000000 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes.h +++ /dev/null @@ -1,311 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2015 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ -#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ - -// to construct a Delaunay_triangulation from a OFF file -#include - -// to construct a simplex_tree from Delaunay_triangulation -#include -#include - -#include -#include -#include // isnan, fmax - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace Gudhi { - -namespace alphashapes { - -#define Kinit(f) =k.f() - -/** \defgroup alpha_shapes Alpha shapes in dimension N - * -
Implementations:
- Alpha shapes in dimension N are a subset of Delaunay Triangulation in dimension N. - - - * \author Vincent Rouvreau - * \version 1.0 - * \date 2015 - * \copyright GNU General Public License v3. - * @{ - */ - -/** - * \brief Alpha shapes data structure. - * - * \details Every simplex \f$[v_0, \cdots ,v_d]\f$ admits a canonical orientation - * induced by the order relation on vertices \f$ v_0 < \cdots < v_d \f$. - * - * Details may be found in \cite boissonnatmariasimplextreealgorithmica. - * - * \implements FilteredComplex - * - */ -class Alpha_shapes { - private: - // From Simplex_tree - /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ - typedef std::vector typeVectorVertex; - - typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; - typedef typename std::pair Simplex_result; - - // From CGAL - /** \brief Kernel for the Delaunay_triangulation. - * Dimension can be set dynamically. - */ - typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - /** \brief Delaunay_triangulation type required to create an alpha-shape. - */ - typedef CGAL::Delaunay_triangulation Delaunay_triangulation; - - typedef typename Kernel::Compute_squared_radius_d Squared_Radius; - typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; - - /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ - typedef std::vector typeVectorPoint; - - private: - /** \brief Upper bound on the simplex tree of the simplicial complex.*/ - Gudhi::Simplex_tree<> st_; - - public: - - Alpha_shapes(std::string& off_file_name) { - // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function - Delaunay_triangulation dt(2); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << off_file_name << std::endl; - exit(-1); // ----- >> - } -#ifdef DEBUG_TRACES - std::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; - std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; -#endif // DEBUG_TRACES - init(dt); - } - - template - Alpha_shapes(T& triangulation) { - init(triangulation); - } - - ~Alpha_shapes() { } - - private: - - template - void init(T& triangulation) { - st_.set_dimension(triangulation.maximal_dimension()); - - // -------------------------------------------------------------------------------------------- - // bimap to retrieve vertex handles from points and vice versa - typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; - bimap_points_vh points_to_vh; - // Start to insert at handle = 0 - default integer value - Vertex_handle vertex_handle = Vertex_handle(); - // Loop on triangulation vertices list - for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { - points_to_vh.insert(bimap_points_vh::value_type(vit->point(), vertex_handle)); - vertex_handle++; - } - // -------------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------------- - // Simplex_tree construction from loop on triangulation finite full cells list - for (auto cit = triangulation.finite_full_cells_begin(); cit != triangulation.finite_full_cells_end(); ++cit) { - typeVectorVertex vertexVector; -#ifdef DEBUG_TRACES - std::cout << "Simplex_tree insertion "; -#endif // DEBUG_TRACES - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { -#ifdef DEBUG_TRACES - std::cout << " " << points_to_vh.left.at((*vit)->point()); -#endif // DEBUG_TRACES - // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(points_to_vh.left.at((*vit)->point())); - } -#ifdef DEBUG_TRACES - std::cout << std::endl; -#endif // DEBUG_TRACES - // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - Simplex_result insert_result = st_.insert_simplex_and_subfaces(vertexVector, - std::numeric_limits::quiet_NaN()); - if (!insert_result.second) { - std::cerr << "Alpha_shapes::init insert_simplex_and_subfaces failed" << std::endl; - } - } - // -------------------------------------------------------------------------------------------- - - Filtration_value filtration_max = 0.0; - - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); - // -------------------------------------------------------------------------------------------- - // ### For i : d -> 0 - for (int decr_dim = st_.dimension(); decr_dim >= 0; decr_dim--) { - // ### Foreach Sigma of dim i - for (auto f_simplex : st_.skeleton_simplex_range(decr_dim)) { - int f_simplex_dim = st_.dimension(f_simplex); - if (decr_dim == f_simplex_dim) { - typeVectorPoint pointVector; -#ifdef DEBUG_TRACES - std::cout << "Sigma of dim " << decr_dim << " is"; -#endif // DEBUG_TRACES - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { - pointVector.push_back(points_to_vh.right.at(vertex)); -#ifdef DEBUG_TRACES - std::cout << " " << vertex; -#endif // DEBUG_TRACES - } -#ifdef DEBUG_TRACES - std::cout << std::endl; -#endif // DEBUG_TRACES - // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (isnan(st_.filtration(f_simplex))) { - Filtration_value alpha_shapes_filtration = 0.0; - // No need to compute squared_radius on a single point - alpha is 0.0 - if (f_simplex_dim > 0) { - alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); - } - st_.assign_filtration(f_simplex, alpha_shapes_filtration); - filtration_max = fmax(filtration_max, alpha_shapes_filtration); -#ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; -#endif // DEBUG_TRACES - } - - // ### Foreach Tau face of Sigma - for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { -#ifdef DEBUG_TRACES - std::cout << " | --------------------------------------------------" << std::endl; - std::cout << " | Tau "; - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { - std::cout << vertex << " "; - } - std::cout << "is a face of Sigma" << std::endl; -#endif // DEBUG_TRACES - // insert the Tau points in a vector for is_gabriel function - typeVectorPoint pointVector; - Vertex_handle vertexForGabriel = Vertex_handle(); - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { - pointVector.push_back(points_to_vh.right.at(vertex)); - } - // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { - if (std::find(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertex)) == pointVector.end()) { - // vertex is not found in Tau - vertexForGabriel = vertex; - // No need to continue loop - break; - } - } -#ifdef DEBUG_TRACES - std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; - bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) - != CGAL::ON_BOUNDED_SIDE; - std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; -#endif // DEBUG_TRACES - // ### If filt(Tau) is not NaN - // ### or Tau is not Gabriel of Sigma - if (!isnan(st_.filtration(f_boundary)) || - (is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) == CGAL::ON_BOUNDED_SIDE) - ) { - // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) - Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); - st_.assign_filtration(f_boundary, alpha_shapes_filtration); - filtration_max = fmax(filtration_max, alpha_shapes_filtration); -#ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; -#endif // DEBUG_TRACES - } - } - } - } - } - // -------------------------------------------------------------------------------------------- - -#ifdef DEBUG_TRACES - std::cout << "filtration_max=" << filtration_max << std::endl; -#endif // DEBUG_TRACES - st_.set_filtration(filtration_max); - } - - public: - - /** \brief Returns the number of vertices in the complex. */ - size_t num_vertices() { - return st_.num_vertices(); - } - - /** \brief Returns the number of simplices in the complex. - * - * Does not count the empty simplex. */ - const unsigned int& num_simplices() const { - return st_.num_simplices(); - } - - /** \brief Returns an upper bound on the dimension of the simplicial complex. */ - int dimension() { - return st_.dimension(); - } - - /** \brief Returns an upper bound of the filtration values of the simplices. */ - Filtration_value filtration() { - return st_.filtration(); - } - - friend std::ostream& operator<<(std::ostream& os, const Alpha_shapes & alpha_shape) { - // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor - Gudhi::Simplex_tree<> st = alpha_shape.st_; - os << st << std::endl; - return os; - } -}; - -} // namespace alphashapes - -} // namespace Gudhi - -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ diff --git a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h deleted file mode 100644 index a4e5e2fe..00000000 --- a/src/Alpha_shapes/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ /dev/null @@ -1,192 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2015 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ -#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ - -#include -#include -#include -#include - -#include "gudhi/Off_reader.h" - -namespace Gudhi { - -namespace alphashapes { - -/** - *@brief Off reader visitor with flag that can be passed to Off_reader to read a Delaunay_triangulation_complex. - */ -template -class Delaunay_triangulation_off_visitor_reader { - Complex& complex_; - typedef typename Complex::Point Point; - - public: - - explicit Delaunay_triangulation_off_visitor_reader(Complex& complex) : - complex_(complex) { } - - void init(int dim, int num_vertices, int num_faces, int num_edges) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << - num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; -#endif // DEBUG_TRACES - if (num_faces > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << - "file for Delaunay triangulation - faces are computed." << std::endl; - } - if (num_edges > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << - "file for Delaunay triangulation - edges are computed." << std::endl; - } - //complex_.set_current_dimension(dim); - } - - void point(const std::vector& point) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::point "; - for (auto coordinate : point) { - std::cout << coordinate << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES - complex_.insert(Point(point.size(), point.begin(), point.end())); - } - - void maximal_face(const std::vector& face) { - // For Delaunay Triangulation, only points are read -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::face "; - for (auto vertex : face) { - std::cout << vertex << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES - } - - void done() { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::done" << std::endl; -#endif // DEBUG_TRACES - } -}; - -/** - *@brief Class that allows to load a Delaunay_triangulation_complex from an off file. - */ -template -class Delaunay_triangulation_off_reader { - public: - - /** - * name_file : file to read - * read_complex : complex that will receive the file content - * read_only_points : specify true if only the points must be read - */ - Delaunay_triangulation_off_reader(const std::string & name_file, Complex& read_complex) : valid_(false) { - std::ifstream stream(name_file); - if (stream.is_open()) { - Delaunay_triangulation_off_visitor_reader off_visitor(read_complex); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - } else { - std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << - name_file << std::endl; - } - - } - - /** - * return true if reading did not meet problems. - */ - bool is_valid() const { - return valid_; - } - - private: - bool valid_; -}; - -template -class Delaunay_triangulation_off_writer { - public: - typedef typename Complex::Point Point; - - /** - * name_file : file where the off will be written - * save_complex : complex that be outputted in the file - * for now only save triangles. - */ - Delaunay_triangulation_off_writer(const std::string & name_file, const Complex& save_complex) { - std::ofstream stream(name_file); - if (stream.is_open()) { - if (save_complex.current_dimension() == 3) { - // OFF header - stream << "OFF" << std::endl; - // no endl on next line - don't know why... - stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; - } else { - // nOFF header - stream << "nOFF" << std::endl; - // no endl on next line - don't know why... - stream << save_complex.current_dimension() << " " << save_complex.number_of_vertices() << " " << - save_complex.number_of_finite_full_cells() << " 0"; - - } - - // bimap to retrieve vertex handles from points and vice versa - std::map< Point, int > points_to_vh; - // Start to insert at default handle value - int vertex_handle = int(); - - // Points list - for (auto vit = save_complex.vertices_begin(); vit != save_complex.vertices_end(); ++vit) { - for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { - stream << *Coord << " "; - } - stream << std::endl; - points_to_vh[vit->point()] = vertex_handle; - vertex_handle++; - } - - for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.finite_full_cells_end(); ++cit) { - std::vector vertexVector; - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - stream << points_to_vh[(*vit)->point()] << " "; - } - stream << std::endl; - } - stream.close(); - } else { - std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << - name_file << std::endl; - } - } -}; - -} // namespace alphashapes - -} // namespace Gudhi - -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp b/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp deleted file mode 100644 index d5db3bfa..00000000 --- a/src/Alpha_shapes/test/Alpha_shapes_unit_test.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2015 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#define BOOST_TEST_MODULE alpha_shapes -#include -#include -#include -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_shapes.h" - -// to construct a simplex_tree from Delaunay_triangulation -#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Simplex_tree.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instanciation of the -// TriangulationDataStructure template parameter - -BOOST_AUTO_TEST_CASE( OFF_file ) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a OFF file - // - // ---------------------------------------------------------------------------- - std::string off_file_name("S4_100.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name, 4); - - const int DIMENSION = 4; - std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.filtration() == FILTRATION); - - const int NUMBER_OF_VERTICES = 100; - std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.num_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_SIMPLICES = 6779; - std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.num_simplices() == NUMBER_OF_SIMPLICES); - -} - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a Delauny triangulation - // - // ---------------------------------------------------------------------------- - T dt(8); - std::string off_file_name("S8_10.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); - std::cout << "off_reader.is_valid()=" << off_reader.is_valid() << std::endl; - BOOST_CHECK(off_reader.is_valid()); - - const int NUMBER_OF_VERTICES = 10; - std::cout << "dt.number_of_vertices()=" << dt.number_of_vertices() << std::endl; - BOOST_CHECK(dt.number_of_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_FULL_CELLS = 30; - std::cout << "dt.number_of_full_cells()=" << dt.number_of_full_cells() << std::endl; - BOOST_CHECK(dt.number_of_full_cells() == NUMBER_OF_FULL_CELLS); - - const int NUMBER_OF_FINITE_FULL_CELLS = 6; - std::cout << "dt.number_of_finite_full_cells()=" << dt.number_of_finite_full_cells() << std::endl; - BOOST_CHECK(dt.number_of_finite_full_cells() == NUMBER_OF_FINITE_FULL_CELLS); - - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_dt(dt); - - const int DIMENSION = 8; - std::cout << "alpha_shapes_from_dt.dimension()=" << alpha_shapes_from_dt.dimension() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_shapes_from_dt.filtration()=" << alpha_shapes_from_dt.filtration() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.filtration() == FILTRATION); - - std::cout << "alpha_shapes_from_dt.num_vertices()=" << alpha_shapes_from_dt.num_vertices() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.num_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_SIMPLICES = 997; - std::cout << "alpha_shapes_from_dt.num_simplices()=" << alpha_shapes_from_dt.num_simplices() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.num_simplices() == NUMBER_OF_SIMPLICES); -} - diff --git a/src/Alpha_shapes/test/CMakeLists.txt b/src/Alpha_shapes/test/CMakeLists.txt deleted file mode 100644 index 3cf97b71..00000000 --- a/src/Alpha_shapes/test/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -cmake_minimum_required(VERSION 2.6) -project(GUDHIAlphaShapesTest) - -# need CGAL 4.7 -# cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. -if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.7.0) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - - include( ${CGAL_USE_FILE} ) - - find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) - message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") - include( ${EIGEN3_USE_FILE} ) - include_directories (BEFORE "../../include") - - add_definitions(-DDEBUG_TRACES) - add_executable ( AlphaShapesUnitTest Alpha_shapes_unit_test.cpp ) - target_link_libraries(AlphaShapesUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - add_test(AlphaShapesUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaShapesUnitTest) - - else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") - endif() - else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") - endif () -endif() - -cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/Alpha_shapes/include/gudhi") diff --git a/src/Alpha_shapes/test/README b/src/Alpha_shapes/test/README deleted file mode 100644 index 244a2b84..00000000 --- a/src/Alpha_shapes/test/README +++ /dev/null @@ -1,12 +0,0 @@ -To compile: -*********** - -cmake . -make - -To launch with details: -*********************** - -./AlphaShapesUnitTest --report_level=detailed --log_level=all - - ==> echo $? returns 0 in case of success (non-zero otherwise) diff --git a/src/Alpha_shapes/test/S4_100.off b/src/Alpha_shapes/test/S4_100.off deleted file mode 100644 index 0a5dc58c..00000000 --- a/src/Alpha_shapes/test/S4_100.off +++ /dev/null @@ -1,102 +0,0 @@ -OFF -100 0 0 -0.562921 -0.735261 -0.256472 0.277007 --0.803733 -0.0527915 -0.315125 0.501918 --0.24946 -0.354982 -0.410773 -0.801887 -0.916381 -0.0512295 0.371049 0.141223 -0.182222 0.940836 -0.171362 -0.228599 --0.787145 -0.129213 0.568102 -0.202402 -0.0187866 -0.22093 -0.832882 -0.507095 --0.4702 -0.533814 0.353776 0.607286 --0.159798 -0.504771 0.263586 0.806346 -0.295546 0.162541 0.452931 0.825279 -0.242043 -0.107437 -0.913612 -0.308521 -0.875759 -0.113035 -0.469189 -0.0114505 -0.547877 -0.762247 -0.256972 -0.229729 --0.172302 0.521057 0.412013 -0.727363 --0.724729 -0.0574074 -0.0290602 0.686023 -0.700434 -0.102636 0.687285 0.162779 --0.681386 0.0946893 0.610047 0.393178 --0.847553 -0.357132 0.383743 0.0827718 -0.72297 -0.161631 -0.608517 0.284424 -0.757394 0.141549 0.196065 -0.606528 -0.78094 0.00901997 0.434536 0.448586 -0.14166 -0.619339 0.614589 -0.467582 -0.473105 -0.537832 -0.0103746 0.697711 --0.208004 0.536218 0.818027 0.00605288 -0.743694 -0.628926 0.188072 0.126488 --0.462228 -0.278147 0.35514 -0.76345 --0.17361 0.249211 0.758567 -0.57648 -0.416958 -0.254924 -0.576373 -0.654946 --0.590751 -0.286089 -0.424896 0.623402 --0.639538 -0.739693 -0.203745 0.0482932 -0.0731787 0.132121 0.864022 0.480266 --0.149644 -0.164724 -0.249746 -0.94239 --0.348592 0.0120379 -0.928656 -0.126239 -0.395328 -0.54513 0.149976 -0.723917 --0.974164 0.14707 0.157191 0.068302 --0.166425 0.119943 -0.627304 -0.751269 -0.031947 -0.358518 -0.708301 -0.607251 -0.93781 -0.155368 -0.30951 0.0240237 -0.276094 -0.753155 -0.597088 -0.00387459 --0.642876 -0.200551 -0.263517 -0.690687 -0.178711 0.604987 -0.262989 0.729993 --0.520347 0.497922 -0.676144 0.155374 --0.703999 0.500219 -0.484381 0.139789 --0.131013 0.835735 0.506779 0.166004 --0.536116 -0.566557 0.229226 0.582279 --0.334105 0.158252 0.926091 0.0754059 --0.0362677 0.296076 0.897108 0.325915 --0.57486 0.798575 0.15324 -0.0912754 -0.498602 0.0186805 0.72824 0.469801 --0.960329 0.0473356 0.261005 -0.0860505 -0.899134 -0.381392 -0.214508 0.00921711 -0.570576 0.567224 0.393019 -0.445237 --0.761763 -0.614589 -0.0546476 -0.197513 -0.188584 0.289531 0.174031 0.922129 --0.458506 -0.583876 0.639297 -0.2004 -0.785343 -0.21571 0.0794082 -0.574804 -0.0819036 0.65961 -0.247426 0.704973 -0.573125 0.49706 0.373026 0.534145 --0.513286 -0.626226 0.208535 -0.548536 -0.460558 0.468686 0.507832 -0.55707 -0.716158 -0.488201 0.388209 -0.313164 -0.881074 0.152441 0.380128 -0.236589 -0.885793 0.0386389 0.161009 -0.433537 --0.365162 0.298384 0.292846 0.831784 -0.364934 0.632269 -0.197205 -0.654346 --0.31469 -0.429991 0.665304 -0.522923 --0.734198 0.462914 -0.135691 -0.477756 --0.422885 0.674444 -0.364143 -0.483419 -0.829218 -0.154622 -0.381147 0.378439 -0.887881 0.310479 -0.109528 0.321363 --0.354398 -0.693974 0.456019 -0.429941 --0.492045 -0.160008 0.044387 0.854587 -0.0595532 0.158421 0.412577 -0.895062 --0.211441 0.491794 -0.153521 0.83058 --0.33558 -0.504711 0.353831 -0.71236 --0.735211 -0.197714 0.525626 0.379593 -0.465818 -0.424245 0.769469 -0.104627 --0.641071 -0.286339 -0.704442 -0.103923 --0.00446569 0.0249849 -0.194417 -0.980591 --0.610081 -0.252448 0.176698 -0.729966 --0.0859217 -0.154471 0.715027 0.676382 -0.091315 0.0723382 -0.855023 -0.505337 -0.165362 0.200983 -0.428242 -0.865373 --0.587465 0.303019 -0.152442 0.734729 -0.454946 -0.319828 0.437063 -0.706902 --0.384368 0.277509 0.879225 -0.0470385 -0.523335 -0.330233 -0.208592 0.757335 -0.895086 0.0448492 0.268089 -0.353466 --0.0272491 -0.567336 -0.72254 -0.39411 --0.0745014 -0.121818 -0.882466 0.448179 -0.382304 -0.240135 0.851109 -0.267941 --0.418057 -0.852847 -0.3128 0.00606452 --0.554046 0.304237 0.272381 -0.725453 -0.155115 -0.0894732 -0.245017 -0.952838 -0.114459 -0.130722 0.953669 0.245614 -0.0913002 -0.462466 0.244433 0.847374 --0.198849 0.0785111 0.131441 -0.967997 --0.303154 -0.686484 0.639333 0.167604 -0.521455 0.256835 -0.0584503 -0.811606 --0.109787 0.870544 0.161523 0.451676 diff --git a/src/Alpha_shapes/test/S8_10.off b/src/Alpha_shapes/test/S8_10.off deleted file mode 100644 index 1d67e10f..00000000 --- a/src/Alpha_shapes/test/S8_10.off +++ /dev/null @@ -1,12 +0,0 @@ -OFF -10 0 0 -0.440036 -0.574754 -0.200485 0.216537 -0.501251 -0.0329236 -0.196529 0.313023 --0.129367 -0.184089 -0.213021 -0.415848 0.783529 -0.0438025 0.317256 0.120749 -0.132429 0.683748 -0.124536 -0.166133 -0.540695 -0.0887576 0.390234 -0.139031 -0.0137399 -0.161581 -0.609142 -0.370872 -0.320669 -0.364053 0.24127 0.41416 --0.115313 -0.36425 0.190208 0.581871 0.204605 0.112527 0.313562 0.571337 -0.168272 -0.0746917 -0.635156 -0.214488 0.629498 -0.0812499 -0.337255 -0.00823068 -0.369896 -0.514626 -0.173493 -0.1551 -0.127105 0.384377 0.303936 -0.536566 --0.49013 -0.0388242 -0.0196532 0.463953 0.515962 -0.0756047 0.506276 0.119908 --0.434258 0.060347 0.388793 0.250579 -0.653127 -0.275207 0.295714 0.0637842 -0.596172 -0.133284 -0.501793 0.234541 0.428452 0.0800735 0.110912 -0.343109 -- cgit v1.2.3 From 77b57ae69fa2042b652d91d8015c1d9533176090 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 16 Jun 2015 13:30:27 +0000 Subject: Alpha_complex renamed. Compilation and tests are OK. bimap is stored in class. bimap is now on CGAL Vertex_iterator - instead of points. is_gabriel not computed when simplex dimension is 1. is_gabriel not computed when filt(Tau) is not NaN. Delaunay_triangulation is a pointer constructed in Delaunay_triangulation_off_io.h git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@617 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4fa4a26ce47066efe22aed99734ff1dd821ad70b --- CMakeLists.txt | 6 +- data/points/generator/hypergenerator.cpp | 9 +- src/Alpha_complex/example/CMakeLists.txt | 3 + .../example/Delaunay_triangulation_off_rw.cpp | 4 +- .../Simplex_tree_from_delaunay_triangulation.cpp | 16 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 339 +++++++++++++++++++++ src/Alpha_complex/include/gudhi/Alpha_shapes.h | 311 ------------------- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 50 ++- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 126 ++++++++ src/Alpha_complex/test/Alpha_shapes_unit_test.cpp | 126 -------- src/Alpha_complex/test/CMakeLists.txt | 14 +- src/CMakeLists.txt | 2 +- 12 files changed, 530 insertions(+), 476 deletions(-) create mode 100644 src/Alpha_complex/include/gudhi/Alpha_complex.h delete mode 100644 src/Alpha_complex/include/gudhi/Alpha_shapes.h create mode 100644 src/Alpha_complex/test/Alpha_complex_unit_test.cpp delete mode 100644 src/Alpha_complex/test/Alpha_shapes_unit_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 89440490..01108db9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,7 @@ else() message(STATUS "boost include dirs:" ${Boost_INCLUDE_DIRS}) include_directories(src/common/include/) - include_directories(src/Alpha_shapes/include/) + include_directories(src/Alpha_complex/include/) include_directories(src/Bottleneck/include/) include_directories(src/Contraction/include/) include_directories(src/Hasse_complex/include/) @@ -85,8 +85,8 @@ else() add_subdirectory(src/Skeleton_blocker/example) add_subdirectory(src/Contraction/example) add_subdirectory(src/Hasse_complex/example) - add_subdirectory(src/Alpha_shapes/example) - add_subdirectory(src/Alpha_shapes/test) + add_subdirectory(src/Alpha_complex/example) + add_subdirectory(src/Alpha_complex/test) add_subdirectory(src/Bottleneck/example) add_subdirectory(src/Bottleneck/test) diff --git a/data/points/generator/hypergenerator.cpp b/data/points/generator/hypergenerator.cpp index f4ea6b07..32ef450d 100644 --- a/data/points/generator/hypergenerator.cpp +++ b/data/points/generator/hypergenerator.cpp @@ -86,8 +86,13 @@ int main(int argc, char **argv) { } std::ofstream diagram_out(argv[3]); - diagram_out << "OFF" << std::endl; - diagram_out << points_number << " 0 0" << std::endl; + if (dimension == 3) { + diagram_out << "OFF" << std::endl; + diagram_out << points_number << " 0 0" << std::endl; + } else { + diagram_out << "nOFF" << std::endl; + diagram_out << dimension << " " << points_number << " 0 0" << std::endl; + } if (diagram_out.is_open()) { // Instanciate a random point generator diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 582a9322..258def49 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -22,6 +22,9 @@ if(CGAL_FOUND) add_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + + add_executable ( template_off template_off.cpp ) + target_link_libraries(template_off ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp index fe889ec0..405b3cb9 100644 --- a/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp +++ b/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp @@ -63,7 +63,7 @@ int main(int argc, char **argv) { T dt(dimension); std::string offFileName(argv[1]); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(offFileName, dt); + Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(offFileName, dt); if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << offFileName << std::endl; exit(-1); // ----- >> @@ -73,7 +73,7 @@ int main(int argc, char **argv) { std::string outFileName(argv[3]); std::string offOutputFile(outFileName); - Gudhi::alphashapes::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); + Gudhi::alphacomplex::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); return 0; } \ No newline at end of file diff --git a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp index 0a24fb56..f09e6121 100644 --- a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -22,7 +22,7 @@ // to construct a Delaunay_triangulation from a OFF file #include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_shapes.h" +#include "gudhi/Alpha_complex.h" // to construct a simplex_tree from Delaunay_triangulation #include "gudhi/graph_simplicial_complex.h" @@ -62,16 +62,16 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // - // Init of an alpha-shape from a OFF file + // Init of an alpha-complex from a OFF file // // ---------------------------------------------------------------------------- - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); - std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; - std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; - std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; - std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; - //std::cout << alpha_shapes_from_file << std::endl; + std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; + std::cout << "alpha_complex_from_file.filtration()=" << alpha_complex_from_file.filtration() << std::endl; + std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; + std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + std::cout << alpha_complex_from_file << std::endl; return 0; } \ No newline at end of file diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h new file mode 100644 index 00000000..ca84d6d9 --- /dev/null +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -0,0 +1,339 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ +#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ + +// to construct a Delaunay_triangulation from a OFF file +#include + +// to construct a simplex_tree from Delaunay_triangulation +#include +#include + +#include +#include +#include // isnan, fmax + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Gudhi { + +namespace alphacomplex { + +#define Kinit(f) =k.f() + +/** \defgroup alpha_complex Alpha complex in dimension N + * +
Implementations:
+ Alpha complex in dimension N are a subset of Delaunay Triangulation in dimension N. + + + * \author Vincent Rouvreau + * \version 1.0 + * \date 2015 + * \copyright GNU General Public License v3. + * @{ + */ + +/** + * \brief Alpha complex data structure. + * + * \details Every simplex \f$[v_0, \cdots ,v_d]\f$ admits a canonical orientation + * induced by the order relation on vertices \f$ v_0 < \cdots < v_d \f$. + * + * Details may be found in \cite boissonnatmariasimplextreealgorithmica. + * + * + */ +class Alpha_complex { + private: + // From Simplex_tree + /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + typedef std::vector typeVectorVertex; + + typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; + typedef typename std::pair Simplex_result; + + // From CGAL + /** \brief Kernel for the Delaunay_triangulation-> + * Dimension can be set dynamically. + */ + typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + /** \brief Delaunay_triangulation type required to create an alpha-complex. + */ + typedef CGAL::Delaunay_triangulation Delaunay_triangulation; + + typedef typename Kernel::Compute_squared_radius_d Squared_Radius; + typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; + + /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + typedef std::vector Vector_of_CGAL_points; + + typedef Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; + + typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; + + private: + /** \brief Upper bound on the simplex tree of the simplicial complex.*/ + Gudhi::Simplex_tree<> st_; + Bimap_vertex cgal_simplextree; + Delaunay_triangulation* triangulation; + + public: + + Alpha_complex(std::string& off_file_name) + : triangulation(nullptr) { +#ifdef DEBUG_TRACES + char buffer[256]={0}; + sprintf(buffer,"%p", triangulation); + std::cout << "pointer=" << buffer << std::endl; +#endif // DEBUG_TRACES + Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(off_file_name); + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << off_file_name << std::endl; + exit(-1); // ----- >> + } + triangulation = off_reader.get_complex(); +#ifdef DEBUG_TRACES + //char buffer[256]={0}; + sprintf(buffer,"%p", triangulation); + std::cout << "pointer=" << buffer << std::endl; + std::cout << "number of vertices=" << triangulation->number_of_vertices() << std::endl; + std::cout << "number of full cells=" << triangulation->number_of_full_cells() << std::endl; + std::cout << "number of finite full cells=" << triangulation->number_of_finite_full_cells() << std::endl; +#endif // DEBUG_TRACES + init(); + } + + ~Alpha_complex() { + delete triangulation; + } + + private: + + void init() { + st_.set_dimension(triangulation->maximal_dimension()); + + // -------------------------------------------------------------------------------------------- + // bimap to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa + // Start to insert at handle = 0 - default integer value + Vertex_handle vertex_handle = Vertex_handle(); + // Loop on triangulation vertices list + for (CGAL_vertex_iterator vit = triangulation->vertices_begin(); vit != triangulation->vertices_end(); ++vit) { + cgal_simplextree.insert(Bimap_vertex::value_type(vit, vertex_handle)); + vertex_handle++; + } + // -------------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------------- + // Simplex_tree construction from loop on triangulation finite full cells list + for (auto cit = triangulation->finite_full_cells_begin(); cit != triangulation->finite_full_cells_end(); ++cit) { + typeVectorVertex vertexVector; +#ifdef DEBUG_TRACES + std::cout << "Simplex_tree insertion "; +#endif // DEBUG_TRACES + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { +#ifdef DEBUG_TRACES + std::cout << " " << cgal_simplextree.left.at(*vit); +#endif // DEBUG_TRACES + // Vector of vertex construction for simplex_tree structure + vertexVector.push_back(cgal_simplextree.left.at(*vit)); + } +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES + // Insert each simplex and its subfaces in the simplex tree - filtration is NaN + Simplex_result insert_result = st_.insert_simplex_and_subfaces(vertexVector, + std::numeric_limits::quiet_NaN()); + if (!insert_result.second) { + std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; + } + } + // -------------------------------------------------------------------------------------------- + + Filtration_value filtration_max = 0.0; + // -------------------------------------------------------------------------------------------- + // ### For i : d -> 0 + for (int decr_dim = st_.dimension(); decr_dim >= 0; decr_dim--) { + // ### Foreach Sigma of dim i + for (auto f_simplex : st_.skeleton_simplex_range(decr_dim)) { + int f_simplex_dim = st_.dimension(f_simplex); + if (decr_dim == f_simplex_dim) { + Vector_of_CGAL_points pointVector; +#ifdef DEBUG_TRACES + std::cout << "Sigma of dim " << decr_dim << " is"; +#endif // DEBUG_TRACES + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); +#ifdef DEBUG_TRACES + std::cout << " " << vertex; +#endif // DEBUG_TRACES + } +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES + // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) + if (isnan(st_.filtration(f_simplex))) { + Filtration_value alpha_complex_filtration = 0.0; + // No need to compute squared_radius on a single point - alpha is 0.0 + if (f_simplex_dim > 0) { + // squared_radius function initialization + Kernel k; + Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); + + alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); + } + st_.assign_filtration(f_simplex, alpha_complex_filtration); + filtration_max = fmax(filtration_max, alpha_complex_filtration); +#ifdef DEBUG_TRACES + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; +#endif // DEBUG_TRACES + } + propagate_alpha_filtration(f_simplex, decr_dim); + } + } + } + // -------------------------------------------------------------------------------------------- + +#ifdef DEBUG_TRACES + std::cout << "filtration_max=" << filtration_max << std::endl; +#endif // DEBUG_TRACES + st_.set_filtration(filtration_max); + } + + template + void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { + // ### Foreach Tau face of Sigma + for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { +#ifdef DEBUG_TRACES + std::cout << " | --------------------------------------------------" << std::endl; + std::cout << " | Tau "; + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + std::cout << vertex << " "; + } + std::cout << "is a face of Sigma" << std::endl; + std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; +#endif // DEBUG_TRACES + // ### If filt(Tau) is not NaN + if (!isnan(st_.filtration(f_boundary))) { + // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) + Filtration_value alpha_complex_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); + st_.assign_filtration(f_boundary, alpha_complex_filtration); + // No need to check for filtration_max, alpha_complex_filtration is a min of an existing filtration value +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES + // ### Else + } else { + // No need to compute is_gabriel for dimension <= 2 + // i.e. : Sigma = (3,1) => Tau = 1 + if (decr_dim > 1) { + // insert the Tau points in a vector for is_gabriel function + Vector_of_CGAL_points pointVector; + Vertex_handle vertexForGabriel = Vertex_handle(); + for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); + } + // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function + for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + if (std::find(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertex))->point()) + == pointVector.end()) { + // vertex is not found in Tau + vertexForGabriel = vertex; + // No need to continue loop + break; + } + } + // is_gabriel function initialization + Kernel k; + Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); +#ifdef DEBUG_TRACES + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) + != CGAL::ON_BOUNDED_SIDE; + std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; +#endif // DEBUG_TRACES + // ### If Tau is not Gabriel of Sigma + if ((is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) + == CGAL::ON_BOUNDED_SIDE)) { + // ### filt(Tau) = filt(Sigma) + Filtration_value alpha_complex_filtration = st_.filtration(f_simplex); + st_.assign_filtration(f_boundary, alpha_complex_filtration); + // No need to check for filtration_max, alpha_complex_filtration is an existing filtration value +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = filt(Sigma) = " << st_.filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES + } + } + } + } + } + public: + + /** \brief Returns the number of vertices in the complex. */ + size_t num_vertices() { + return st_.num_vertices(); + } + + /** \brief Returns the number of simplices in the complex. + * + * Does not count the empty simplex. */ + const unsigned int& num_simplices() const { + return st_.num_simplices(); + } + + /** \brief Returns an upper bound on the dimension of the simplicial complex. */ + int dimension() { + return st_.dimension(); + } + + /** \brief Returns an upper bound of the filtration values of the simplices. */ + Filtration_value filtration() { + return st_.filtration(); + } + + friend std::ostream& operator<<(std::ostream& os, const Alpha_complex & alpha_complex) { + // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor + Gudhi::Simplex_tree<> st = alpha_complex.st_; + os << st << std::endl; + return os; + } +}; + +} // namespace alphacomplex + +} // namespace Gudhi + +#endif // SRC_ALPHA_COMPLEX_INCLUDE_GUDHI_ALPHA_COMPLEX_H_ diff --git a/src/Alpha_complex/include/gudhi/Alpha_shapes.h b/src/Alpha_complex/include/gudhi/Alpha_shapes.h deleted file mode 100644 index f23df51a..00000000 --- a/src/Alpha_complex/include/gudhi/Alpha_shapes.h +++ /dev/null @@ -1,311 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2015 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ -#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ - -// to construct a Delaunay_triangulation from a OFF file -#include - -// to construct a simplex_tree from Delaunay_triangulation -#include -#include - -#include -#include -#include // isnan, fmax - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace Gudhi { - -namespace alphashapes { - -#define Kinit(f) =k.f() - -/** \defgroup alpha_shapes Alpha shapes in dimension N - * -
Implementations:
- Alpha shapes in dimension N are a subset of Delaunay Triangulation in dimension N. - - - * \author Vincent Rouvreau - * \version 1.0 - * \date 2015 - * \copyright GNU General Public License v3. - * @{ - */ - -/** - * \brief Alpha shapes data structure. - * - * \details Every simplex \f$[v_0, \cdots ,v_d]\f$ admits a canonical orientation - * induced by the order relation on vertices \f$ v_0 < \cdots < v_d \f$. - * - * Details may be found in \cite boissonnatmariasimplextreealgorithmica. - * - * \implements FilteredComplex - * - */ -class Alpha_shapes { - private: - // From Simplex_tree - /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ - typedef std::vector typeVectorVertex; - - typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; - typedef typename std::pair Simplex_result; - - // From CGAL - /** \brief Kernel for the Delaunay_triangulation. - * Dimension can be set dynamically. - */ - typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - /** \brief Delaunay_triangulation type required to create an alpha-shape. - */ - typedef CGAL::Delaunay_triangulation Delaunay_triangulation; - - typedef typename Kernel::Compute_squared_radius_d Squared_Radius; - typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; - - /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ - typedef std::vector typeVectorPoint; - - private: - /** \brief Upper bound on the simplex tree of the simplicial complex.*/ - Gudhi::Simplex_tree<> st_; - - public: - - Alpha_shapes(std::string& off_file_name) { - // Construct a default Delaunay_triangulation (dim=0) - dim will be set in visitor reader init function - Delaunay_triangulation dt(2); - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << off_file_name << std::endl; - exit(-1); // ----- >> - } -#ifdef DEBUG_TRACES - std::cout << "number of vertices=" << dt.number_of_vertices() << std::endl; - std::cout << "number of full cells=" << dt.number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << dt.number_of_finite_full_cells() << std::endl; -#endif // DEBUG_TRACES - init(dt); - } - - template - Alpha_shapes(T& triangulation) { - init(triangulation); - } - - ~Alpha_shapes() { } - - private: - - template - void init(T& triangulation) { - st_.set_dimension(triangulation.maximal_dimension()); - - // -------------------------------------------------------------------------------------------- - // bimap to retrieve vertex handles from points and vice versa - typedef boost::bimap< Kernel::Point_d, Vertex_handle > bimap_points_vh; - bimap_points_vh points_to_vh; - // Start to insert at handle = 0 - default integer value - Vertex_handle vertex_handle = Vertex_handle(); - // Loop on triangulation vertices list - for (auto vit = triangulation.vertices_begin(); vit != triangulation.vertices_end(); ++vit) { - points_to_vh.insert(bimap_points_vh::value_type(vit->point(), vertex_handle)); - vertex_handle++; - } - // -------------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------------- - // Simplex_tree construction from loop on triangulation finite full cells list - for (auto cit = triangulation.finite_full_cells_begin(); cit != triangulation.finite_full_cells_end(); ++cit) { - typeVectorVertex vertexVector; -#ifdef DEBUG_TRACES - std::cout << "Simplex_tree insertion "; -#endif // DEBUG_TRACES - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { -#ifdef DEBUG_TRACES - std::cout << " " << points_to_vh.left.at((*vit)->point()); -#endif // DEBUG_TRACES - // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(points_to_vh.left.at((*vit)->point())); - } -#ifdef DEBUG_TRACES - std::cout << std::endl; -#endif // DEBUG_TRACES - // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - Simplex_result insert_result = st_.insert_simplex_and_subfaces(vertexVector, - std::numeric_limits::quiet_NaN()); - if (!insert_result.second) { - std::cerr << "Alpha_shapes::init insert_simplex_and_subfaces failed" << std::endl; - } - } - // -------------------------------------------------------------------------------------------- - - Filtration_value filtration_max = 0.0; - - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); - // -------------------------------------------------------------------------------------------- - // ### For i : d -> 0 - for (int decr_dim = st_.dimension(); decr_dim >= 0; decr_dim--) { - // ### Foreach Sigma of dim i - for (auto f_simplex : st_.skeleton_simplex_range(decr_dim)) { - int f_simplex_dim = st_.dimension(f_simplex); - if (decr_dim == f_simplex_dim) { - typeVectorPoint pointVector; -#ifdef DEBUG_TRACES - std::cout << "Sigma of dim " << decr_dim << " is"; -#endif // DEBUG_TRACES - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { - pointVector.push_back(points_to_vh.right.at(vertex)); -#ifdef DEBUG_TRACES - std::cout << " " << vertex; -#endif // DEBUG_TRACES - } -#ifdef DEBUG_TRACES - std::cout << std::endl; -#endif // DEBUG_TRACES - // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (isnan(st_.filtration(f_simplex))) { - Filtration_value alpha_shapes_filtration = 0.0; - // No need to compute squared_radius on a single point - alpha is 0.0 - if (f_simplex_dim > 0) { - alpha_shapes_filtration = squared_radius(pointVector.begin(), pointVector.end()); - } - st_.assign_filtration(f_simplex, alpha_shapes_filtration); - filtration_max = fmax(filtration_max, alpha_shapes_filtration); -#ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; -#endif // DEBUG_TRACES - } - - // ### Foreach Tau face of Sigma - for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { -#ifdef DEBUG_TRACES - std::cout << " | --------------------------------------------------" << std::endl; - std::cout << " | Tau "; - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { - std::cout << vertex << " "; - } - std::cout << "is a face of Sigma" << std::endl; -#endif // DEBUG_TRACES - // insert the Tau points in a vector for is_gabriel function - typeVectorPoint pointVector; - Vertex_handle vertexForGabriel = Vertex_handle(); - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { - pointVector.push_back(points_to_vh.right.at(vertex)); - } - // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { - if (std::find(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertex)) == pointVector.end()) { - // vertex is not found in Tau - vertexForGabriel = vertex; - // No need to continue loop - break; - } - } -#ifdef DEBUG_TRACES - std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; - bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) - != CGAL::ON_BOUNDED_SIDE; - std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; -#endif // DEBUG_TRACES - // ### If filt(Tau) is not NaN - // ### or Tau is not Gabriel of Sigma - if (!isnan(st_.filtration(f_boundary)) || - (is_gabriel(pointVector.begin(), pointVector.end(), points_to_vh.right.at(vertexForGabriel)) == CGAL::ON_BOUNDED_SIDE) - ) { - // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) - Filtration_value alpha_shapes_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); - st_.assign_filtration(f_boundary, alpha_shapes_filtration); - filtration_max = fmax(filtration_max, alpha_shapes_filtration); -#ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; -#endif // DEBUG_TRACES - } - } - } - } - } - // -------------------------------------------------------------------------------------------- - -#ifdef DEBUG_TRACES - std::cout << "filtration_max=" << filtration_max << std::endl; -#endif // DEBUG_TRACES - st_.set_filtration(filtration_max); - } - - public: - - /** \brief Returns the number of vertices in the complex. */ - size_t num_vertices() { - return st_.num_vertices(); - } - - /** \brief Returns the number of simplices in the complex. - * - * Does not count the empty simplex. */ - const unsigned int& num_simplices() const { - return st_.num_simplices(); - } - - /** \brief Returns an upper bound on the dimension of the simplicial complex. */ - int dimension() { - return st_.dimension(); - } - - /** \brief Returns an upper bound of the filtration values of the simplices. */ - Filtration_value filtration() { - return st_.filtration(); - } - - friend std::ostream& operator<<(std::ostream& os, const Alpha_shapes & alpha_shape) { - // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor - Gudhi::Simplex_tree<> st = alpha_shape.st_; - os << st << std::endl; - return os; - } -}; - -} // namespace alphashapes - -} // namespace Gudhi - -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ diff --git a/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h index a4e5e2fe..8bda23b7 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ b/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h @@ -31,20 +31,22 @@ namespace Gudhi { -namespace alphashapes { +namespace alphacomplex { /** *@brief Off reader visitor with flag that can be passed to Off_reader to read a Delaunay_triangulation_complex. */ template class Delaunay_triangulation_off_visitor_reader { - Complex& complex_; + private: + Complex* _complex; typedef typename Complex::Point Point; public: - explicit Delaunay_triangulation_off_visitor_reader(Complex& complex) : - complex_(complex) { } + // Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. + Delaunay_triangulation_off_visitor_reader(Complex* _complex_ptr) + : _complex(nullptr) { } void init(int dim, int num_vertices, int num_faces, int num_edges) { #ifdef DEBUG_TRACES @@ -59,7 +61,8 @@ class Delaunay_triangulation_off_visitor_reader { std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << "file for Delaunay triangulation - edges are computed." << std::endl; } - //complex_.set_current_dimension(dim); + // Complex construction with dimension from file + _complex = new Complex(dim); } void point(const std::vector& point) { @@ -70,7 +73,7 @@ class Delaunay_triangulation_off_visitor_reader { } std::cout << std::endl; #endif // DEBUG_TRACES - complex_.insert(Point(point.size(), point.begin(), point.end())); + _complex->insert(Point(point.size(), point.begin(), point.end())); } void maximal_face(const std::vector& face) { @@ -89,6 +92,10 @@ class Delaunay_triangulation_off_visitor_reader { std::cout << "Delaunay_triangulation_off_visitor_reader::done" << std::endl; #endif // DEBUG_TRACES } + + Complex* get_complex() { + return _complex; + } }; /** @@ -103,12 +110,15 @@ class Delaunay_triangulation_off_reader { * read_complex : complex that will receive the file content * read_only_points : specify true if only the points must be read */ - Delaunay_triangulation_off_reader(const std::string & name_file, Complex& read_complex) : valid_(false) { + Delaunay_triangulation_off_reader(const std::string & name_file) : valid_(false) { std::ifstream stream(name_file); if (stream.is_open()) { - Delaunay_triangulation_off_visitor_reader off_visitor(read_complex); + Delaunay_triangulation_off_visitor_reader off_visitor(_complex); Off_reader off_reader(stream); valid_ = off_reader.read(off_visitor); + if (valid_) { + _complex = off_visitor.get_complex(); + } } else { std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << name_file << std::endl; @@ -123,8 +133,16 @@ class Delaunay_triangulation_off_reader { return valid_; } + Complex* get_complex() { + if (valid_) + return _complex; + return nullptr; + + } + private: bool valid_; + Complex* _complex; }; template @@ -137,20 +155,20 @@ class Delaunay_triangulation_off_writer { * save_complex : complex that be outputted in the file * for now only save triangles. */ - Delaunay_triangulation_off_writer(const std::string & name_file, const Complex& save_complex) { + Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) { std::ofstream stream(name_file); if (stream.is_open()) { - if (save_complex.current_dimension() == 3) { + if (complex_ptr->current_dimension() == 3) { // OFF header stream << "OFF" << std::endl; // no endl on next line - don't know why... - stream << save_complex.number_of_vertices() << " " << save_complex.number_of_finite_full_cells() << " 0"; + stream << complex_ptr->number_of_vertices() << " " << complex_ptr->number_of_finite_full_cells() << " 0"; } else { // nOFF header stream << "nOFF" << std::endl; // no endl on next line - don't know why... - stream << save_complex.current_dimension() << " " << save_complex.number_of_vertices() << " " << - save_complex.number_of_finite_full_cells() << " 0"; + stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << + complex_ptr->number_of_finite_full_cells() << " 0"; } @@ -160,7 +178,7 @@ class Delaunay_triangulation_off_writer { int vertex_handle = int(); // Points list - for (auto vit = save_complex.vertices_begin(); vit != save_complex.vertices_end(); ++vit) { + for (auto vit = complex_ptr->vertices_begin(); vit != complex_ptr->vertices_end(); ++vit) { for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { stream << *Coord << " "; } @@ -169,7 +187,7 @@ class Delaunay_triangulation_off_writer { vertex_handle++; } - for (auto cit = save_complex.finite_full_cells_begin(); cit != save_complex.finite_full_cells_end(); ++cit) { + for (auto cit = complex_ptr->finite_full_cells_begin(); cit != complex_ptr->finite_full_cells_end(); ++cit) { std::vector vertexVector; stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { @@ -185,7 +203,7 @@ class Delaunay_triangulation_off_writer { } }; -} // namespace alphashapes +} // namespace alphacomplex } // namespace Gudhi diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp new file mode 100644 index 00000000..38168f10 --- /dev/null +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -0,0 +1,126 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define BOOST_TEST_MODULE alpha_complex +#include +#include +#include +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" + +// to construct a simplex_tree from Delaunay_triangulation +#include "gudhi/graph_simplicial_complex.h" +#include "gudhi/Simplex_tree.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; +typedef CGAL::Delaunay_triangulation T; +// The triangulation uses the default instantiation of the +// TriangulationDataStructure template parameter + +BOOST_AUTO_TEST_CASE( OFF_file ) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-complex from a OFF file + // + // ---------------------------------------------------------------------------- + std::string off_file_name("S4_100.off"); + std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + + const int DIMENSION = 4; + std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); + + const double FILTRATION = 0.0; + std::cout << "alpha_complex_from_file.filtration()=" << alpha_complex_from_file.filtration() << std::endl; + BOOST_CHECK(alpha_complex_from_file.filtration() == FILTRATION); + + const int NUMBER_OF_VERTICES = 100; + std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 6779; + std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + +} + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-complex from a Delaunay triangulation + // + // ---------------------------------------------------------------------------- + T dt; + std::string off_file_name("S8_10.off"); + std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + + Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); + std::cout << "off_reader.is_valid()=" << off_reader.is_valid() << std::endl; + BOOST_CHECK(off_reader.is_valid()); + + const int NUMBER_OF_VERTICES = 10; + std::cout << "dt.number_of_vertices()=" << dt.number_of_vertices() << std::endl; + BOOST_CHECK(dt.number_of_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_FULL_CELLS = 30; + std::cout << "dt.number_of_full_cells()=" << dt.number_of_full_cells() << std::endl; + BOOST_CHECK(dt.number_of_full_cells() == NUMBER_OF_FULL_CELLS); + + const int NUMBER_OF_FINITE_FULL_CELLS = 6; + std::cout << "dt.number_of_finite_full_cells()=" << dt.number_of_finite_full_cells() << std::endl; + BOOST_CHECK(dt.number_of_finite_full_cells() == NUMBER_OF_FINITE_FULL_CELLS); + + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_dt(dt); + + const int DIMENSION = 8; + std::cout << "alpha_complex_from_dt.dimension()=" << alpha_complex_from_dt.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_dt.dimension() == DIMENSION); + + const double FILTRATION = 0.0; + std::cout << "alpha_complex_from_dt.filtration()=" << alpha_complex_from_dt.filtration() << std::endl; + BOOST_CHECK(alpha_complex_from_dt.filtration() == FILTRATION); + + std::cout << "alpha_complex_from_dt.num_vertices()=" << alpha_complex_from_dt.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_dt.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 997; + std::cout << "alpha_complex_from_dt.num_simplices()=" << alpha_complex_from_dt.num_simplices() << std::endl; + BOOST_CHECK(alpha_complex_from_dt.num_simplices() == NUMBER_OF_SIMPLICES); +} + diff --git a/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp b/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp deleted file mode 100644 index d5db3bfa..00000000 --- a/src/Alpha_complex/test/Alpha_shapes_unit_test.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2015 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#define BOOST_TEST_MODULE alpha_shapes -#include -#include -#include -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_shapes.h" - -// to construct a simplex_tree from Delaunay_triangulation -#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Simplex_tree.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instanciation of the -// TriangulationDataStructure template parameter - -BOOST_AUTO_TEST_CASE( OFF_file ) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a OFF file - // - // ---------------------------------------------------------------------------- - std::string off_file_name("S4_100.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_file(off_file_name, 4); - - const int DIMENSION = 4; - std::cout << "alpha_shapes_from_file.dimension()=" << alpha_shapes_from_file.dimension() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_shapes_from_file.filtration()=" << alpha_shapes_from_file.filtration() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.filtration() == FILTRATION); - - const int NUMBER_OF_VERTICES = 100; - std::cout << "alpha_shapes_from_file.num_vertices()=" << alpha_shapes_from_file.num_vertices() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.num_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_SIMPLICES = 6779; - std::cout << "alpha_shapes_from_file.num_simplices()=" << alpha_shapes_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_shapes_from_file.num_simplices() == NUMBER_OF_SIMPLICES); - -} - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { - // ---------------------------------------------------------------------------- - // - // Init of an alpha-shape from a Delauny triangulation - // - // ---------------------------------------------------------------------------- - T dt(8); - std::string off_file_name("S8_10.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - - Gudhi::alphashapes::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); - std::cout << "off_reader.is_valid()=" << off_reader.is_valid() << std::endl; - BOOST_CHECK(off_reader.is_valid()); - - const int NUMBER_OF_VERTICES = 10; - std::cout << "dt.number_of_vertices()=" << dt.number_of_vertices() << std::endl; - BOOST_CHECK(dt.number_of_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_FULL_CELLS = 30; - std::cout << "dt.number_of_full_cells()=" << dt.number_of_full_cells() << std::endl; - BOOST_CHECK(dt.number_of_full_cells() == NUMBER_OF_FULL_CELLS); - - const int NUMBER_OF_FINITE_FULL_CELLS = 6; - std::cout << "dt.number_of_finite_full_cells()=" << dt.number_of_finite_full_cells() << std::endl; - BOOST_CHECK(dt.number_of_finite_full_cells() == NUMBER_OF_FINITE_FULL_CELLS); - - Gudhi::alphashapes::Alpha_shapes alpha_shapes_from_dt(dt); - - const int DIMENSION = 8; - std::cout << "alpha_shapes_from_dt.dimension()=" << alpha_shapes_from_dt.dimension() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_shapes_from_dt.filtration()=" << alpha_shapes_from_dt.filtration() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.filtration() == FILTRATION); - - std::cout << "alpha_shapes_from_dt.num_vertices()=" << alpha_shapes_from_dt.num_vertices() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.num_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_SIMPLICES = 997; - std::cout << "alpha_shapes_from_dt.num_simplices()=" << alpha_shapes_from_dt.num_simplices() << std::endl; - BOOST_CHECK(alpha_shapes_from_dt.num_simplices() == NUMBER_OF_SIMPLICES); -} - diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 3cf97b71..72e8390a 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.6) -project(GUDHIAlphaShapesTest) +project(GUDHIAlphaComplexTest) # need CGAL 4.7 # cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. @@ -16,16 +16,16 @@ if(CGAL_FOUND) include_directories (BEFORE "../../include") add_definitions(-DDEBUG_TRACES) - add_executable ( AlphaShapesUnitTest Alpha_shapes_unit_test.cpp ) - target_link_libraries(AlphaShapesUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - add_test(AlphaShapesUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaShapesUnitTest) + add_executable ( AlphaComplexUnitTest Alpha_complex_unit_test.cpp ) + target_link_libraries(AlphaComplexUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_test(AlphaComplexUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUnitTest) else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha complex feature.") endif() else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha complex feature. Version 4.6.0 is required.") endif () endif() -cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/Alpha_shapes/include/gudhi") +cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/Alpha_complex/include/gudhi") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ceb993fa..e0d5ff28 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,7 +37,7 @@ else() add_subdirectory(example/Skeleton_blocker) add_subdirectory(example/Contraction) add_subdirectory(example/Hasse_complex) - add_subdirectory(example/Alpha_shapes) + add_subdirectory(example/Alpha_complex) add_subdirectory(example/Bottleneck) endif() -- cgit v1.2.3 From 56e89b6b7666dec86a70f6a30f08ef8b7960eb21 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 Jun 2015 14:21:31 +0000 Subject: Moved alphashapedoc.off in data/points Moved Delaunay triangulation OFF files read and write in src/common Delaunay triangulation OFF files read and write documentation, examples and tests git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@623 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e03902736a79436e97dbf77a88504f3faa8bd9c6 --- CMakeLists.txt | 9 +- data/points/alphashapedoc.off | 10 + src/Alpha_complex/example/CMakeLists.txt | 9 +- .../example/Delaunay_triangulation_off_rw.cpp | 79 ------ .../Simplex_tree_from_delaunay_triangulation.cpp | 27 +- src/Alpha_complex/example/alphashapedoc.off | 10 - src/Alpha_complex/include/gudhi/Alpha_complex.h | 70 +++-- .../Alpha_shapes/Delaunay_triangulation_off_io.h | 210 -------------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 71 ++--- src/Alpha_complex/test/CMakeLists.txt | 2 +- src/Alpha_complex/test/README | 2 +- src/Alpha_complex/test/S4_100.off | 4 +- src/Alpha_complex/test/S8_10.off | 4 +- src/CMakeLists.txt | 1 + src/Doxyfile | 3 +- src/common/example/CMakeLists.txt | 26 ++ .../example/Delaunay_triangulation_off_rw.cpp | 55 ++++ .../include/gudhi/Delaunay_triangulation_off_io.h | 308 +++++++++++++++++++++ src/common/include/gudhi/Off_reader.h | 291 ++++++++++--------- src/common/test/CMakeLists.txt | 44 +++ src/common/test/README | 14 + src/common/test/dtoffrw_alphashapedoc_result.off | 15 + src/common/test/dtoffrw_alphashapedoc_result.txt | 3 + src/common/test/dtoffrw_unit_test.cpp | 91 ++++++ 24 files changed, 790 insertions(+), 568 deletions(-) create mode 100755 data/points/alphashapedoc.off delete mode 100644 src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp delete mode 100755 src/Alpha_complex/example/alphashapedoc.off delete mode 100644 src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h create mode 100644 src/common/example/CMakeLists.txt create mode 100644 src/common/example/Delaunay_triangulation_off_rw.cpp create mode 100644 src/common/include/gudhi/Delaunay_triangulation_off_io.h create mode 100644 src/common/test/CMakeLists.txt create mode 100644 src/common/test/README create mode 100644 src/common/test/dtoffrw_alphashapedoc_result.off create mode 100644 src/common/test/dtoffrw_alphashapedoc_result.txt create mode 100644 src/common/test/dtoffrw_unit_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 01108db9..86b4e2b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,11 @@ if (PYTHON_PATH) message("python found in ${PYTHON_PATH}") endif() +FIND_PROGRAM( DIFF_PATH diff ) +if (DIFF_PATH) + message("diff found in ${DIFF_PATH}") +endif() + # Function to add_test cpplint on each header file of the Gudhi module function(cpplint_add_tests the_directory) if (PYTHON_PATH) @@ -77,9 +82,11 @@ else() include_directories(src/Simplex_tree/include/) include_directories(src/Skeleton_blocker/include/) + add_subdirectory(src/common/example) + add_subdirectory(src/common/test) add_subdirectory(src/Simplex_tree/test) add_subdirectory(src/Simplex_tree/example) - add_subdirectory(src/Persistent_cohomology/test) + #add_subdirectory(src/Persistent_cohomology/test) add_subdirectory(src/Persistent_cohomology/example) add_subdirectory(src/Skeleton_blocker/test) add_subdirectory(src/Skeleton_blocker/example) diff --git a/data/points/alphashapedoc.off b/data/points/alphashapedoc.off new file mode 100755 index 00000000..bb790193 --- /dev/null +++ b/data/points/alphashapedoc.off @@ -0,0 +1,10 @@ +nOFF +2 7 0 0 +1.0 1.0 +7.0 0.0 +4.0 6.0 +9.0 6.0 +0.0 14.0 +2.0 19.0 +9.0 17.0 + diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 258def49..9129fdcf 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -14,17 +14,10 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - add_definitions(-DDEBUG_TRACES) - - add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) - target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(dtoffrw_tore3D ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off 3) - + #add_definitions(-DDEBUG_TRACES) add_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_executable ( template_off template_off.cpp ) - target_link_libraries(template_off ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp b/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp deleted file mode 100644 index 405b3cb9..00000000 --- a/src/Alpha_complex/example/Delaunay_triangulation_off_rw.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2014 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instanciation of the -// TriangulationDataStructure template parameter - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " inputFile.off dimension outputFile.off" << std::endl; - exit(-1); // ----- >> -} - -int main(int argc, char **argv) { - if (argc != 4) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - int dimension = 0; - int returnedScanValue = sscanf(argv[2], "%d", &dimension); - if ((returnedScanValue == EOF) || (dimension <= 0)) { - std::cerr << "Error: " << argv[2] << " is not correct" << std::endl; - usage(argv[0]); - } - - T dt(dimension); - std::string offFileName(argv[1]); - Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(offFileName, dt); - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << offFileName << std::endl; - exit(-1); // ----- >> - } - - std::cout << "number_of_finite_full_cells= " << dt.number_of_finite_full_cells() << std::endl; - - std::string outFileName(argv[3]); - std::string offOutputFile(outFileName); - Gudhi::alphacomplex::Delaunay_triangulation_off_writer off_writer(offOutputFile, dt); - - return 0; -} \ No newline at end of file diff --git a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp index f09e6121..1523372a 100644 --- a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -21,19 +21,13 @@ */ // to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" +#include "gudhi/Delaunay_triangulation_off_io.h" #include "gudhi/Alpha_complex.h" // to construct a simplex_tree from Delaunay_triangulation #include "gudhi/graph_simplicial_complex.h" #include "gudhi/Simplex_tree.h" -#include -#include -#include -#include -#include - #include #include @@ -41,12 +35,6 @@ #include #include -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instanciation of the -// TriangulationDataStructure template parameter - void usage(char * const progName) { std::cerr << "Usage: " << progName << " filename.off" << std::endl; exit(-1); // ----- >> @@ -62,7 +50,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // - // Init of an alpha-complex from a OFF file + // Init of an alpha-complex from an OFF file // // ---------------------------------------------------------------------------- Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); @@ -71,7 +59,14 @@ int main(int argc, char **argv) { std::cout << "alpha_complex_from_file.filtration()=" << alpha_complex_from_file.filtration() << std::endl; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; - std::cout << alpha_complex_from_file << std::endl; - + + std::cout << "Iterator on Simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + std::cout << " " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; + for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + } return 0; } \ No newline at end of file diff --git a/src/Alpha_complex/example/alphashapedoc.off b/src/Alpha_complex/example/alphashapedoc.off deleted file mode 100755 index bb790193..00000000 --- a/src/Alpha_complex/example/alphashapedoc.off +++ /dev/null @@ -1,10 +0,0 @@ -nOFF -2 7 0 0 -1.0 1.0 -7.0 0.0 -4.0 6.0 -9.0 6.0 -0.0 14.0 -2.0 19.0 -9.0 17.0 - diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index ca84d6d9..d25c05cb 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -23,9 +23,6 @@ #ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ #define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ -// to construct a Delaunay_triangulation from a OFF file -#include - // to construct a simplex_tree from Delaunay_triangulation #include #include @@ -46,8 +43,7 @@ #include #include #include -#include -#include +#include // NaN namespace Gudhi { @@ -82,59 +78,59 @@ class Alpha_complex { private: // From Simplex_tree /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ - typedef std::vector typeVectorVertex; + typedef std::vector Vector_vertex; + /** \brief Simplex_handle type from simplex_tree.*/ typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; + /** \brief Simplex_result is the type returned from simplex_tree insert function.*/ typedef typename std::pair Simplex_result; + /** \brief Filtration_simplex_range type from simplex_tree.*/ + typedef typename Gudhi::Simplex_tree<>::Filtration_simplex_range Filtration_simplex_range; + + /** \brief Simplex_vertex_range type from simplex_tree.*/ + typedef typename Gudhi::Simplex_tree<>::Simplex_vertex_range Simplex_vertex_range; + // From CGAL - /** \brief Kernel for the Delaunay_triangulation-> - * Dimension can be set dynamically. - */ + /** \brief Kernel for the Delaunay_triangulation. Dimension can be set dynamically.*/ typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - /** \brief Delaunay_triangulation type required to create an alpha-complex. - */ + /** \brief Delaunay_triangulation type required to create an alpha-complex.*/ typedef CGAL::Delaunay_triangulation Delaunay_triangulation; typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; - /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + /** \brief Type required to compute squared radius, or side of bounded sphere on a vector of points.*/ typedef std::vector Vector_of_CGAL_points; + /** \brief Vertex_iterator type from CGAL.*/ typedef Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; + /** \brief Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; private: - /** \brief Upper bound on the simplex tree of the simplicial complex.*/ + /** \brief Alpha complex is represented internally by a simplex tree.*/ Gudhi::Simplex_tree<> st_; + /** \brief Boost bimap to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ Bimap_vertex cgal_simplextree; + /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation; public: - Alpha_complex(std::string& off_file_name) : triangulation(nullptr) { -#ifdef DEBUG_TRACES - char buffer[256]={0}; - sprintf(buffer,"%p", triangulation); - std::cout << "pointer=" << buffer << std::endl; -#endif // DEBUG_TRACES - Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(off_file_name); + Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << off_file_name << std::endl; exit(-1); // ----- >> } triangulation = off_reader.get_complex(); -#ifdef DEBUG_TRACES - //char buffer[256]={0}; - sprintf(buffer,"%p", triangulation); - std::cout << "pointer=" << buffer << std::endl; - std::cout << "number of vertices=" << triangulation->number_of_vertices() << std::endl; - std::cout << "number of full cells=" << triangulation->number_of_full_cells() << std::endl; - std::cout << "number of finite full cells=" << triangulation->number_of_finite_full_cells() << std::endl; -#endif // DEBUG_TRACES + init(); + } + + Alpha_complex(Delaunay_triangulation* triangulation_ptr) + : triangulation(triangulation_ptr) { init(); } @@ -142,6 +138,21 @@ class Alpha_complex { delete triangulation; } + Filtration_simplex_range filtration_simplex_range() { + return st_.filtration_simplex_range(); + } + + Simplex_vertex_range simplex_vertex_range(Simplex_handle sh) { + return st_.simplex_vertex_range(sh); + } + + /** \brief Returns the filtration value of a simplex. + * + * Called on the null_simplex, returns INFINITY. */ + Gudhi::Simplex_tree<>::Filtration_value filtration(Simplex_handle sh) { + return st_.filtration(sh); + } + private: void init() { @@ -161,7 +172,7 @@ class Alpha_complex { // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation->finite_full_cells_begin(); cit != triangulation->finite_full_cells_end(); ++cit) { - typeVectorVertex vertexVector; + Vector_vertex vertexVector; #ifdef DEBUG_TRACES std::cout << "Simplex_tree insertion "; #endif // DEBUG_TRACES @@ -325,7 +336,6 @@ class Alpha_complex { } friend std::ostream& operator<<(std::ostream& os, const Alpha_complex & alpha_complex) { - // TODO: Program terminated with signal SIGABRT, Aborted - Maybe because of copy constructor Gudhi::Simplex_tree<> st = alpha_complex.st_; os << st << std::endl; return os; diff --git a/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h b/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h deleted file mode 100644 index 8bda23b7..00000000 --- a/src/Alpha_complex/include/gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h +++ /dev/null @@ -1,210 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2015 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ -#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ - -#include -#include -#include -#include - -#include "gudhi/Off_reader.h" - -namespace Gudhi { - -namespace alphacomplex { - -/** - *@brief Off reader visitor with flag that can be passed to Off_reader to read a Delaunay_triangulation_complex. - */ -template -class Delaunay_triangulation_off_visitor_reader { - private: - Complex* _complex; - typedef typename Complex::Point Point; - - public: - - // Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. - Delaunay_triangulation_off_visitor_reader(Complex* _complex_ptr) - : _complex(nullptr) { } - - void init(int dim, int num_vertices, int num_faces, int num_edges) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << - num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; -#endif // DEBUG_TRACES - if (num_faces > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << - "file for Delaunay triangulation - faces are computed." << std::endl; - } - if (num_edges > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << - "file for Delaunay triangulation - edges are computed." << std::endl; - } - // Complex construction with dimension from file - _complex = new Complex(dim); - } - - void point(const std::vector& point) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::point "; - for (auto coordinate : point) { - std::cout << coordinate << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES - _complex->insert(Point(point.size(), point.begin(), point.end())); - } - - void maximal_face(const std::vector& face) { - // For Delaunay Triangulation, only points are read -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::face "; - for (auto vertex : face) { - std::cout << vertex << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES - } - - void done() { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::done" << std::endl; -#endif // DEBUG_TRACES - } - - Complex* get_complex() { - return _complex; - } -}; - -/** - *@brief Class that allows to load a Delaunay_triangulation_complex from an off file. - */ -template -class Delaunay_triangulation_off_reader { - public: - - /** - * name_file : file to read - * read_complex : complex that will receive the file content - * read_only_points : specify true if only the points must be read - */ - Delaunay_triangulation_off_reader(const std::string & name_file) : valid_(false) { - std::ifstream stream(name_file); - if (stream.is_open()) { - Delaunay_triangulation_off_visitor_reader off_visitor(_complex); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - if (valid_) { - _complex = off_visitor.get_complex(); - } - } else { - std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << - name_file << std::endl; - } - - } - - /** - * return true if reading did not meet problems. - */ - bool is_valid() const { - return valid_; - } - - Complex* get_complex() { - if (valid_) - return _complex; - return nullptr; - - } - - private: - bool valid_; - Complex* _complex; -}; - -template -class Delaunay_triangulation_off_writer { - public: - typedef typename Complex::Point Point; - - /** - * name_file : file where the off will be written - * save_complex : complex that be outputted in the file - * for now only save triangles. - */ - Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) { - std::ofstream stream(name_file); - if (stream.is_open()) { - if (complex_ptr->current_dimension() == 3) { - // OFF header - stream << "OFF" << std::endl; - // no endl on next line - don't know why... - stream << complex_ptr->number_of_vertices() << " " << complex_ptr->number_of_finite_full_cells() << " 0"; - } else { - // nOFF header - stream << "nOFF" << std::endl; - // no endl on next line - don't know why... - stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << - complex_ptr->number_of_finite_full_cells() << " 0"; - - } - - // bimap to retrieve vertex handles from points and vice versa - std::map< Point, int > points_to_vh; - // Start to insert at default handle value - int vertex_handle = int(); - - // Points list - for (auto vit = complex_ptr->vertices_begin(); vit != complex_ptr->vertices_end(); ++vit) { - for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { - stream << *Coord << " "; - } - stream << std::endl; - points_to_vh[vit->point()] = vertex_handle; - vertex_handle++; - } - - for (auto cit = complex_ptr->finite_full_cells_begin(); cit != complex_ptr->finite_full_cells_end(); ++cit) { - std::vector vertexVector; - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - stream << points_to_vh[(*vit)->point()] << " "; - } - stream << std::endl; - } - stream.close(); - } else { - std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << - name_file << std::endl; - } - } -}; - -} // namespace alphacomplex - -} // namespace Gudhi - -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 38168f10..86d4d9c3 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -25,25 +25,10 @@ #include #include // to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Alpha_shapes/Delaunay_triangulation_off_io.h" +#include "gudhi/Delaunay_triangulation_off_io.h" #include "gudhi/Alpha_complex.h" -// to construct a simplex_tree from Delaunay_triangulation -#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Simplex_tree.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include +#include // float comparison // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; @@ -51,7 +36,7 @@ typedef CGAL::Delaunay_triangulation T; // The triangulation uses the default instantiation of the // TriangulationDataStructure template parameter -BOOST_AUTO_TEST_CASE( OFF_file ) { +BOOST_AUTO_TEST_CASE( S4_100_OFF_file ) { // ---------------------------------------------------------------------------- // // Init of an alpha-complex from a OFF file @@ -66,61 +51,37 @@ BOOST_AUTO_TEST_CASE( OFF_file ) { std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - const double FILTRATION = 0.0; - std::cout << "alpha_complex_from_file.filtration()=" << alpha_complex_from_file.filtration() << std::endl; - BOOST_CHECK(alpha_complex_from_file.filtration() == FILTRATION); - const int NUMBER_OF_VERTICES = 100; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 6779; + const int NUMBER_OF_SIMPLICES = 6879; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); } -BOOST_AUTO_TEST_CASE( Delaunay_triangulation ) { +BOOST_AUTO_TEST_CASE( S8_10_OFF_file ) { // ---------------------------------------------------------------------------- // - // Init of an alpha-complex from a Delaunay triangulation + // Init of an alpha-complex from a OFF file // // ---------------------------------------------------------------------------- - T dt; std::string off_file_name("S8_10.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - Gudhi::alphacomplex::Delaunay_triangulation_off_reader off_reader(off_file_name, dt); - std::cout << "off_reader.is_valid()=" << off_reader.is_valid() << std::endl; - BOOST_CHECK(off_reader.is_valid()); - - const int NUMBER_OF_VERTICES = 10; - std::cout << "dt.number_of_vertices()=" << dt.number_of_vertices() << std::endl; - BOOST_CHECK(dt.number_of_vertices() == NUMBER_OF_VERTICES); - - const int NUMBER_OF_FULL_CELLS = 30; - std::cout << "dt.number_of_full_cells()=" << dt.number_of_full_cells() << std::endl; - BOOST_CHECK(dt.number_of_full_cells() == NUMBER_OF_FULL_CELLS); - - const int NUMBER_OF_FINITE_FULL_CELLS = 6; - std::cout << "dt.number_of_finite_full_cells()=" << dt.number_of_finite_full_cells() << std::endl; - BOOST_CHECK(dt.number_of_finite_full_cells() == NUMBER_OF_FINITE_FULL_CELLS); - - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_dt(dt); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 8; - std::cout << "alpha_complex_from_dt.dimension()=" << alpha_complex_from_dt.dimension() << std::endl; - BOOST_CHECK(alpha_complex_from_dt.dimension() == DIMENSION); - - const double FILTRATION = 0.0; - std::cout << "alpha_complex_from_dt.filtration()=" << alpha_complex_from_dt.filtration() << std::endl; - BOOST_CHECK(alpha_complex_from_dt.filtration() == FILTRATION); + std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - std::cout << "alpha_complex_from_dt.num_vertices()=" << alpha_complex_from_dt.num_vertices() << std::endl; - BOOST_CHECK(alpha_complex_from_dt.num_vertices() == NUMBER_OF_VERTICES); + const int NUMBER_OF_VERTICES = 10; + std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 997; - std::cout << "alpha_complex_from_dt.num_simplices()=" << alpha_complex_from_dt.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_dt.num_simplices() == NUMBER_OF_SIMPLICES); -} + const int NUMBER_OF_SIMPLICES = 1007; + std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); +} diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 72e8390a..4fe69ce5 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -15,7 +15,7 @@ if(CGAL_FOUND) include( ${EIGEN3_USE_FILE} ) include_directories (BEFORE "../../include") - add_definitions(-DDEBUG_TRACES) + #add_definitions(-DDEBUG_TRACES) add_executable ( AlphaComplexUnitTest Alpha_complex_unit_test.cpp ) target_link_libraries(AlphaComplexUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) add_test(AlphaComplexUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUnitTest) diff --git a/src/Alpha_complex/test/README b/src/Alpha_complex/test/README index 244a2b84..45b87d91 100644 --- a/src/Alpha_complex/test/README +++ b/src/Alpha_complex/test/README @@ -7,6 +7,6 @@ make To launch with details: *********************** -./AlphaShapesUnitTest --report_level=detailed --log_level=all +./AlphaComplexUnitTest --report_level=detailed --log_level=all ==> echo $? returns 0 in case of success (non-zero otherwise) diff --git a/src/Alpha_complex/test/S4_100.off b/src/Alpha_complex/test/S4_100.off index 0a5dc58c..cd017e12 100644 --- a/src/Alpha_complex/test/S4_100.off +++ b/src/Alpha_complex/test/S4_100.off @@ -1,5 +1,5 @@ -OFF -100 0 0 +nOFF +4 100 0 0 0.562921 -0.735261 -0.256472 0.277007 -0.803733 -0.0527915 -0.315125 0.501918 -0.24946 -0.354982 -0.410773 -0.801887 diff --git a/src/Alpha_complex/test/S8_10.off b/src/Alpha_complex/test/S8_10.off index 1d67e10f..4e147c44 100644 --- a/src/Alpha_complex/test/S8_10.off +++ b/src/Alpha_complex/test/S8_10.off @@ -1,5 +1,5 @@ -OFF -10 0 0 +nOFF +8 10 0 0 0.440036 -0.574754 -0.200485 0.216537 -0.501251 -0.0329236 -0.196529 0.313023 -0.129367 -0.184089 -0.213021 -0.415848 0.783529 -0.0438025 0.317256 0.120749 0.132429 0.683748 -0.124536 -0.166133 -0.540695 -0.0887576 0.390234 -0.139031 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e0d5ff28..e2271efd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,7 @@ else() LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) include_directories(include/) + add_subdirectory(example/common) add_subdirectory(example/Simplex_tree) add_subdirectory(example/Persistent_cohomology) add_subdirectory(example/Skeleton_blocker) diff --git a/src/Doxyfile b/src/Doxyfile index 62412627..9d4bc9c8 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -811,7 +811,8 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = +EXAMPLE_PATH = common/example \ + common/test # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt new file mode 100644 index 00000000..ae30da54 --- /dev/null +++ b/src/common/example/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIDelaunayTriangulationOffFileReadWrite) + +# need CGAL 4.6 +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + + add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) + target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(dtoffrw ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/alphashapedoc.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) + + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () +endif() diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp new file mode 100644 index 00000000..d1aa7988 --- /dev/null +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -0,0 +1,55 @@ +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" + +#include +#include + +#include +#include +#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; +typedef CGAL::Delaunay_triangulation T; +// The triangulation uses the default instantiation of the +// TriangulationDataStructure template parameter + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " inputFile.off outputFile.off" << std::endl; + exit(-1); // ----- >> +} + +int main(int argc, char **argv) { + if (argc != 3) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + std::string offInputFile(argv[1]); + // Read the OFF file (input file name given as parameter) and triangulates points + Gudhi::Delaunay_triangulation_off_reader off_reader(offInputFile); + // Check the read operation was correct + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << offInputFile << std::endl; + exit(-1); // ----- >> + } + + // Retrieve the triangulation + T* triangulation = off_reader.get_complex(); + // Operations on triangulation + std::cout << "Number of vertices= " << triangulation->number_of_vertices() << std::endl; + std::cout << "Number of finite full cells= " << triangulation->number_of_finite_full_cells() << std::endl; + + std::string outFileName(argv[2]); + std::string offOutputFile(outFileName); + // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces + Gudhi::Delaunay_triangulation_off_writer off_writer(offOutputFile, triangulation); + + // Check the write operation was correct + if (!off_writer.is_valid()) { + std::cerr << "Unable to write file " << offOutputFile << std::endl; + exit(-1); // ----- >> + } + + return 0; +} \ No newline at end of file diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h new file mode 100644 index 00000000..de5fa2af --- /dev/null +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -0,0 +1,308 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ +#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ + +#include +#include +#include +#include + +#include "gudhi/Off_reader.h" + +namespace Gudhi { + +/** \brief OFF file visitor implementation according to Off_reader in order to construct a CGAL Delaunay triangulation. + * + * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page + * http://doc.cgal.org/latest/Triangulation/ + */ +template +class Delaunay_triangulation_off_visitor_reader { + private: + Complex* _complex; + typedef typename Complex::Point Point; + + public: + + // TODO(VR) : Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. + + /** \brief Delaunay_triangulation_off_visitor_reader constructor + * + * @param[in] _complex_ptr pointer on a Delaunay triangulation. + */ + Delaunay_triangulation_off_visitor_reader(Complex* _complex_ptr) + : _complex(nullptr) { } + + /** \brief Off_reader visitor init implementation. + * + * The init parameters are set from OFF file header. + * Dimension value is required in order to construct Delaunay triangulation. + * + * @param[in] dim space dimension of vertices. + * @param[in] num_vertices number of vertices in the OFF file (not used). + * @param[in] num_faces number of faces in the OFF file (not used). + * @param[in] num_edges number of edges in the OFF file (not used). + */ + void init(int dim, int num_vertices, int num_faces, int num_edges) { +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; +#endif // DEBUG_TRACES + if (num_faces > 0) { + std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << + "file for Delaunay triangulation - faces are computed." << std::endl; + } + if (num_edges > 0) { + std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << + "file for Delaunay triangulation - edges are computed." << std::endl; + } + // Complex construction with dimension from file + _complex = new Complex(dim); + } + + /** \brief Off_reader visitor point implementation. + * + * The point function is called on each vertex line from OFF file. + * This function inserts the vertex in the Delaunay triangulation. + * + * @param[in] point vector of vertex coordinates. + */ + void point(const std::vector& point) { +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::point "; + for (auto coordinate : point) { + std::cout << coordinate << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + _complex->insert(Point(point.size(), point.begin(), point.end())); + } + + // Off_reader visitor maximal_face implementation - not used + void maximal_face(const std::vector& face) { + // For Delaunay Triangulation, only points are read + } + + // Off_reader visitor done implementation - not used + void done() { + // Nothing to be done on end of OFF file read + } + + /** \brief Returns the constructed Delaunay triangulation. + * + * @return A pointer on the Delaunay triangulation. + * + * @warning The returned pointer can be nullptr. + */ + Complex* get_complex() const { + return _complex; + } +}; + +/** \brief OFF file reader implementation in order to construct a Delaunay triangulation. + * + * This class is using the Delaunay_triangulation_off_visitor_reader to visit the OFF file according to Off_reader. + * + * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page + * http://doc.cgal.org/latest/Triangulation/ + * + * \section Example + * + * This example loads points from an OFF file and builds the Delaunay triangulation. + * Then, it is asked to display the number of vertices and finites full cells from the Delaunay triangulation. + * + * \include Delaunay_triangulation_off_rw.cpp + * + * When launching: + * + * \code $> ./dtoffrw ../../data/points/alphashapedoc.off triangulated.off + * \endcode + * + * the program output is: + * + * \include dtoffrw_alphashapedoc_result.txt + */ +template +class Delaunay_triangulation_off_reader { + public: + + /** \brief Reads the OFF file and constructs the Delaunay triangulation from the points + * that are in the OFF file. + * + * @param[in] name_file OFF file to read. + * + * @warning Check with is_valid() function to see if read operation was successful. + */ + Delaunay_triangulation_off_reader(const std::string & name_file) + : valid_(false) { + std::ifstream stream(name_file); + if (stream.is_open()) { + Delaunay_triangulation_off_visitor_reader off_visitor(_complex); + Off_reader off_reader(stream); + valid_ = off_reader.read(off_visitor); + if (valid_) { + _complex = off_visitor.get_complex(); + if (_complex == nullptr) { + std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader off_visitor returns an empty pointer" << std::endl; + valid_ = false; + } + } + } else { + std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << + name_file << std::endl; + } + + } + + /** \brief Returns if the OFF file read operation was successful or not. + * + * @return OFF file read status. + */ + bool is_valid() const { + return valid_; + } + + /** \brief Returns the constructed Delaunay triangulation. + * + * @return A pointer on the Delaunay triangulation. + * + * @warning The returned pointer can be nullptr. + */ + Complex* get_complex() const { + if (valid_) + return _complex; + return nullptr; + + } + + private: + /** \brief OFF file read status.*/ + bool valid_; + /** \brief A pointer on the Delaunay triangulation.*/ + Complex* _complex; +}; + +/** \brief OFF file writer from a Delaunay triangulation. + * + * This class constructs the OFF file header according to http://www.geomview.org/docs/html/OFF.html + * + * The header is followed by the list of points coordinates (Delaunay triangulation vertices) + * + * And finally is followed by the list of faces (Delaunay triangulation finite full cells) + * + * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page + * http://doc.cgal.org/latest/Triangulation/ + * + * \section Example + * + * This example loads points from an OFF file and builds the Delaunay triangulation. + * Then, the Delaunay triangulation is saved in a new file including the triangulation as a list of faces. + * + * \include Delaunay_triangulation_off_rw.cpp + * + * When launching: + * + * \code $> ./dtoffrw ../../data/points/alphashapedoc.off triangulated.off + * \endcode + * + * The result will be an OFF file of dimension 2 with the 7 points from alphashapedoc.off followed by the 6 + * triangulations of dimension 3 (the first value on each faces): + * \include dtoffrw_alphashapedoc_result.off + */ +template +class Delaunay_triangulation_off_writer { + public: + typedef typename Complex::Point Point; + + /** \brief Writes the OFF file from the Delaunay triangulation + * + * @param[in] name_file OFF file to write. + * @param[in] complex_ptr pointer on a Delaunay triangulation. + * + * @warning Check with is_valid() function to see if write operation was successful. + */ + Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) + : valid_(false) { + std::ofstream stream(name_file); + if (stream.is_open()) { + if (complex_ptr->current_dimension() == 3) { + // OFF header + stream << "OFF" << std::endl; + // no endl on next line - don't know why... + stream << complex_ptr->number_of_vertices() << " " << complex_ptr->number_of_finite_full_cells() << " 0"; + } else { + // nOFF header + stream << "nOFF" << std::endl; + // no endl on next line - don't know why... + stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << + complex_ptr->number_of_finite_full_cells() << " 0"; + + } + + // bimap to retrieve vertex handles from points and vice versa + std::map< Point, int > points_to_vh; + // Start to insert at default handle value + int vertex_handle = int(); + + // Points list + for (auto vit = complex_ptr->vertices_begin(); vit != complex_ptr->vertices_end(); ++vit) { + for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { + stream << *Coord << " "; + } + stream << std::endl; + points_to_vh[vit->point()] = vertex_handle; + vertex_handle++; + } + + for (auto cit = complex_ptr->finite_full_cells_begin(); cit != complex_ptr->finite_full_cells_end(); ++cit) { + std::vector vertexVector; + stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; + for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + stream << points_to_vh[(*vit)->point()] << " "; + } + stream << std::endl; + } + stream.close(); + valid_ = true; + } else { + std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << + name_file << std::endl; + } + } + + /** \brief Returns if the OFF write operation was successful or not. + * + * @return OFF file write status. + */ + bool is_valid() const { + return valid_; + } + + private: + /* \brief OFF file write status. */ + bool valid_; +}; + +} // namespace Gudhi + +#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index 618d1b4d..a8abb507 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -36,163 +36,150 @@ namespace Gudhi { -/** - * Read an off file and calls a visitor methods while reading it. - * An off file must have its first/snd line in this format : - * OFF - * num_vert num_faces num_edges - * - * A noff file must have its first/snd line in this format : - * nOFF - * dim num_vert num_faces num_edges - * - * The number of edges num_edges is optional and can be left to zero. +/** \brief OFF file reader top class visitor. + * + * OFF file must be conform to format described here : + * http://www.geomview.org/docs/html/OFF.html */ -class Off_reader{ -public: - Off_reader(std::ifstream& stream):stream_(stream){ - } -// Off_reader(const std::string& name):stream_(name){ -// if(!stream_.is_open()) -// std::cerr <<"could not open file \n"; -// } - - ~Off_reader(){ - stream_.close(); - } - - /** - * read an off file and calls the following methods : - * void init(int dim,int num_vertices,int num_faces,int num_edges); //num_edges may not be set - * void point(const std::vector& point); - * void maximal_face(const std::list& face); - * void done(); - * of the visitor when reading a point or a maximal face. - */ - template - bool read(OffVisitor& off_visitor){ - bool success_read_off_preambule = read_off_preambule(off_visitor); - if(!success_read_off_preambule) { - std::cerr <<"could not read off preambule\n"; - return false; - } - - bool success_read_off_points = read_off_points(off_visitor); - if(!success_read_off_points) { - std::cerr <<"could not read off points\n"; - return false; - } - - bool success_read_off_faces = read_off_faces(off_visitor); - if(!success_read_off_faces) { - std::cerr <<"could not read off faces\n"; - return false; - } - - off_visitor.done(); - return success_read_off_preambule && success_read_off_points && success_read_off_faces; - } - -private: - std::ifstream& stream_; - - struct Off_info{ - int dim; - int num_vertices; - int num_edges; - int num_faces; - }; - - Off_info off_info_; - - template - bool read_off_preambule(OffVisitor& off_visitor){ - std::string line; - if(!goto_next_uncomment_line(line)) return false; - - bool is_off_file = (line.find("OFF") != std::string::npos); - bool is_noff_file = (line.find("nOFF") != std::string::npos); - - if(!is_off_file && !is_noff_file) { - std::cerr << line<> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)){ - std::cerr << "incorrect number of vertices/faces/edges\n"; - return false; - } - } - else - if(!(iss >> off_info_.dim >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)){ - std::cerr << "incorrect number of vertices/faces/edges\n"; - return false; - } - off_visitor.init(off_info_.dim,off_info_.num_vertices,off_info_.num_faces,off_info_.num_edges); - - return true; - } - - bool goto_next_uncomment_line(std::string& uncomment_line){ - uncomment_line.clear(); - do - std::getline(stream_, uncomment_line); - while(uncomment_line[0] == '%');// || uncomment_line.empty()); - return (uncomment_line.size()>0 && uncomment_line[0] != '%'); - } - - - template - bool read_off_points(OffVisitor& visitor){ - int num_vertices_to_read = off_info_.num_vertices; - while(num_vertices_to_read--){ - std::string line; - if(!goto_next_uncomment_line(line)) return false; - std::vector point; - std::istringstream iss(line); - point.assign(std::istream_iterator(iss),std::istream_iterator()); -// if(point.size() != off_info_.dim) return false; - visitor.point(point); - } - return true; - } - - template - bool read_off_faces(OffVisitor& visitor){ - std::string line; - while(goto_next_uncomment_line(line)){ - std::istringstream iss(line); - int num_face_vertices; - iss >> num_face_vertices; - std::vector face; - face.assign(std::istream_iterator(iss),std::istream_iterator()); - if(!face.size() == off_info_.num_vertices) return false; - visitor.maximal_face(face); - } - return true; - } +class Off_reader { + public: + + Off_reader(std::ifstream& stream) : stream_(stream) { } + + ~Off_reader() { + stream_.close(); + } + + /** \brief + * Read an OFF file and calls the following methods : + * + * void init(int dim,int num_vertices,int num_faces,int num_edges); // from file header - num_edges may not be set + * + * void point(const std::vector& point); // for each point read + * + * void maximal_face(const std::list& face); // for each face read + * + * void done(); // upon file read is finished + * + * of the visitor when reading a point or a maximal face. Edges are not taken into account. + */ + template + bool read(OffVisitor& off_visitor) { + bool success_read_off_preambule = read_off_preambule(off_visitor); + if (!success_read_off_preambule) { + std::cerr << "could not read off preambule\n"; + return false; + } + + bool success_read_off_points = read_off_points(off_visitor); + if (!success_read_off_points) { + std::cerr << "could not read off points\n"; + return false; + } + + bool success_read_off_faces = read_off_faces(off_visitor); + if (!success_read_off_faces) { + std::cerr << "could not read off faces\n"; + return false; + } + + off_visitor.done(); + return success_read_off_preambule && success_read_off_points && success_read_off_faces; + } + + private: + std::ifstream& stream_; + + struct Off_info { + int dim; + int num_vertices; + int num_edges; + int num_faces; + }; + + Off_info off_info_; + + template + bool read_off_preambule(OffVisitor& off_visitor) { + std::string line; + if (!goto_next_uncomment_line(line)) return false; + + bool is_off_file = (line.find("OFF") != std::string::npos); + bool is_noff_file = (line.find("nOFF") != std::string::npos); + + if (!is_off_file && !is_noff_file) { + std::cerr << line << std::endl; + std::cerr << "missing off header\n"; + return false; + } + + if (!goto_next_uncomment_line(line)) return false; + std::istringstream iss(line); + if ((is_off_file) && (!is_noff_file)) { + off_info_.dim = 3; + if (!(iss >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) { + std::cerr << "incorrect number of vertices/faces/edges\n"; + return false; + } + } else + if (!(iss >> off_info_.dim >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) { + std::cerr << "incorrect number of vertices/faces/edges\n"; + return false; + } + off_visitor.init(off_info_.dim, off_info_.num_vertices, off_info_.num_faces, off_info_.num_edges); + + return true; + } + + bool goto_next_uncomment_line(std::string& uncomment_line) { + uncomment_line.clear(); + do + std::getline(stream_, uncomment_line); while (uncomment_line[0] == '%'); + return (uncomment_line.size() > 0 && uncomment_line[0] != '%'); + } + + template + bool read_off_points(OffVisitor& visitor) { + int num_vertices_to_read = off_info_.num_vertices; + while (num_vertices_to_read--) { + std::string line; + if (!goto_next_uncomment_line(line)) return false; + std::vector point; + std::istringstream iss(line); + point.assign(std::istream_iterator(iss), std::istream_iterator()); + // if(point.size() != off_info_.dim) return false; + visitor.point(point); + } + return true; + } + + template + bool read_off_faces(OffVisitor& visitor) { + std::string line; + while (goto_next_uncomment_line(line)) { + std::istringstream iss(line); + int num_face_vertices; + iss >> num_face_vertices; + std::vector face; + face.assign(std::istream_iterator(iss), std::istream_iterator()); + if (!face.size() == off_info_.num_vertices) return false; + visitor.maximal_face(face); + } + return true; + } }; - template -void read_off(const std::string& name_file_off,OFFVisitor& vis){ - std::ifstream stream(name_file_off); - if(!stream.is_open()) - std::cerr <<"could not open file \n"; - else{ - Off_reader off_reader(stream); - off_reader.read(vis); - } +void read_off(const std::string& name_file_off, OFFVisitor& vis) { + std::ifstream stream(name_file_off); + if (!stream.is_open()) + std::cerr << "could not open file \n"; + else { + Off_reader off_reader(stream); + off_reader.read(vis); + } } - - } // namespace Gudhi - -#endif /* GUDHI_OFF_READER_H_ */ +#endif // GUDHI_OFF_READER_H_ diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt new file mode 100644 index 00000000..22783caf --- /dev/null +++ b/src/common/test/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 2.6) +project(GUDHIDelaunayTriangulationOffFileReadWriteUT) + +if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} --coverage") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} --coverage") +endif() + +# need CGAL 4.6 +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + + add_executable ( dtoffrw_UT dtoffrw_unit_test.cpp ) + target_link_libraries(dtoffrw_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + + # Unitary tests + add_test(dtoffrw_UT ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_UT) + + if (DIFF_PATH) + add_test(diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) + endif() + + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () +endif() + + + + + +cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/common/include/gudhi") diff --git a/src/common/test/README b/src/common/test/README new file mode 100644 index 00000000..f2a7eb5a --- /dev/null +++ b/src/common/test/README @@ -0,0 +1,14 @@ +To compile: +*********** + +cmake . +make + +To launch with details: +*********************** + +./dtoffrw_UT --report_level=detailed --log_level=all + + ==> echo $? returns 0 in case of success (non-zero otherwise) + + diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off new file mode 100644 index 00000000..13c255c6 --- /dev/null +++ b/src/common/test/dtoffrw_alphashapedoc_result.off @@ -0,0 +1,15 @@ +nOFF +2 7 6 0 +1 1 +7 0 +4 6 +9 6 +0 14 +2 19 +9 17 +3 1 2 3 +3 4 3 2 +3 5 1 3 +3 5 3 7 +3 7 3 4 +3 6 5 7 diff --git a/src/common/test/dtoffrw_alphashapedoc_result.txt b/src/common/test/dtoffrw_alphashapedoc_result.txt new file mode 100644 index 00000000..57761d14 --- /dev/null +++ b/src/common/test/dtoffrw_alphashapedoc_result.txt @@ -0,0 +1,3 @@ +Number of vertices= 7 +Number of finite full cells= 6 + diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp new file mode 100644 index 00000000..4905d845 --- /dev/null +++ b/src/common/test/dtoffrw_unit_test.cpp @@ -0,0 +1,91 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define BOOST_TEST_MODULE DelaunayTriangulationOffFileReadWrite test + +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" + +#include +#include + +#include +#include +#include + +#include +#include +//#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; +typedef CGAL::Delaunay_triangulation T; + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation_doc_test ) +{ + // Read the OFF file (input file name given as parameter) and triangulates points + Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphashapedoc.off"); + // Check the read operation was correct + BOOST_CHECK(off_reader.is_valid()); + + // Retrieve the triangulation + T* triangulation = off_reader.get_complex(); + BOOST_CHECK(triangulation != nullptr); + // Operations on triangulation + BOOST_CHECK(triangulation->number_of_vertices() == 7); + BOOST_CHECK(triangulation->number_of_finite_full_cells() == 6); + + // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces + Gudhi::Delaunay_triangulation_off_writer off_writer("UT.off", triangulation); + + // Check the write operation was correct + BOOST_CHECK(off_writer.is_valid()); + + delete triangulation; +} + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) +{ + Gudhi::Delaunay_triangulation_off_reader off_reader("pouetpouet_tralala.off"); + // Check the read operation was correct + BOOST_CHECK(!off_reader.is_valid()); + T* triangulation = off_reader.get_complex(); + BOOST_CHECK(triangulation == nullptr); +} + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_write_test ) +{ + // Read the OFF file (input file name given as parameter) and triangulates points + Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphashapedoc.off"); + + // Retrieve the triangulation + T* triangulation = off_reader.get_complex(); + + // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces + Gudhi::Delaunay_triangulation_off_writer off_writer("/pouetpouet_tralala/pouetpouet_tralala/pouetpouet_tralala.off", triangulation); + + // Check the write operation was correct + BOOST_CHECK(!off_writer.is_valid()); + + delete triangulation; +} + -- cgit v1.2.3 From 4f18bf5115955c764f4eb15cd600a776f1a4d9ce Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 Jun 2015 14:35:35 +0000 Subject: Ignore this commented line git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@624 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0c8ce17217e7b110df0276f51295fd02af4b54e3 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 86b4e2b6..4596f3da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,7 +86,7 @@ else() add_subdirectory(src/common/test) add_subdirectory(src/Simplex_tree/test) add_subdirectory(src/Simplex_tree/example) - #add_subdirectory(src/Persistent_cohomology/test) + add_subdirectory(src/Persistent_cohomology/test) add_subdirectory(src/Persistent_cohomology/example) add_subdirectory(src/Skeleton_blocker/test) add_subdirectory(src/Skeleton_blocker/example) -- cgit v1.2.3 From 9e7a221884346501d5bcb06ad184e08f96938315 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 Jun 2015 14:58:02 +0000 Subject: From trunk, cpplint was removed git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@626 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 404ea81f038969fb4d96945cfb9856b8ee4ac12a --- src/Alpha_complex/test/CMakeLists.txt | 1 - src/common/test/CMakeLists.txt | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 4fe69ce5..0bd55433 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -28,4 +28,3 @@ if(CGAL_FOUND) endif () endif() -cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/Alpha_complex/include/gudhi") diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 22783caf..e4ac6c7b 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -37,8 +37,3 @@ if(CGAL_FOUND) endif () endif() - - - - -cpplint_add_tests("${CMAKE_SOURCE_DIR}/src/common/include/gudhi") -- cgit v1.2.3 From 2a3afe37fa9423890f4747373c955d7195ce8f72 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 19 Jun 2015 10:57:11 +0000 Subject: Commit before changing example file name git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@628 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3e03055a89514f6308e6aed58a9bcb1d64c95a83 --- src/Alpha_complex/example/CMakeLists.txt | 5 ++-- .../Simplex_tree_from_delaunay_triangulation.cpp | 28 +++++++++------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 9129fdcf..04c0ba58 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -15,9 +15,8 @@ if(CGAL_FOUND) include( ${EIGEN3_USE_FILE} ) #add_definitions(-DDEBUG_TRACES) - add_executable ( stfromdt Simplex_tree_from_delaunay_triangulation.cpp ) - target_link_libraries(stfromdt ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - + add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) + target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp index 1523372a..d129ebf7 100644 --- a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp +++ b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp @@ -24,13 +24,6 @@ #include "gudhi/Delaunay_triangulation_off_io.h" #include "gudhi/Alpha_complex.h" -// to construct a simplex_tree from Delaunay_triangulation -#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/Simplex_tree.h" - -#include -#include - #include #include #include @@ -49,23 +42,24 @@ int main(int argc, char **argv) { std::string off_file_name(argv[1]); // ---------------------------------------------------------------------------- - // - // Init of an alpha-complex from an OFF file - // + // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex<> alpha_complex_from_file(off_file_name); - std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; - std::cout << "alpha_complex_from_file.filtration()=" << alpha_complex_from_file.filtration() << std::endl; - std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; - std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << + " - " << alpha_complex_from_file.num_simplices() << " simplices - " << + alpha_complex_from_file.num_vertices() << " vertices." << std::endl; - std::cout << "Iterator on Simplices in the filtration order, with [filtration value]:" << std::endl; + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - std::cout << " " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; + std::cout << " ( "; for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { std::cout << vertex << " "; } + std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; std::cout << std::endl; } return 0; -- cgit v1.2.3 From 5ade372f809008bf41410455836d07c5efb6bdb9 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 19 Jun 2015 10:57:51 +0000 Subject: File name changed git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@629 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 25f954a52cd71e769a3820751080761eb350891d --- .../example/Alpha_complex_from_off.cpp | 66 ++++++++++++++++++++++ .../Simplex_tree_from_delaunay_triangulation.cpp | 66 ---------------------- 2 files changed, 66 insertions(+), 66 deletions(-) create mode 100644 src/Alpha_complex/example/Alpha_complex_from_off.cpp delete mode 100644 src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp new file mode 100644 index 00000000..d129ebf7 --- /dev/null +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -0,0 +1,66 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2014 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" + +#include +#include +#include + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " filename.off" << std::endl; + exit(-1); // ----- >> +} + +int main(int argc, char **argv) { + if (argc != 2) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + std::string off_file_name(argv[1]); + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from an OFF file + // ---------------------------------------------------------------------------- + Gudhi::alphacomplex::Alpha_complex<> alpha_complex_from_file(off_file_name); + + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << + " - " << alpha_complex_from_file.num_simplices() << " simplices - " << + alpha_complex_from_file.num_vertices() << " vertices." << std::endl; + + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + std::cout << " ( "; + for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; + std::cout << std::endl; + } + return 0; +} \ No newline at end of file diff --git a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp b/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp deleted file mode 100644 index d129ebf7..00000000 --- a/src/Alpha_complex/example/Simplex_tree_from_delaunay_triangulation.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2014 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" - -#include -#include -#include - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off" << std::endl; - exit(-1); // ----- >> -} - -int main(int argc, char **argv) { - if (argc != 2) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - std::string off_file_name(argv[1]); - - // ---------------------------------------------------------------------------- - // Init of an alpha complex from an OFF file - // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex<> alpha_complex_from_file(off_file_name); - - // ---------------------------------------------------------------------------- - // Display information about the alpha complex - // ---------------------------------------------------------------------------- - std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << - " - " << alpha_complex_from_file.num_simplices() << " simplices - " << - alpha_complex_from_file.num_vertices() << " vertices." << std::endl; - - std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; - for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - std::cout << " ( "; - for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { - std::cout << vertex << " "; - } - std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; - std::cout << std::endl; - } - return 0; -} \ No newline at end of file -- cgit v1.2.3 From ea986c68192c7536716d139e5a5f0a30a76f0fc1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 19 Jun 2015 11:08:21 +0000 Subject: Alpha complex documetation - 1st part git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@630 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b64e860b0fb6d60e706784605f699349ea17a869 --- biblio/bibliography.bib | 16 ++ .../example/Alpha_complex_from_off.cpp | 22 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 207 +++++++++++---------- src/Alpha_complex/test/CMakeLists.txt | 8 +- src/Alpha_complex/test/alphaoffreader_for_doc.txt | 27 +++ src/Doxyfile | 5 +- src/common/test/CMakeLists.txt | 6 +- 7 files changed, 163 insertions(+), 128 deletions(-) create mode 100644 src/Alpha_complex/test/alphaoffreader_for_doc.txt diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index 3fd1c10a..859696b4 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -897,6 +897,22 @@ language={English} bibsource = {DBLP, http://dblp.uni-trier.de} } +@ARTICLE{AlphaShapesDefinition, + author = {N. Akkiraju, H. Edelsbrunner, M. Facello, P. Fu, E. P. Mucke, and C. Varela}, + title = {\href{http://pub.ist.ac.at/~edels/Papers/1995-P-06-AlphaShapesSoftware.pdf}{Alpha shapes: definition and software}}, + journal = {Proc. Internat. Comput. Geom. Software Workshop 1995}, + year = {1995}, + bibsource = {http://pub.ist.ac.at} +} + +@ARTICLE{AlphaShapesIntroduction, + author = {Kaspar Fischer}, + title = {\href{http://www.cs.uu.nl/docs/vakken/ddm/texts/Delaunay/alphashapes.pdf}{Introduction to Alpha Shapes}}, + journal = {Unknown}, + year = {Unknown}, + bibsource = {http://www.cs.uu.nl} +} + misc{buddha_stanford_scan, author = "", title = "The Stanford 3D Scanning Repository", diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index d129ebf7..0d7af117 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,25 +1,3 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2014 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - // to construct a Delaunay_triangulation from a OFF file #include "gudhi/Delaunay_triangulation_off_io.h" #include "gudhi/Alpha_complex.h" diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index d25c05cb..44741e3b 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -52,17 +52,37 @@ namespace alphacomplex { #define Kinit(f) =k.f() /** \defgroup alpha_complex Alpha complex in dimension N - * -
Implementations:
- Alpha complex in dimension N are a subset of Delaunay Triangulation in dimension N. - - - * \author Vincent Rouvreau - * \version 1.0 - * \date 2015 - * \copyright GNU General Public License v3. * @{ + * \author Vincent Rouvreau + * + * \section Definition + * + * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation in dimension N. + * + * The filtration value of each simplex is computed from the alpha value of the simplex if it is Gabriel or + * from the alpha value of the simplex coface that makes the simplex not Gabriel. + * + * Please refer to \cite AlphaShapesDefinition for the alpha complex definition or to + * \cite AlphaShapesIntroduction for alpha complex concept vulgarization. + * + * \section Example + * + * This example loads points from an OFF file, builds the Delaunay triangulation, and finally initialize the + * alpha complex with it. + * Then, it is asked to display information about the alpha complex. + * + * \include Alpha_complex_from_off.cpp + * + * When launching: + * + * \code $> ./alphaoffreader ../../data/points/alphashapedoc.off + * \endcode + * + * the program output is: + * + * \include alphaoffreader_for_doc.txt */ +/** @} */ // end defgroup alpha_complex /** * \brief Alpha complex data structure. @@ -74,89 +94,107 @@ namespace alphacomplex { * * */ -class Alpha_complex { +template +class Alpha_complex : public Simplex_tree<> { private: // From Simplex_tree - /** \brief Type required to insert into a simplex_tree (with or without subfaces).*/ + // Type required to insert into a simplex_tree (with or without subfaces). typedef std::vector Vector_vertex; - /** \brief Simplex_handle type from simplex_tree.*/ - typedef typename Gudhi::Simplex_tree<>::Simplex_handle Simplex_handle; - /** \brief Simplex_result is the type returned from simplex_tree insert function.*/ + // Simplex_result is the type returned from simplex_tree insert function. typedef typename std::pair Simplex_result; - /** \brief Filtration_simplex_range type from simplex_tree.*/ - typedef typename Gudhi::Simplex_tree<>::Filtration_simplex_range Filtration_simplex_range; - - /** \brief Simplex_vertex_range type from simplex_tree.*/ - typedef typename Gudhi::Simplex_tree<>::Simplex_vertex_range Simplex_vertex_range; - // From CGAL - /** \brief Kernel for the Delaunay_triangulation. Dimension can be set dynamically.*/ + // Kernel for the Delaunay_triangulation. Dimension can be set dynamically. typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - /** \brief Delaunay_triangulation type required to create an alpha-complex.*/ + + // Delaunay_triangulation type required to create an alpha-complex. typedef CGAL::Delaunay_triangulation Delaunay_triangulation; typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; - /** \brief Type required to compute squared radius, or side of bounded sphere on a vector of points.*/ + // Type required to compute squared radius, or side of bounded sphere on a vector of points. typedef std::vector Vector_of_CGAL_points; - /** \brief Vertex_iterator type from CGAL.*/ + // Vertex_iterator type from CGAL. typedef Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; - /** \brief Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ + // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; - + private: - /** \brief Alpha complex is represented internally by a simplex tree.*/ - Gudhi::Simplex_tree<> st_; /** \brief Boost bimap to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ Bimap_vertex cgal_simplextree; /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation; public: + /** \brief Alpha_complex constructor from an OFF file name. + * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize + * the Alpha_complex. + * + * @param[in] off_file_name OFF file [path and] name. + */ Alpha_complex(std::string& off_file_name) - : triangulation(nullptr) { + : triangulation(nullptr) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << off_file_name << std::endl; + std::cerr << "Alpha_complex - Unable to read file " << off_file_name << std::endl; exit(-1); // ----- >> } triangulation = off_reader.get_complex(); init(); } + /** \brief Alpha_complex constructor from a Delaunay triangulation. + * + * @param[in] triangulation_ptr Pointer on a Delaunay triangulation. + */ Alpha_complex(Delaunay_triangulation* triangulation_ptr) - : triangulation(triangulation_ptr) { + : triangulation(triangulation_ptr) { init(); } + /** \brief Alpha_complex destructor from a Delaunay triangulation. + * + * @warning Deletes the Delaunay triangulation. + */ ~Alpha_complex() { delete triangulation; } - Filtration_simplex_range filtration_simplex_range() { - return st_.filtration_simplex_range(); - } - - Simplex_vertex_range simplex_vertex_range(Simplex_handle sh) { - return st_.simplex_vertex_range(sh); - } - - /** \brief Returns the filtration value of a simplex. - * - * Called on the null_simplex, returns INFINITY. */ - Gudhi::Simplex_tree<>::Filtration_value filtration(Simplex_handle sh) { - return st_.filtration(sh); - } - private: - + /** \brief Initialize the Alpha_complex from the Delaunay triangulation. + * + * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more + * than 0. + * + * Initialization can be launched once. + */ void init() { - st_.set_dimension(triangulation->maximal_dimension()); + if (triangulation == nullptr) { + std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation" << std::endl; + return; // ----- >> + } + if (triangulation->number_of_vertices() < 1) { + std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices" << std::endl; + return; // ----- >> + } + if (triangulation->maximal_dimension() < 1) { + std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation" << std::endl; + return; // ----- >> + } + if (num_vertices() > 0) { + std::cerr << "Alpha_complex init - Cannot init twice" << std::endl; + return; // ----- >> + } + + set_dimension(triangulation->maximal_dimension()); // -------------------------------------------------------------------------------------------- // bimap to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa @@ -187,7 +225,7 @@ class Alpha_complex { std::cout << std::endl; #endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - Simplex_result insert_result = st_.insert_simplex_and_subfaces(vertexVector, + Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); if (!insert_result.second) { std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; @@ -198,16 +236,16 @@ class Alpha_complex { Filtration_value filtration_max = 0.0; // -------------------------------------------------------------------------------------------- // ### For i : d -> 0 - for (int decr_dim = st_.dimension(); decr_dim >= 0; decr_dim--) { + for (int decr_dim = dimension(); decr_dim >= 0; decr_dim--) { // ### Foreach Sigma of dim i - for (auto f_simplex : st_.skeleton_simplex_range(decr_dim)) { - int f_simplex_dim = st_.dimension(f_simplex); + for (auto f_simplex : skeleton_simplex_range(decr_dim)) { + int f_simplex_dim = dimension(f_simplex); if (decr_dim == f_simplex_dim) { Vector_of_CGAL_points pointVector; #ifdef DEBUG_TRACES std::cout << "Sigma of dim " << decr_dim << " is"; #endif // DEBUG_TRACES - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + for (auto vertex : simplex_vertex_range(f_simplex)) { pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); #ifdef DEBUG_TRACES std::cout << " " << vertex; @@ -217,20 +255,20 @@ class Alpha_complex { std::cout << std::endl; #endif // DEBUG_TRACES // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (isnan(st_.filtration(f_simplex))) { + if (isnan(filtration(f_simplex))) { Filtration_value alpha_complex_filtration = 0.0; // No need to compute squared_radius on a single point - alpha is 0.0 if (f_simplex_dim > 0) { // squared_radius function initialization Kernel k; Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - + alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } - st_.assign_filtration(f_simplex, alpha_complex_filtration); + assign_filtration(f_simplex, alpha_complex_filtration); filtration_max = fmax(filtration_max, alpha_complex_filtration); #ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << st_.filtration(f_simplex) << std::endl; + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl; #endif // DEBUG_TRACES } propagate_alpha_filtration(f_simplex, decr_dim); @@ -242,30 +280,30 @@ class Alpha_complex { #ifdef DEBUG_TRACES std::cout << "filtration_max=" << filtration_max << std::endl; #endif // DEBUG_TRACES - st_.set_filtration(filtration_max); + set_filtration(filtration_max); } template void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { // ### Foreach Tau face of Sigma - for (auto f_boundary : st_.boundary_simplex_range(f_simplex)) { + for (auto f_boundary : boundary_simplex_range(f_simplex)) { #ifdef DEBUG_TRACES std::cout << " | --------------------------------------------------" << std::endl; std::cout << " | Tau "; - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + for (auto vertex : simplex_vertex_range(f_boundary)) { std::cout << vertex << " "; } std::cout << "is a face of Sigma" << std::endl; - std::cout << " | isnan(filtration(Tau)=" << isnan(st_.filtration(f_boundary)) << std::endl; + std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl; #endif // DEBUG_TRACES // ### If filt(Tau) is not NaN - if (!isnan(st_.filtration(f_boundary))) { + if (!isnan(filtration(f_boundary))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) - Filtration_value alpha_complex_filtration = fmin(st_.filtration(f_boundary), st_.filtration(f_simplex)); - st_.assign_filtration(f_boundary, alpha_complex_filtration); + Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); + assign_filtration(f_boundary, alpha_complex_filtration); // No need to check for filtration_max, alpha_complex_filtration is a min of an existing filtration value #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << st_.filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl; #endif // DEBUG_TRACES // ### Else } else { @@ -275,11 +313,11 @@ class Alpha_complex { // insert the Tau points in a vector for is_gabriel function Vector_of_CGAL_points pointVector; Vertex_handle vertexForGabriel = Vertex_handle(); - for (auto vertex : st_.simplex_vertex_range(f_boundary)) { + for (auto vertex : simplex_vertex_range(f_boundary)) { pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); } // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function - for (auto vertex : st_.simplex_vertex_range(f_simplex)) { + for (auto vertex : simplex_vertex_range(f_simplex)) { if (std::find(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertex))->point()) == pointVector.end()) { // vertex is not found in Tau @@ -300,46 +338,17 @@ class Alpha_complex { if ((is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) == CGAL::ON_BOUNDED_SIDE)) { // ### filt(Tau) = filt(Sigma) - Filtration_value alpha_complex_filtration = st_.filtration(f_simplex); - st_.assign_filtration(f_boundary, alpha_complex_filtration); + Filtration_value alpha_complex_filtration = filtration(f_simplex); + assign_filtration(f_boundary, alpha_complex_filtration); // No need to check for filtration_max, alpha_complex_filtration is an existing filtration value #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = filt(Sigma) = " << st_.filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl; #endif // DEBUG_TRACES } } } } } - public: - - /** \brief Returns the number of vertices in the complex. */ - size_t num_vertices() { - return st_.num_vertices(); - } - - /** \brief Returns the number of simplices in the complex. - * - * Does not count the empty simplex. */ - const unsigned int& num_simplices() const { - return st_.num_simplices(); - } - - /** \brief Returns an upper bound on the dimension of the simplicial complex. */ - int dimension() { - return st_.dimension(); - } - - /** \brief Returns an upper bound of the filtration values of the simplices. */ - Filtration_value filtration() { - return st_.filtration(); - } - - friend std::ostream& operator<<(std::ostream& os, const Alpha_complex & alpha_complex) { - Gudhi::Simplex_tree<> st = alpha_complex.st_; - os << st << std::endl; - return os; - } }; } // namespace alphacomplex diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 0bd55433..79300790 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -16,9 +16,11 @@ if(CGAL_FOUND) include_directories (BEFORE "../../include") #add_definitions(-DDEBUG_TRACES) - add_executable ( AlphaComplexUnitTest Alpha_complex_unit_test.cpp ) - target_link_libraries(AlphaComplexUnitTest ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - add_test(AlphaComplexUnitTest ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUnitTest) + add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp ) + target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_test(AlphaComplexUT ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUT + # XML format for Jenkins xUnit plugin + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/AlphaComplexUT.xml --log_level=test_suite --report_level=no) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha complex feature.") diff --git a/src/Alpha_complex/test/alphaoffreader_for_doc.txt b/src/Alpha_complex/test/alphaoffreader_for_doc.txt new file mode 100644 index 00000000..1153f097 --- /dev/null +++ b/src/Alpha_complex/test/alphaoffreader_for_doc.txt @@ -0,0 +1,27 @@ +Alpha complex is of dimension 2 - 25 simplices - 7 vertices. +Iterator on alpha complex simplices in the filtration order, with [filtration value]: + ( 1 ) -> [0] + ( 2 ) -> [0] + ( 3 ) -> [0] + ( 4 ) -> [0] + ( 5 ) -> [0] + ( 6 ) -> [0] + ( 7 ) -> [0] + ( 4 3 ) -> [6.25] + ( 6 5 ) -> [7.25] + ( 3 1 ) -> [8.5] + ( 2 1 ) -> [9.25] + ( 4 2 ) -> [10] + ( 3 2 ) -> [11.25] + ( 4 3 2 ) -> [12.5] + ( 3 2 1 ) -> [12.9959] + ( 7 6 ) -> [13.25] + ( 5 3 ) -> [20] + ( 7 5 ) -> [22.7367] + ( 7 6 5 ) -> [22.7367] + ( 7 4 ) -> [30.25] + ( 7 3 ) -> [36.5] + ( 7 4 3 ) -> [36.5] + ( 7 5 3 ) -> [37.2449] + ( 5 1 ) -> [59.7107] + ( 5 3 1 ) -> [59.7107] diff --git a/src/Doxyfile b/src/Doxyfile index 9d4bc9c8..49ec4768 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -812,8 +812,9 @@ EXCLUDE_SYMBOLS = # command). EXAMPLE_PATH = common/example \ - common/test - + common/test \ + Alpha_complex/example \ + Alpha_complex/test \ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index e4ac6c7b..1b4dd6e0 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -23,10 +23,12 @@ if(CGAL_FOUND) target_link_libraries(dtoffrw_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) # Unitary tests - add_test(dtoffrw_UT ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_UT) + add_test(dtoffrw_UT ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_UT + # XML format for Jenkins xUnit plugin + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/dtoffrw_UT.xml --log_level=test_suite --report_level=no) if (DIFF_PATH) - add_test(diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) + add_test(dtoffrw_diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) endif() else() -- cgit v1.2.3 From 01b0bf84f780b9998a48f0dbe338319da1c6d6f2 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 23 Jun 2015 13:50:46 +0000 Subject: Alpha complex documentation - 2nd part git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@633 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 023b5aaa57593a4e8e77cf12f388559b638f0eb1 --- data/points/alphacomplexdoc.off | 10 + data/points/alphashapedoc.off | 10 - src/Alpha_complex/doc/alpha_complex_doc.ipe | 438 ++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc.png | Bin 0 -> 46226 bytes src/Alpha_complex/doc/alpha_complex_doc_135.ipe | 514 +++++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 0 -> 94098 bytes .../doc/alpha_complex_doc_alpha_shape.ipe | 493 ++++++++++++++++++++ .../doc/alpha_complex_doc_alpha_shape.png | Bin 0 -> 70425 bytes src/Alpha_complex/include/gudhi/Alpha_complex.h | 90 +++- src/Doxyfile | 3 +- 10 files changed, 1531 insertions(+), 27 deletions(-) create mode 100755 data/points/alphacomplexdoc.off delete mode 100755 data/points/alphashapedoc.off create mode 100644 src/Alpha_complex/doc/alpha_complex_doc.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc.png create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.png create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png diff --git a/data/points/alphacomplexdoc.off b/data/points/alphacomplexdoc.off new file mode 100755 index 00000000..bb790193 --- /dev/null +++ b/data/points/alphacomplexdoc.off @@ -0,0 +1,10 @@ +nOFF +2 7 0 0 +1.0 1.0 +7.0 0.0 +4.0 6.0 +9.0 6.0 +0.0 14.0 +2.0 19.0 +9.0 17.0 + diff --git a/data/points/alphashapedoc.off b/data/points/alphashapedoc.off deleted file mode 100755 index bb790193..00000000 --- a/data/points/alphashapedoc.off +++ /dev/null @@ -1,10 +0,0 @@ -nOFF -2 7 0 0 -1.0 1.0 -7.0 0.0 -4.0 6.0 -9.0 6.0 -0.0 14.0 -2.0 19.0 -9.0 17.0 - diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe new file mode 100644 index 00000000..6257b2f4 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -0,0 +1,438 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +Delaunay triangulation +1 +2 +3 +4 +5 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +1 +2 +3 +3 +2 +3 +3 +4 +4 +4 +4 +5 +5 +5 +5 +7 +7 +7 +7 +7 +7 +6 +7 +6 + +4 0 0 4 320 704 e + + +322.919 706.788 m +317.189 701.058 l +317.189 701.203 l + + +317.551 706.934 m +322.629 701.058 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +220 670 l + + +230 680 m +230 670 l + + +220 660 m +220 650 l + + +230 660 m +230 650 l + + +260 680 m +260 670 l + + +260 660 m +260 650 l + + +300 680 m +300 670 l + + +300 680 m +290 670 l + + +290 660 m +290 650 l + + +300 660 m +300 650 l + + +330 680 m +330 670 l + + +350 680 m +350 670 l + + +350 660 m +350 650 l + + +320 700 m +240 690 l + + +320 700 m +270 690 l + + +320 700 m +310 690 l + + +320 700 m +330 690 l + + +320 700 m +350 690 l + + +320 700 m +380 690 l + + +320 700 m +400 690 l + + +240 620 m +220 600 l + + +240 620 m +220 640 l + +Simplex tree structure + +280 630 m +170 630 l + + +280 610 m +170 610 l + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png new file mode 100644 index 00000000..ff51ea9a Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe new file mode 100644 index 00000000..df55639a --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe @@ -0,0 +1,514 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +Cell [5,3,1] +1 +2 +3 +4 +5 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + + +77.2727 0 0 77.2727 243.636 591.818 e + + + +243.428 591.569 m +186.061 643.28 l + +$\alpha_{531}$ + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[3,1] is Gabriel $\rightarrow$ $\alpha_{31}$ is not$\\$ +modified (NaN) + +1 +2 +3 +4 +5 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{31}$ + +290 530 m +320 580 l + + +29.1548 0 0 29.1548 305 555 e + + + +304.883 555.015 m +334.509 555.015 l + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[1,5] is not Gabriel $\rightarrow$ $\alpha_{15} = \alpha_{135}$ +1 +2 +3 +4 +5 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{15}$ + +290 530 m +280 660 l + + +65.192 0 0 65.192 285 595 e + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +1 +2 +3 +4 +6 +7 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{35}$ +5 + +406.093 497.775 m +446.094 418.092 l + + +44.5799 0 0 44.5799 425.934 457.774 e + + + +425.854 457.774 m +470.795 457.774 l + +[3,5] is Gabriel $\rightarrow$ $\alpha_{35}$ is not modified (NaN) + + +205.028 596.091 m +110.946 544.02 l + + +280.768 588.99 m +280.768 547.57 l + + +341.123 594.316 m +413.904 554.079 l + +For all faces of [5,3,1] +N.B. : is Gabriel on a single point has no sense. +Dimension =2 - $\sigma$ = [5,3,1] + + +247.333 430.892 m +311.764 430.892 l + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png new file mode 100644 index 00000000..edf61368 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc_135.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe new file mode 100644 index 00000000..192ea772 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe @@ -0,0 +1,493 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Alpha shape +1 +2 +3 +4 +5 +6 +7 +1 +2 +3 +3 +2 +3 +3 +4 +4 +4 +4 +5 +5 +5 +5 +7 +7 +7 +7 +7 +7 +6 +7 +6 + +4 0 0 4 320 704 e + + +322.919 706.788 m +317.189 701.058 l +317.189 701.203 l + + +317.551 706.934 m +322.629 701.058 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +240 670 l + + +230 680 m +220 670 l + + +230 680 m +230 670 l + + +220 660 m +220 650 l + + +230 660 m +230 650 l + + +260 680 m +260 670 l + + +260 660 m +260 650 l + + +300 680 m +300 670 l + + +300 680 m +290 670 l + + +290 660 m +290 650 l + + +300 660 m +300 650 l + + +330 680 m +330 670 l + + +350 680 m +350 670 l + + +350 660 m +350 650 l + + +320 700 m +240 690 l + + +320 700 m +270 690 l + + +320 700 m +310 690 l + + +320 700 m +330 690 l + + +320 700 m +350 690 l + + +320 700 m +380 690 l + + +320 700 m +400 690 l + +Alpha complex structure + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +58.1341 0 0 58.1341 218.925 692.601 e + + +60 710 m +40 660 l + + +40 660 m +130 690 l + + +130 690 m +60 710 l + + +40 660 m +80 580 l + + +80 580 m +130 580 l +130 580 l + + +130 580 m +110 520 l + + +110 520 m +50 530 l +50 530 l +50 530 l + + +50 530 m +80 580 l + + +80 580 m +110 520 l +110 520 l + + +130 580 m +130 690 l + + + +108.275 743.531 m +166.45 743.531 l + +$\alpha$ +filtration value $> \alpha$ are greyed + +280 660 m +300 680 l + + +280 660 m +300 640 l + + +370 660 m +350 680 l + + +370 660 m +350 640 l + + +290 670 m +360 670 l + + +290 650 m +360 650 l + +equivalent + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png new file mode 100644 index 00000000..516de126 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png differ diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 44741e3b..191ff853 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -51,47 +51,105 @@ namespace alphacomplex { #define Kinit(f) =k.f() -/** \defgroup alpha_complex Alpha complex in dimension N - * @{ +/** \tableofcontents + * \defgroup alpha_complex Alpha complex + * * \author Vincent Rouvreau - * - * \section Definition * - * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation in dimension N. + * @{ + * + * \section definition Definition + * + * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation. * * The filtration value of each simplex is computed from the alpha value of the simplex if it is Gabriel or * from the alpha value of the simplex coface that makes the simplex not Gabriel. * - * Please refer to \cite AlphaShapesDefinition for the alpha complex definition or to - * \cite AlphaShapesIntroduction for alpha complex concept vulgarization. + * Please refer to \cite AlphaShapesDefinition for a more complete alpha complex definition. * - * \section Example + * Alpha complex are interesting because it looks like an \ref alpha-shape "Alpha shape" as described in + * \cite AlphaShapesIntroduction (an alpha complex concept vulgarization). + * + * \section example Example + * + * This example loads points from an OFF file, builds the Delaunay triangulation from the points, and finally + * initialize the alpha complex with it. * - * This example loads points from an OFF file, builds the Delaunay triangulation, and finally initialize the - * alpha complex with it. * Then, it is asked to display information about the alpha complex. * * \include Alpha_complex_from_off.cpp * * When launching: * - * \code $> ./alphaoffreader ../../data/points/alphashapedoc.off + * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off * \endcode * * the program output is: * * \include alphaoffreader_for_doc.txt + * + * \section algorithm Algorithm + * + * Data structure + * + * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. + * (The filtration value is set to NaN, which stands for unknown value): + * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" + * + * Filtration value computation algorithm + * + * \f{algorithm}{ + * \caption{Filtration value computation algorithm}\label{alpha} + * \begin{algorithmic} + * \For{i : dimension $\rightarrow$ 1} + * \ForAll{$\sigma$ of dimension i} + * \If {filtration($\sigma$) is NaN} + * \State filtration($\sigma$) = $\alpha(\sigma)$ + * \EndIf + * \ForAll{$\tau$ face of $\sigma$} \Comment{propagate alpha filtration value} + * \If {filtration($\tau$) is not NaN} + * \State filtration($\tau$) = min (filtration($\tau$), filtration($\sigma$)) + * \Else + * \If {$\tau$ is not Gabriel for $\sigma$} + * \State filtration($\tau$) = filtration($\sigma$) + * \EndIf + * \EndIf + * \EndFor + * \EndFor + * \EndFor + * \end{algorithmic} + * \f} + * + * From the example above, it means the algorithm will look into each triangulation ([1,2,3], [2,3,4], [1,3,5], ...), + * will compute the filtration value of the triangulation, and then will propagate the filtration value as described + * here : + * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" + * Then, the algorithm will look into each edge ([1,2], [2,3], [1,3], ...), + * will compute the filtration value of the edge (in this case, propagation will have no effect). + * + * Finally, the algorithm will look into each vertex ([1], [2], [3], [4], [5], [6] and [7]), + * will set the filtration value (0 in case of a vertex - propagation will have no effect). + * + * \section alpha-shape Alpha shape + * + * In the example above, the alpha shape of \f$\alpha_{74} < \alpha < \alpha_{73}\f$ is the alpha complex where the + * \f$\alpha_{74} <\f$ filtration value \f$< \alpha_{73}\f$ as described in \cite AlphaShapesIntroduction + * + * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" + * \copyright GNU General Public License v3. + * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim */ /** @} */ // end defgroup alpha_complex /** * \brief Alpha complex data structure. * - * \details Every simplex \f$[v_0, \cdots ,v_d]\f$ admits a canonical orientation - * induced by the order relation on vertices \f$ v_0 < \cdots < v_d \f$. - * - * Details may be found in \cite boissonnatmariasimplextreealgorithmica. - * + * \details + * The data structure can be constructed from a CGAL Delaunay triangulation (for more informations on CGAL Delaunay + * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) or from + * an OFF file (cf. Delaunay_triangulation_off_reader). + * + * Please refer to \ref alpha_complex for examples. * */ template Date: Tue, 23 Jun 2015 15:15:18 +0000 Subject: Separate main alpha documentation from class documentation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@635 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c1a775a032fc5e5ee6da473b91d07cfc3f1930c6 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 119 ++++++++++++++++++++++++ src/Alpha_complex/include/gudhi/Alpha_complex.h | 90 ------------------ 2 files changed, 119 insertions(+), 90 deletions(-) create mode 100644 src/Alpha_complex/doc/Intro_alpha_complex.h diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h new file mode 100644 index 00000000..34af2b98 --- /dev/null +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -0,0 +1,119 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// needs namespace for Doxygen to link on classes +namespace Gudhi { +// needs namespace for Doxygen to link on classes +namespace alphacomplex { + +/** \defgroup alpha_complex Alpha complex + * + * \author Vincent Rouvreau + * + * @{ + * + * \section definition Definition + * + * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation. + * + * The filtration value of each simplex is computed from the alpha value of the simplex if it is Gabriel or + * from the alpha value of the simplex coface that makes the simplex not Gabriel. + * + * Please refer to \cite AlphaShapesDefinition for a more complete alpha complex definition. + * + * Alpha complex are interesting because it looks like an \ref alpha-shape "Alpha shape" as described in + * \cite AlphaShapesIntroduction (an alpha complex concept vulgarization). + * + * \section example Example + * + * This example loads points from an OFF file, builds the Delaunay triangulation from the points, and finally + * initialize the alpha complex with it. + * + * Then, it is asked to display information about the alpha complex. + * + * \include Alpha_complex_from_off.cpp + * + * When launching: + * + * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off + * \endcode + * + * the program output is: + * + * \include alphaoffreader_for_doc.txt + * + * \section algorithm Algorithm + * + * Data structure + * + * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. + * (The filtration value is set to NaN, which stands for unknown value): + * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" + * + * Filtration value computation algorithm + * + * \f{algorithm}{ + * \caption{Filtration value computation algorithm}\label{alpha} + * \begin{algorithmic} + * \For{i : dimension $\rightarrow$ 1} + * \ForAll{$\sigma$ of dimension i} + * \If {filtration($\sigma$) is NaN} + * \State filtration($\sigma$) = $\alpha(\sigma)$ + * \EndIf + * \ForAll{$\tau$ face of $\sigma$} \Comment{propagate alpha filtration value} + * \If {filtration($\tau$) is not NaN} + * \State filtration($\tau$) = min (filtration($\tau$), filtration($\sigma$)) + * \Else + * \If {$\tau$ is not Gabriel for $\sigma$} + * \State filtration($\tau$) = filtration($\sigma$) + * \EndIf + * \EndIf + * \EndFor + * \EndFor + * \EndFor + * \end{algorithmic} + * \f} + * + * From the example above, it means the algorithm will look into each triangulation ([1,2,3], [2,3,4], [1,3,5], ...), + * will compute the filtration value of the triangulation, and then will propagate the filtration value as described + * here : + * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" + * Then, the algorithm will look into each edge ([1,2], [2,3], [1,3], ...), + * will compute the filtration value of the edge (in this case, propagation will have no effect). + * + * Finally, the algorithm will look into each vertex ([1], [2], [3], [4], [5], [6] and [7]), + * will set the filtration value (0 in case of a vertex - propagation will have no effect). + * + * \section alpha-shape Alpha shape + * + * In the example above, the alpha shape of \f$\alpha_{74} < \alpha < \alpha_{73}\f$ is the alpha complex where the + * \f$\alpha_{74} <\f$ filtration value \f$< \alpha_{73}\f$ as described in \cite AlphaShapesIntroduction + * + * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" + * \copyright GNU General Public License v3. + * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim + */ +/** @} */ // end defgroup alpha_complex + +} // namespace alphacomplex + +} // namespace Gudhi diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 191ff853..97c30abb 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -51,96 +51,6 @@ namespace alphacomplex { #define Kinit(f) =k.f() -/** \tableofcontents - * \defgroup alpha_complex Alpha complex - * - * \author Vincent Rouvreau - * - * @{ - * - * \section definition Definition - * - * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation. - * - * The filtration value of each simplex is computed from the alpha value of the simplex if it is Gabriel or - * from the alpha value of the simplex coface that makes the simplex not Gabriel. - * - * Please refer to \cite AlphaShapesDefinition for a more complete alpha complex definition. - * - * Alpha complex are interesting because it looks like an \ref alpha-shape "Alpha shape" as described in - * \cite AlphaShapesIntroduction (an alpha complex concept vulgarization). - * - * \section example Example - * - * This example loads points from an OFF file, builds the Delaunay triangulation from the points, and finally - * initialize the alpha complex with it. - * - * Then, it is asked to display information about the alpha complex. - * - * \include Alpha_complex_from_off.cpp - * - * When launching: - * - * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off - * \endcode - * - * the program output is: - * - * \include alphaoffreader_for_doc.txt - * - * \section algorithm Algorithm - * - * Data structure - * - * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. - * (The filtration value is set to NaN, which stands for unknown value): - * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" - * - * Filtration value computation algorithm - * - * \f{algorithm}{ - * \caption{Filtration value computation algorithm}\label{alpha} - * \begin{algorithmic} - * \For{i : dimension $\rightarrow$ 1} - * \ForAll{$\sigma$ of dimension i} - * \If {filtration($\sigma$) is NaN} - * \State filtration($\sigma$) = $\alpha(\sigma)$ - * \EndIf - * \ForAll{$\tau$ face of $\sigma$} \Comment{propagate alpha filtration value} - * \If {filtration($\tau$) is not NaN} - * \State filtration($\tau$) = min (filtration($\tau$), filtration($\sigma$)) - * \Else - * \If {$\tau$ is not Gabriel for $\sigma$} - * \State filtration($\tau$) = filtration($\sigma$) - * \EndIf - * \EndIf - * \EndFor - * \EndFor - * \EndFor - * \end{algorithmic} - * \f} - * - * From the example above, it means the algorithm will look into each triangulation ([1,2,3], [2,3,4], [1,3,5], ...), - * will compute the filtration value of the triangulation, and then will propagate the filtration value as described - * here : - * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" - * Then, the algorithm will look into each edge ([1,2], [2,3], [1,3], ...), - * will compute the filtration value of the edge (in this case, propagation will have no effect). - * - * Finally, the algorithm will look into each vertex ([1], [2], [3], [4], [5], [6] and [7]), - * will set the filtration value (0 in case of a vertex - propagation will have no effect). - * - * \section alpha-shape Alpha shape - * - * In the example above, the alpha shape of \f$\alpha_{74} < \alpha < \alpha_{73}\f$ is the alpha complex where the - * \f$\alpha_{74} <\f$ filtration value \f$< \alpha_{73}\f$ as described in \cite AlphaShapesIntroduction - * - * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" - * \copyright GNU General Public License v3. - * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim - */ -/** @} */ // end defgroup alpha_complex - /** * \brief Alpha complex data structure. * -- cgit v1.2.3 From 85059e058ea651d5d9e849c8462cbe5f01e4743b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 24 Jun 2015 15:27:19 +0000 Subject: Alpha complex construction from a list of CGAL points git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@641 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 521269f793f9c16c2305db8c97678bea2bf95092 --- .../example/Alpha_complex_from_off.cpp | 2 +- .../example/Alpha_complex_from_points.cpp | 71 +++++++++++++++ src/Alpha_complex/example/CMakeLists.txt | 3 + src/Alpha_complex/include/gudhi/Alpha_complex.h | 32 +++++-- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 100 ++++++++++++++++++--- src/common/doc/main_page.h | 4 +- 6 files changed, 192 insertions(+), 20 deletions(-) create mode 100644 src/Alpha_complex/example/Alpha_complex_from_points.cpp diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 0d7af117..ce278419 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -22,7 +22,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex<> alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp new file mode 100644 index 00000000..fc0e2460 --- /dev/null +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -0,0 +1,71 @@ +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" + +#include +#include + +#include +#include +#include + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef Kernel::Point_d Point; +typedef std::vector Vector_of_points; + +int main(int argc, char **argv) { + + // ---------------------------------------------------------------------------- + // Init of a list of points + // ---------------------------------------------------------------------------- + Vector_of_points points; + std::vector coords; + + coords.clear(); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(1.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(1.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(0.0); + coords.push_back(1.0); + coords.push_back(0.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(1.0); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from the list of points + // ---------------------------------------------------------------------------- + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Alpha complex is of dimension " << alpha_complex_from_points.dimension() << + " - " << alpha_complex_from_points.num_simplices() << " simplices - " << + alpha_complex_from_points.num_vertices() << " vertices." << std::endl; + + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + std::cout << " ( "; + for (auto vertex : alpha_complex_from_points.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << alpha_complex_from_points.filtration(f_simplex) << "] "; + std::cout << std::endl; + } + return 0; +} \ No newline at end of file diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 04c0ba58..2e64e4db 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -17,6 +17,9 @@ if(CGAL_FOUND) #add_definitions(-DDEBUG_TRACES) add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + + add_executable ( alphapoints Alpha_complex_from_points.cpp ) + target_link_libraries(alphapoints ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 97c30abb..138270ff 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -44,6 +44,7 @@ #include #include #include // NaN +#include // std::iterator namespace Gudhi { @@ -62,11 +63,6 @@ namespace alphacomplex { * Please refer to \ref alpha_complex for examples. * */ -template class Alpha_complex : public Simplex_tree<> { private: // From Simplex_tree @@ -94,6 +90,9 @@ class Alpha_complex : public Simplex_tree<> { // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; + + // size_type type from CGAL. + typedef Delaunay_triangulation::size_type size_type; private: /** \brief Boost bimap to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ @@ -108,7 +107,7 @@ class Alpha_complex : public Simplex_tree<> { * * @param[in] off_file_name OFF file [path and] name. */ - Alpha_complex(std::string& off_file_name) + Alpha_complex(const std::string& off_file_name) : triangulation(nullptr) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { @@ -128,6 +127,27 @@ class Alpha_complex : public Simplex_tree<> { init(); } + /** \brief Alpha_complex constructor from a list of points. + * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize + * the Alpha_complex. + * + * @param[in] dimension Dimension of points to be inserted. + * @param[in] size Number of points to be inserted. + * @param[in] firstPoint Iterator on the first point to be inserted. + * @param[in] last Point Iterator on the last point to be inserted. + */ + template + Alpha_complex(int dimension, size_type size, ForwardIterator firstPoint, ForwardIterator lastPoint) + : triangulation(nullptr) { + triangulation = new Delaunay_triangulation(dimension); + Delaunay_triangulation::size_type inserted = triangulation->insert(firstPoint, lastPoint); + if (inserted != size) { + std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << size<< std::endl; + exit(-1); // ----- >> + } + init(); + } + /** \brief Alpha_complex destructor from a Delaunay triangulation. * * @warning Deletes the Delaunay triangulation. diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 86d4d9c3..9530314c 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -28,15 +28,19 @@ #include "gudhi/Delaunay_triangulation_off_io.h" #include "gudhi/Alpha_complex.h" +#include +#include + #include // float comparison +#include // Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instantiation of the -// TriangulationDataStructure template parameter +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef Kernel::Point_d Point; +typedef std::vector Vector_of_points; +// The triangulation uses the default instantiation of the TriangulationDataStructure template parameter -BOOST_AUTO_TEST_CASE( S4_100_OFF_file ) { +BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { // ---------------------------------------------------------------------------- // // Init of an alpha-complex from a OFF file @@ -44,24 +48,24 @@ BOOST_AUTO_TEST_CASE( S4_100_OFF_file ) { // ---------------------------------------------------------------------------- std::string off_file_name("S4_100.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 4; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - + const int NUMBER_OF_VERTICES = 100; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - + const int NUMBER_OF_SIMPLICES = 6879; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); } -BOOST_AUTO_TEST_CASE( S8_10_OFF_file ) { +BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { // ---------------------------------------------------------------------------- // // Init of an alpha-complex from a OFF file @@ -69,19 +73,91 @@ BOOST_AUTO_TEST_CASE( S8_10_OFF_file ) { // ---------------------------------------------------------------------------- std::string off_file_name("S8_10.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 8; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - + const int NUMBER_OF_VERTICES = 10; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - + const int NUMBER_OF_SIMPLICES = 1007; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); +} + +bool are_almost_the_same(float a, float b) { + return std::fabs(a - b) < std::numeric_limits::epsilon(); +} + +BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { + + // ---------------------------------------------------------------------------- + // Init of a list of points + // ---------------------------------------------------------------------------- + Vector_of_points points; + std::vector coords; + + coords.clear(); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(1.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(1.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(0.0); + coords.push_back(1.0); + coords.push_back(0.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + coords.clear(); + coords.push_back(1.0); + coords.push_back(0.0); + coords.push_back(0.0); + coords.push_back(0.0); + points.push_back(Point(coords.begin(), coords.end())); + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from the list of points + // ---------------------------------------------------------------------------- + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + + std::cout << "========== Alpha_complex_from_points ==========" << std::endl; + + std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_points.dimension() == 3); + std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_simplices() == 15); + std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() == 4); + + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + switch (alpha_complex_from_points.dimension(f_simplex)) { + case 0: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 0.0)); + break; + case 1: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 1.0/2.0)); + break; + case 2: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 2.0/3.0)); + break; + case 3: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 3.0/4.0)); + break; + default: + BOOST_CHECK(false); // Shall not happen + break; + } + } } diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 315aa0ac..770d2216 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -48,8 +48,10 @@ CGAL is a C++ library which provides easy access to efficient and reliable geome The following example requires the Computational Geometry Algorithms Library (CGAL) and will not be built if CGAL is not installed: - Simplex_tree/simplex_tree_from_alpha_shapes_3 + - Alpha_complex/Alpha_complex_from_off + - Alpha_complex/Alpha_complex_from_points -Having CGAL version 4.4 or higher installed is recommended. The procedure to install this library according to +Having CGAL version 4.7 or higher installed is recommended. The procedure to install this library according to your operating system is detailed here http://doc.cgal.org/latest/Manual/installation.html \subsection demos Demos and examples -- cgit v1.2.3 From fc092e56fd3148c40b054d9cd05b05ed3c171295 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 25 Jun 2015 07:39:26 +0000 Subject: Modification for doxygen to be generated from user version (to fix bad path in doc) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@642 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 68362c2ab9d83a8daa31bcb9d7799216c8ccf94c --- scripts/generate_version.sh | 20 ++++++++-------- .../example/alphaoffreader_for_doc.txt | 27 ++++++++++++++++++++++ src/Alpha_complex/test/alphaoffreader_for_doc.txt | 27 ---------------------- src/Doxyfile | 17 +++++++------- .../example/dtoffrw_alphashapedoc_result.txt | 3 +++ src/common/test/dtoffrw_alphashapedoc_result.txt | 3 --- 6 files changed, 48 insertions(+), 49 deletions(-) create mode 100644 src/Alpha_complex/example/alphaoffreader_for_doc.txt delete mode 100644 src/Alpha_complex/test/alphaoffreader_for_doc.txt create mode 100644 src/common/example/dtoffrw_alphashapedoc_result.txt delete mode 100644 src/common/test/dtoffrw_alphashapedoc_result.txt diff --git a/scripts/generate_version.sh b/scripts/generate_version.sh index 4d28cf53..e7575282 100755 --- a/scripts/generate_version.sh +++ b/scripts/generate_version.sh @@ -2,6 +2,8 @@ #usage bash generate_version.sh : dont generate if svn st non empty #usage bash generate_version.sh -f : generate even if svn is empty #usage bash generate_version.sh -f DIR : generate even if svn is empty and save library in dir +# +# 23/06/2015 - Remove source, add biblio, and doc # VERSION CHECK ROOT_DIR=.. VERSION_FILE="$ROOT_DIR/Version.txt" @@ -48,11 +50,13 @@ cp $ROOT_DIR/COPYING $VERSION_DIR cp -R $ROOT_DIR/data $VERSION_DIR cp $ROOT_DIR/src/CMakeLists.txt $VERSION_DIR cp $ROOT_DIR/src/Doxyfile $VERSION_DIR +cp -R $ROOT_DIR/biblio $VERSION_DIR # PACKAGE LEVEL COPY PACKAGE_INC_DIR="/include" -PACKAGE_SRC_DIR="/source" +#PACKAGE_SRC_DIR="/source" PACKAGE_EX_DIR="/example" +PACKAGE_DOC_DIR="/doc" for package in `ls $ROOT_DIR/src/` do echo $package @@ -77,20 +81,16 @@ do fi cp -R $ROOT_DIR/src/$package$PACKAGE_INC_DIR/* $VERSION_DIR$PACKAGE_INC_DIR/ fi - if [ -d "$ROOT_DIR/src/$package$PACKAGE_SRC_DIR" ] - then - if [ ! -d "$VERSION_DIR$PACKAGE_SRC_DIR" ] - then - # MUST CREATE DIRECTORY ON FIRST LOOP - mkdir $VERSION_DIR$PACKAGE_INC_DIR - fi - cp -R $ROOT_DIR/src/$package$PACKAGE_SRC_DIR/* $VERSION_DIR$PACKAGE_SRC_DIR/ - fi if [ -d "$ROOT_DIR/src/$package$PACKAGE_EX_DIR" ] then mkdir -p $VERSION_DIR$PACKAGE_EX_DIR/$package cp -R $ROOT_DIR/src/$package$PACKAGE_EX_DIR/* $VERSION_DIR$PACKAGE_EX_DIR/$package fi + if [ -d "$ROOT_DIR/src/$package$PACKAGE_DOC_DIR" ] + then + mkdir -p $VERSION_DIR$PACKAGE_DOC_DIR/$package + cp -R $ROOT_DIR/src/$package$PACKAGE_DOC_DIR/* $VERSION_DIR$PACKAGE_DOC_DIR/$package + fi fi fi done diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc.txt b/src/Alpha_complex/example/alphaoffreader_for_doc.txt new file mode 100644 index 00000000..1153f097 --- /dev/null +++ b/src/Alpha_complex/example/alphaoffreader_for_doc.txt @@ -0,0 +1,27 @@ +Alpha complex is of dimension 2 - 25 simplices - 7 vertices. +Iterator on alpha complex simplices in the filtration order, with [filtration value]: + ( 1 ) -> [0] + ( 2 ) -> [0] + ( 3 ) -> [0] + ( 4 ) -> [0] + ( 5 ) -> [0] + ( 6 ) -> [0] + ( 7 ) -> [0] + ( 4 3 ) -> [6.25] + ( 6 5 ) -> [7.25] + ( 3 1 ) -> [8.5] + ( 2 1 ) -> [9.25] + ( 4 2 ) -> [10] + ( 3 2 ) -> [11.25] + ( 4 3 2 ) -> [12.5] + ( 3 2 1 ) -> [12.9959] + ( 7 6 ) -> [13.25] + ( 5 3 ) -> [20] + ( 7 5 ) -> [22.7367] + ( 7 6 5 ) -> [22.7367] + ( 7 4 ) -> [30.25] + ( 7 3 ) -> [36.5] + ( 7 4 3 ) -> [36.5] + ( 7 5 3 ) -> [37.2449] + ( 5 1 ) -> [59.7107] + ( 5 3 1 ) -> [59.7107] diff --git a/src/Alpha_complex/test/alphaoffreader_for_doc.txt b/src/Alpha_complex/test/alphaoffreader_for_doc.txt deleted file mode 100644 index 1153f097..00000000 --- a/src/Alpha_complex/test/alphaoffreader_for_doc.txt +++ /dev/null @@ -1,27 +0,0 @@ -Alpha complex is of dimension 2 - 25 simplices - 7 vertices. -Iterator on alpha complex simplices in the filtration order, with [filtration value]: - ( 1 ) -> [0] - ( 2 ) -> [0] - ( 3 ) -> [0] - ( 4 ) -> [0] - ( 5 ) -> [0] - ( 6 ) -> [0] - ( 7 ) -> [0] - ( 4 3 ) -> [6.25] - ( 6 5 ) -> [7.25] - ( 3 1 ) -> [8.5] - ( 2 1 ) -> [9.25] - ( 4 2 ) -> [10] - ( 3 2 ) -> [11.25] - ( 4 3 2 ) -> [12.5] - ( 3 2 1 ) -> [12.9959] - ( 7 6 ) -> [13.25] - ( 5 3 ) -> [20] - ( 7 5 ) -> [22.7367] - ( 7 6 5 ) -> [22.7367] - ( 7 4 ) -> [30.25] - ( 7 3 ) -> [36.5] - ( 7 4 3 ) -> [36.5] - ( 7 5 3 ) -> [37.2449] - ( 5 1 ) -> [59.7107] - ( 5 3 1 ) -> [59.7107] diff --git a/src/Doxyfile b/src/Doxyfile index a84c4897..0724de1c 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -672,7 +672,7 @@ LAYOUT_FILE = # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. -CITE_BIB_FILES = ../biblio/bibliography.bib +CITE_BIB_FILES = biblio/bibliography.bib #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages @@ -811,10 +811,9 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = common/example \ - common/test \ - Alpha_complex/example \ - Alpha_complex/test \ +EXAMPLE_PATH = example/common/ \ + example/Alpha_complex/ + # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all @@ -833,10 +832,10 @@ EXAMPLE_RECURSIVE = NO # that contain images that are to be included in the documentation (see the # \image command). -IMAGE_PATH = Skeleton_blocker/doc/ \ - Alpha_complex/doc/ \ - common/doc/ \ - Contraction/doc/ +IMAGE_PATH = doc/Skeleton_blocker/ \ + doc/Alpha_complex/ \ + doc/common/ \ + doc/Contraction/ # The INPUT_FILTER tag can be used to specify a program that doxygen should diff --git a/src/common/example/dtoffrw_alphashapedoc_result.txt b/src/common/example/dtoffrw_alphashapedoc_result.txt new file mode 100644 index 00000000..57761d14 --- /dev/null +++ b/src/common/example/dtoffrw_alphashapedoc_result.txt @@ -0,0 +1,3 @@ +Number of vertices= 7 +Number of finite full cells= 6 + diff --git a/src/common/test/dtoffrw_alphashapedoc_result.txt b/src/common/test/dtoffrw_alphashapedoc_result.txt deleted file mode 100644 index 57761d14..00000000 --- a/src/common/test/dtoffrw_alphashapedoc_result.txt +++ /dev/null @@ -1,3 +0,0 @@ -Number of vertices= 7 -Number of finite full cells= 6 - -- cgit v1.2.3 From e1b8ee37a896ddb8d733ecd8752eb70307521f7a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 25 Jun 2015 08:25:54 +0000 Subject: File was not renamed here git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@643 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ea5a10408d8f44eb508ae68cb3ed0699dc4eba93 --- src/common/example/CMakeLists.txt | 2 +- src/common/test/dtoffrw_unit_test.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index ae30da54..4cb03dbe 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -15,7 +15,7 @@ if(CGAL_FOUND) add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(dtoffrw ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/alphashapedoc.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) + add_test(dtoffrw ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp index 4905d845..d2705955 100644 --- a/src/common/test/dtoffrw_unit_test.cpp +++ b/src/common/test/dtoffrw_unit_test.cpp @@ -43,7 +43,7 @@ typedef CGAL::Delaunay_triangulation T; BOOST_AUTO_TEST_CASE( Delaunay_triangulation_doc_test ) { // Read the OFF file (input file name given as parameter) and triangulates points - Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphashapedoc.off"); + Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphacomplexdoc.off"); // Check the read operation was correct BOOST_CHECK(off_reader.is_valid()); @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_write_test ) { // Read the OFF file (input file name given as parameter) and triangulates points - Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphashapedoc.off"); + Gudhi::Delaunay_triangulation_off_reader off_reader("../../../data/points/alphacomplexdoc.off"); // Retrieve the triangulation T* triangulation = off_reader.get_complex(); -- cgit v1.2.3 From ed8ae292df7b486b71f573431e17e3466a0a2ace Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 25 Jun 2015 09:01:59 +0000 Subject: coface removal - added but not needed git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@644 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3598444f908fd791b111c8ab8eb18a3c0a15fc16 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 87 --------------------------- 1 file changed, 87 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 32fb2f43..9a06b262 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -837,92 +837,6 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } - //---------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------- - private: - - /** Recursive search of cofaces - */ - template - void rec_coface(RandomAccessVertexRange &vertices, Siblings *curr_sib, Dictionary *curr_res, std::vector& cofaces, unsigned int length, unsigned long codimension) { - for (auto sib = curr_sib->members().begin(); sib != curr_sib->members().end() && (vertices.empty() || sib->first <= vertices[vertices.size() - 1]); ++sib) { - bool continueRecursion = (codimension == length || curr_res->size() <= codimension); // dimension of actual simplex <= codimension - if (vertices.empty()) { - if (curr_res->size() >= length && continueRecursion) - // If we reached the end of the vertices, and the simplex has more vertices than the given simplex, we found a coface - { - curr_res->emplace(sib->first, sib->second); - bool egalDim = (codimension == length || curr_res->size() == codimension); // dimension of actual simplex == codimension - if (egalDim) - cofaces.push_back(*curr_res); - if (has_children(sib)) - rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); - curr_res->erase(curr_res->end() - 1); - } - } else if (continueRecursion) { - if (sib->first == vertices[vertices.size() - 1]) // If curr_sib matches with the top vertex - { - curr_res->emplace(sib->first, sib->second); - bool egalDim = (codimension == length || curr_res->size() == codimension); // dimension of actual simplex == codimension - if (vertices.size() == 1 && curr_res->size() > length && egalDim) - cofaces.push_back(*curr_res); - if (has_children(sib)) { // Rec call - Vertex_handle tmp = vertices[vertices.size() - 1]; - vertices.pop_back(); - rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); - vertices.push_back(tmp); - } - curr_res->erase(curr_res->end() - 1); - } else // (sib->first < vertices[vertices.size()-1]) - { - if (has_children(sib)) { - curr_res->emplace(sib->first, sib->second); - rec_coface(vertices, sib->second.children(), curr_res, cofaces, length, codimension); - curr_res->erase(curr_res->end() - 1); - } - } - } - } - } - - public: - - /** \brief Compute the cofaces of a n simplex - * \param vertices List of vertices which represent the n simplex. - * \param codimension The function returns the n+codimension-simplices. If codimension = 0, return all cofaces - * \return Vector of Dictionary, empty vector if no cofaces found. - * \warning n+codimension must be lower than Simplex_tree dimension, otherwise an an empty vector is returned. - */ - - template - std::vector coface(const RandomAccessVertexRange &vertices, int codimension) { - RandomAccessVertexRange copy = vertices; - std::vector cofaces; - std::sort(copy.begin(), copy.end(), std::greater()); // must be sorted in decreasing order - if (root_.members().empty()) { - std::cerr << "Simplex_tree::coface - empty Simplex_tree" << std::endl; - return cofaces; // ----->> - } - if (vertices.empty()) { - std::cerr << "Simplex_tree::coface - empty vertices list" << std::endl; - return cofaces; // ----->> - } - if (codimension < 0) { - std::cerr << "Simplex_tree::coface - codimension is empty" << std::endl; - return cofaces; // ----->> - } - if (codimension + vertices.size() >= (unsigned long) dimension_) { - std::cerr << "Simplex_tree::coface - codimension + vertices list size cannot be greater than Simplex_tree dimension" << std::endl; - return cofaces; // ----->> - } - std::sort(copy.begin(), copy.end(), std::greater()); // must be sorted in decreasing order - Dictionary res; - rec_coface(copy, &root_, &res, cofaces, vertices.size(), codimension + vertices.size()); - return cofaces; - } - - //---------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------- private: Vertex_handle null_vertex_; @@ -950,7 +864,6 @@ std::ostream& operator<<(std::ostream & os, Simplex_tree & st) { } return os; } - template std::istream& operator>>(std::istream & is, Simplex_tree & st) { // assert(st.num_simplices() == 0); -- cgit v1.2.3 From 909bba8b607f4279709e989c7727063df4a98016 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 4 Aug 2015 12:32:08 +0000 Subject: get_point method in alpha_complex structure and its UT git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@723 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9ad36d7617f4aade5c85e2a8fb7a0c60180aa59f --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 29 +++++++++++---- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 43 ++++++++++++++++++++++ 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 138270ff..16781563 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -50,8 +50,6 @@ namespace Gudhi { namespace alphacomplex { -#define Kinit(f) =k.f() - /** * \brief Alpha complex data structure. * @@ -99,6 +97,8 @@ class Alpha_complex : public Simplex_tree<> { Bimap_vertex cgal_simplextree; /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation; + /** \brief Kernel for triangulation functions access.*/ + Kernel kernel; public: /** \brief Alpha_complex constructor from an OFF file name. @@ -156,6 +156,22 @@ class Alpha_complex : public Simplex_tree<> { delete triangulation; } + /** \brief get_point returns the point corresponding to the vertex given as parameter. + * + * @param[in] vertex Vertex handle of the point to retrieve. + * @return The founded point. + */ + Kernel::Point_d get_point(Vertex_handle vertex) { + Kernel::Point_d point; + try { + point = cgal_simplextree.right.at(vertex)->point(); + } + catch(...) { + std::cerr << "Alpha_complex - getPoint not found on vertex " << vertex << std::endl; + } + return point; + } + private: /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * @@ -248,9 +264,8 @@ class Alpha_complex : public Simplex_tree<> { // No need to compute squared_radius on a single point - alpha is 0.0 if (f_simplex_dim > 0) { // squared_radius function initialization - Kernel k; - Squared_Radius squared_radius Kinit(compute_squared_radius_d_object); - + Squared_Radius squared_radius = kernel.compute_squared_radius_d_object(); + alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } assign_filtration(f_simplex, alpha_complex_filtration); @@ -315,8 +330,7 @@ class Alpha_complex : public Simplex_tree<> { } } // is_gabriel function initialization - Kernel k; - Is_Gabriel is_gabriel Kinit(side_of_bounded_sphere_d_object); + Is_Gabriel is_gabriel = kernel.side_of_bounded_sphere_d_object(); #ifdef DEBUG_TRACES bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) != CGAL::ON_BOUNDED_SIDE; @@ -337,6 +351,7 @@ class Alpha_complex : public Simplex_tree<> { } } } + }; } // namespace alphacomplex diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 9530314c..b55b5e2e 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -93,6 +93,14 @@ bool are_almost_the_same(float a, float b) { return std::fabs(a - b) < std::numeric_limits::epsilon(); } +bool is_point_in_list(Vector_of_points points_list, Point point) { + for (auto& point_in_list : points_list) { + if (point_in_list == point) { + return true; // point found + } + } + return false; // point not found +} BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // ---------------------------------------------------------------------------- @@ -159,5 +167,40 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { break; } } + + Point p1 = alpha_complex_from_points.get_point(1); + std::cout << "alpha_complex_from_points.get_point(1)=" << p1 << std::endl; + BOOST_CHECK(4 == p1.dimension()); + BOOST_CHECK(is_point_in_list(points, p1)); + + Point p2 = alpha_complex_from_points.get_point(2); + std::cout << "alpha_complex_from_points.get_point(2)=" << p2 << std::endl; + BOOST_CHECK(4 == p2.dimension()); + BOOST_CHECK(is_point_in_list(points, p2)); + + Point p3 = alpha_complex_from_points.get_point(3); + std::cout << "alpha_complex_from_points.get_point(3)=" << p3 << std::endl; + BOOST_CHECK(4 == p3.dimension()); + BOOST_CHECK(is_point_in_list(points, p3)); + + Point p4 = alpha_complex_from_points.get_point(4); + std::cout << "alpha_complex_from_points.get_point(4)=" << p4 << std::endl; + BOOST_CHECK(4 == p4.dimension()); + BOOST_CHECK(is_point_in_list(points, p4)); + + Point p5 = alpha_complex_from_points.get_point(5); + std::cout << "alpha_complex_from_points.get_point(5)=" << p5 << std::endl; + BOOST_CHECK(0 == p5.dimension()); + BOOST_CHECK(!is_point_in_list(points, p5)); + + Point p0 = alpha_complex_from_points.get_point(0); + std::cout << "alpha_complex_from_points.get_point(0)=" << p0 << std::endl; + BOOST_CHECK(0 == p0.dimension()); + BOOST_CHECK(!is_point_in_list(points, p0)); + + Point p1234 = alpha_complex_from_points.get_point(1234); + std::cout << "alpha_complex_from_points.get_point(1234)=" << p1234.dimension() << std::endl; + BOOST_CHECK(0 == p1234.dimension()); + BOOST_CHECK(!is_point_in_list(points, p1234)); } -- cgit v1.2.3 From d6c4c80e50d558034958f8fab0289d4cfb1a31b8 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 5 Aug 2015 15:03:29 +0000 Subject: Debug traces in DEBUG mode Alpha complex from delaunay triangulation in static dimension git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@725 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9dda5a16874ae009c24be39c5a9c9d4124a29063 --- .../example/Alpha_complex_from_off.cpp | 3 +- .../example/Alpha_complex_from_points.cpp | 2 +- src/Alpha_complex/example/CMakeLists.txt | 5 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 85 +++++++++++++--------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 27 ++++--- src/Alpha_complex/test/CMakeLists.txt | 5 +- src/Persistent_cohomology/example/CMakeLists.txt | 7 +- 7 files changed, 81 insertions(+), 53 deletions(-) diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index ce278419..a17155de 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -22,7 +22,8 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index fc0e2460..33680a40 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -49,7 +49,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 2e64e4db..04fc34af 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -13,8 +13,11 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() - #add_definitions(-DDEBUG_TRACES) add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 16781563..5834e3df 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -43,8 +43,8 @@ #include #include #include -#include // NaN -#include // std::iterator +#include // NaN +#include // std::iterator namespace Gudhi { @@ -61,6 +61,7 @@ namespace alphacomplex { * Please refer to \ref alpha_complex for examples. * */ +template class Alpha_complex : public Simplex_tree<> { private: // From Simplex_tree @@ -72,35 +73,43 @@ class Alpha_complex : public Simplex_tree<> { // From CGAL // Kernel for the Delaunay_triangulation. Dimension can be set dynamically. - typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + //typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; // Delaunay_triangulation type required to create an alpha-complex. - typedef CGAL::Delaunay_triangulation Delaunay_triangulation; + typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; + typedef typename Kernel::Point_d Point_d; + // Type required to compute squared radius, or side of bounded sphere on a vector of points. - typedef std::vector Vector_of_CGAL_points; + typedef typename std::vector Vector_of_CGAL_points; // Vertex_iterator type from CGAL. - typedef Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; + typedef typename Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; - // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. - typedef boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; - // size_type type from CGAL. - typedef Delaunay_triangulation::size_type size_type; + typedef typename Delaunay_triangulation::size_type size_type; + + // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. + //typedef typename boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; + //typedef typename Bimap_vertex::value_type value_type; + typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; + typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; private: - /** \brief Boost bimap to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa.*/ - Bimap_vertex cgal_simplextree; + /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ + Map_vertex_iterator_to_handle vertex_iterator_to_handle; + /** \brief Map to switch from simplex tree vertex handle to CGAL vertex iterator.*/ + Map_vertex_handle_to_iterator vertex_handle_to_iterator; /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation; /** \brief Kernel for triangulation functions access.*/ Kernel kernel; public: + /** \brief Alpha_complex constructor from an OFF file name. * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize * the Alpha_complex. @@ -140,9 +149,9 @@ class Alpha_complex : public Simplex_tree<> { Alpha_complex(int dimension, size_type size, ForwardIterator firstPoint, ForwardIterator lastPoint) : triangulation(nullptr) { triangulation = new Delaunay_triangulation(dimension); - Delaunay_triangulation::size_type inserted = triangulation->insert(firstPoint, lastPoint); + size_type inserted = triangulation->insert(firstPoint, lastPoint); if (inserted != size) { - std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << size<< std::endl; + std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << size << std::endl; exit(-1); // ----- >> } init(); @@ -161,18 +170,20 @@ class Alpha_complex : public Simplex_tree<> { * @param[in] vertex Vertex handle of the point to retrieve. * @return The founded point. */ - Kernel::Point_d get_point(Vertex_handle vertex) { - Kernel::Point_d point; + Point_d get_point(Vertex_handle vertex) { + Point_d point; try { - point = cgal_simplextree.right.at(vertex)->point(); - } - catch(...) { + if (vertex_handle_to_iterator[vertex] != nullptr) { + point = vertex_handle_to_iterator[vertex]->point(); + } + } catch (...) { std::cerr << "Alpha_complex - getPoint not found on vertex " << vertex << std::endl; } return point; } - + private: + /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more @@ -197,7 +208,7 @@ class Alpha_complex : public Simplex_tree<> { std::cerr << "Alpha_complex init - Cannot init twice" << std::endl; return; // ----- >> } - + set_dimension(triangulation->maximal_dimension()); // -------------------------------------------------------------------------------------------- @@ -206,7 +217,11 @@ class Alpha_complex : public Simplex_tree<> { Vertex_handle vertex_handle = Vertex_handle(); // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation->vertices_begin(); vit != triangulation->vertices_end(); ++vit) { - cgal_simplextree.insert(Bimap_vertex::value_type(vit, vertex_handle)); +#ifdef DEBUG_TRACES + std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; +#endif // DEBUG_TRACES + vertex_iterator_to_handle[vit] = vertex_handle; + vertex_handle_to_iterator[vertex_handle] = vit; vertex_handle++; } // -------------------------------------------------------------------------------------------- @@ -219,18 +234,20 @@ class Alpha_complex : public Simplex_tree<> { std::cout << "Simplex_tree insertion "; #endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { + if (*vit != nullptr) { #ifdef DEBUG_TRACES - std::cout << " " << cgal_simplextree.left.at(*vit); + std::cout << " " << vertex_iterator_to_handle[*vit]; #endif // DEBUG_TRACES - // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(cgal_simplextree.left.at(*vit)); + // Vector of vertex construction for simplex_tree structure + vertexVector.push_back(vertex_iterator_to_handle[*vit]); + } } #ifdef DEBUG_TRACES std::cout << std::endl; #endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, - std::numeric_limits::quiet_NaN()); + std::numeric_limits::quiet_NaN()); if (!insert_result.second) { std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; } @@ -250,7 +267,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << "Sigma of dim " << decr_dim << " is"; #endif // DEBUG_TRACES for (auto vertex : simplex_vertex_range(f_simplex)) { - pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); + pointVector.push_back(get_point(vertex)); #ifdef DEBUG_TRACES std::cout << " " << vertex; #endif // DEBUG_TRACES @@ -265,7 +282,7 @@ class Alpha_complex : public Simplex_tree<> { if (f_simplex_dim > 0) { // squared_radius function initialization Squared_Radius squared_radius = kernel.compute_squared_radius_d_object(); - + alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } assign_filtration(f_simplex, alpha_complex_filtration); @@ -317,12 +334,11 @@ class Alpha_complex : public Simplex_tree<> { Vector_of_CGAL_points pointVector; Vertex_handle vertexForGabriel = Vertex_handle(); for (auto vertex : simplex_vertex_range(f_boundary)) { - pointVector.push_back((cgal_simplextree.right.at(vertex))->point()); + pointVector.push_back(get_point(vertex)); } // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function for (auto vertex : simplex_vertex_range(f_simplex)) { - if (std::find(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertex))->point()) - == pointVector.end()) { + if (std::find(pointVector.begin(), pointVector.end(), get_point(vertex)) == pointVector.end()) { // vertex is not found in Tau vertexForGabriel = vertex; // No need to continue loop @@ -331,14 +347,13 @@ class Alpha_complex : public Simplex_tree<> { } // is_gabriel function initialization Is_Gabriel is_gabriel = kernel.side_of_bounded_sphere_d_object(); -#ifdef DEBUG_TRACES - bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), get_point(vertexForGabriel)) != CGAL::ON_BOUNDED_SIDE; +#ifdef DEBUG_TRACES std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; #endif // DEBUG_TRACES // ### If Tau is not Gabriel of Sigma - if ((is_gabriel(pointVector.begin(), pointVector.end(), (cgal_simplextree.right.at(vertexForGabriel))->point()) - == CGAL::ON_BOUNDED_SIDE)) { + if (false == is_gab) { // ### filt(Tau) = filt(Sigma) Filtration_value alpha_complex_filtration = filtration(f_simplex); assign_filtration(f_boundary, alpha_complex_filtration); diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index b55b5e2e..4202c9e9 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -35,11 +35,9 @@ #include // Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; -typedef Kernel::Point_d Point; -typedef std::vector Vector_of_points; +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d; // The triangulation uses the default instantiation of the TriangulationDataStructure template parameter - +/* BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { // ---------------------------------------------------------------------------- // @@ -49,7 +47,7 @@ BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { std::string off_file_name("S4_100.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 4; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -74,7 +72,7 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { std::string off_file_name("S8_10.off"); std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); const int DIMENSION = 8; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -88,11 +86,17 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); } - +*/ bool are_almost_the_same(float a, float b) { return std::fabs(a - b) < std::numeric_limits::epsilon(); } +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Kernel_s; +typedef Kernel_s::Point_d Point; +typedef std::vector Vector_of_points; + + bool is_point_in_list(Vector_of_points points_list, Point point) { for (auto& point_in_list : points_list) { if (point_in_list == point) { @@ -101,6 +105,7 @@ bool is_point_in_list(Vector_of_points points_list, Point point) { } return false; // point not found } + BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // ---------------------------------------------------------------------------- @@ -109,6 +114,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { Vector_of_points points; std::vector coords; + points.clear(); coords.clear(); coords.push_back(0.0); coords.push_back(0.0); @@ -137,12 +143,12 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); std::cout << "========== Alpha_complex_from_points ==========" << std::endl; std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; - BOOST_CHECK(alpha_complex_from_points.dimension() == 3); + BOOST_CHECK(alpha_complex_from_points.dimension() == 4); std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_points.num_simplices() == 15); std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; @@ -190,17 +196,14 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { Point p5 = alpha_complex_from_points.get_point(5); std::cout << "alpha_complex_from_points.get_point(5)=" << p5 << std::endl; - BOOST_CHECK(0 == p5.dimension()); BOOST_CHECK(!is_point_in_list(points, p5)); Point p0 = alpha_complex_from_points.get_point(0); std::cout << "alpha_complex_from_points.get_point(0)=" << p0 << std::endl; - BOOST_CHECK(0 == p0.dimension()); BOOST_CHECK(!is_point_in_list(points, p0)); Point p1234 = alpha_complex_from_points.get_point(1234); std::cout << "alpha_complex_from_points.get_point(1234)=" << p1234.dimension() << std::endl; - BOOST_CHECK(0 == p1234.dimension()); BOOST_CHECK(!is_point_in_list(points, p1234)); } diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 79300790..87b05a3a 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -14,8 +14,11 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) include_directories (BEFORE "../../include") + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() - #add_definitions(-DDEBUG_TRACES) add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp ) target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) add_test(AlphaComplexUT ${CMAKE_CURRENT_BINARY_DIR}/AlphaComplexUT diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index 9487cce6..3276989d 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -28,8 +28,11 @@ if (NOT MSVC) target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) if(CGAL_FOUND) - # uncomment to display debug traces - # add_definitions(-DDEBUG_TRACES) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() + add_executable(alpha_shapes_persistence alpha_shapes_persistence.cpp) target_link_libraries(alpha_shapes_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) add_test(alpha_shapes_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) -- cgit v1.2.3 From f572657e071e25e6fddea4950096e7eefc72072e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 10 Aug 2015 09:26:11 +0000 Subject: fix bad merge in src/CMakeLists.txt Remove commented lines from UT git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@726 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c0d0c1412205aacbedaa0a562ba5e1e12513020b --- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 4 ++-- src/CMakeLists.txt | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 4202c9e9..b7aceb5e 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -37,7 +37,7 @@ // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d; // The triangulation uses the default instantiation of the TriangulationDataStructure template parameter -/* + BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { // ---------------------------------------------------------------------------- // @@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); } -*/ + bool are_almost_the_same(float a, float b) { return std::fabs(a - b) < std::numeric_limits::epsilon(); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0af1a6d..7b30f77a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -47,7 +47,6 @@ else() add_subdirectory(example/Hasse_complex) add_subdirectory(example/Alpha_complex) add_subdirectory(example/Bottleneck) - add_subdirectory(example/Bottleneck) # GudhUI add_subdirectory(GudhUI) -- cgit v1.2.3 From 9d0238eb065cd1a6b25ec2916d7a1a3cc52adcd6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 17 Aug 2015 10:04:23 +0000 Subject: Alpha complex fix for only inserting when alpha is less than git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@736 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0bc6560fa08b72d823681d36c49e80f0437d99f1 --- .../example/Alpha_complex_from_off.cpp | 25 +- .../example/Alpha_complex_from_points.cpp | 51 ++-- src/Alpha_complex/include/gudhi/Alpha_complex.h | 272 ++++++++++++--------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 174 +++++++++---- 4 files changed, 326 insertions(+), 196 deletions(-) diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index a17155de..3ce4c7f4 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,37 +1,40 @@ -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" - #include #include + #include +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" + void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off" << std::endl; - exit(-1); // ----- >> + std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value" << std::endl; + std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0" << std::endl; + exit(-1); // ----- >> } int main(int argc, char **argv) { - if (argc != 2) { + if (argc != 3) { std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; usage(argv[0]); } std::string off_file_name(argv[1]); + double alpha_square_max_value = atof(argv[2]); // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); - + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); + // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << " - " << alpha_complex_from_file.num_simplices() << " simplices - " << alpha_complex_from_file.num_vertices() << " vertices." << std::endl; - + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { std::cout << " ( "; @@ -42,4 +45,4 @@ int main(int argc, char **argv) { std::cout << std::endl; } return 0; -} \ No newline at end of file +} diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 33680a40..b160d702 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -1,55 +1,40 @@ -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" - +#include +#include #include #include -#include -#include #include +#include + +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; int main(int argc, char **argv) { - // ---------------------------------------------------------------------------- // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - std::vector coords; - - coords.clear(); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(1.0); + + std::vector coords = { 0.0, 0.0, 0.0, 1.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(1.0); - coords.push_back(0.0); + coords = { 0.0, 0.0, 1.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(0.0); - coords.push_back(1.0); - coords.push_back(0.0); - coords.push_back(0.0); + coords = { 0.0, 1.0, 0.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(1.0); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(0.0); + coords = { 1.0, 0.0, 0.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - + // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + double max_alpha_square_value = 1e10; + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end(), + max_alpha_square_value); // ---------------------------------------------------------------------------- // Display information about the alpha complex @@ -57,7 +42,7 @@ int main(int argc, char **argv) { std::cout << "Alpha complex is of dimension " << alpha_complex_from_points.dimension() << " - " << alpha_complex_from_points.num_simplices() << " simplices - " << alpha_complex_from_points.num_vertices() << " vertices." << std::endl; - + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { std::cout << " ( "; @@ -68,4 +53,4 @@ int main(int argc, char **argv) { std::cout << std::endl; } return 0; -} \ No newline at end of file +} diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 5834e3df..06e69cf3 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ -#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_H_ +#ifndef ALPHA_COMPLEX_H_ +#define ALPHA_COMPLEX_H_ // to construct a simplex_tree from Delaunay_triangulation #include @@ -31,8 +31,6 @@ #include #include // isnan, fmax -#include - #include #include #include @@ -40,11 +38,11 @@ #include #include -#include #include #include #include // NaN -#include // std::iterator +#include +#include // std::pair namespace Gudhi { @@ -71,10 +69,6 @@ class Alpha_complex : public Simplex_tree<> { // Simplex_result is the type returned from simplex_tree insert function. typedef typename std::pair Simplex_result; - // From CGAL - // Kernel for the Delaunay_triangulation. Dimension can be set dynamically. - //typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - // Delaunay_triangulation type required to create an alpha-complex. typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; @@ -92,38 +86,38 @@ class Alpha_complex : public Simplex_tree<> { // size_type type from CGAL. typedef typename Delaunay_triangulation::size_type size_type; - // Boost bimap type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. - //typedef typename boost::bimap< CGAL_vertex_iterator, Vertex_handle > Bimap_vertex; - //typedef typename Bimap_vertex::value_type value_type; + // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; private: /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ - Map_vertex_iterator_to_handle vertex_iterator_to_handle; + Map_vertex_iterator_to_handle vertex_iterator_to_handle_; /** \brief Map to switch from simplex tree vertex handle to CGAL vertex iterator.*/ - Map_vertex_handle_to_iterator vertex_handle_to_iterator; + Map_vertex_handle_to_iterator vertex_handle_to_iterator_; /** \brief Pointer on the CGAL Delaunay triangulation.*/ - Delaunay_triangulation* triangulation; - /** \brief Kernel for triangulation functions access.*/ - Kernel kernel; + Delaunay_triangulation* triangulation_; + /** \brief Kernel for triangulation_ functions access.*/ + Kernel kernel_; + /** \brief Maximum value for alpha square.*/ + Filtration_value max_alpha_square_; public: - /** \brief Alpha_complex constructor from an OFF file name. * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize * the Alpha_complex. * * @param[in] off_file_name OFF file [path and] name. */ - Alpha_complex(const std::string& off_file_name) - : triangulation(nullptr) { + Alpha_complex(const std::string& off_file_name, Filtration_value max_alpha_square) + : triangulation_(nullptr), + max_alpha_square_(max_alpha_square) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { std::cerr << "Alpha_complex - Unable to read file " << off_file_name << std::endl; - exit(-1); // ----- >> + exit(-1); // ----- >> } - triangulation = off_reader.get_complex(); + triangulation_ = off_reader.get_complex(); init(); } @@ -131,8 +125,9 @@ class Alpha_complex : public Simplex_tree<> { * * @param[in] triangulation_ptr Pointer on a Delaunay triangulation. */ - Alpha_complex(Delaunay_triangulation* triangulation_ptr) - : triangulation(triangulation_ptr) { + Alpha_complex(Delaunay_triangulation* triangulation_ptr, Filtration_value max_alpha_square) + : triangulation_(triangulation_ptr), + max_alpha_square_(max_alpha_square) { init(); } @@ -146,13 +141,15 @@ class Alpha_complex : public Simplex_tree<> { * @param[in] last Point Iterator on the last point to be inserted. */ template - Alpha_complex(int dimension, size_type size, ForwardIterator firstPoint, ForwardIterator lastPoint) - : triangulation(nullptr) { - triangulation = new Delaunay_triangulation(dimension); - size_type inserted = triangulation->insert(firstPoint, lastPoint); + Alpha_complex(int dimension, size_type size, ForwardIterator firstPoint, ForwardIterator lastPoint, + Filtration_value max_alpha_square) + : triangulation_(nullptr), + max_alpha_square_(max_alpha_square) { + triangulation_ = new Delaunay_triangulation(dimension); + size_type inserted = triangulation_->insert(firstPoint, lastPoint); if (inserted != size) { std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << size << std::endl; - exit(-1); // ----- >> + exit(-1); // ----- >> } init(); } @@ -162,7 +159,7 @@ class Alpha_complex : public Simplex_tree<> { * @warning Deletes the Delaunay triangulation. */ ~Alpha_complex() { - delete triangulation; + delete triangulation_; } /** \brief get_point returns the point corresponding to the vertex given as parameter. @@ -173,17 +170,16 @@ class Alpha_complex : public Simplex_tree<> { Point_d get_point(Vertex_handle vertex) { Point_d point; try { - if (vertex_handle_to_iterator[vertex] != nullptr) { - point = vertex_handle_to_iterator[vertex]->point(); + if (vertex_handle_to_iterator_[vertex] != nullptr) { + point = vertex_handle_to_iterator_[vertex]->point(); } - } catch (...) { + } catch (...) { std::cerr << "Alpha_complex - getPoint not found on vertex " << vertex << std::endl; } return point; } private: - /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more @@ -192,108 +188,136 @@ class Alpha_complex : public Simplex_tree<> { * Initialization can be launched once. */ void init() { - if (triangulation == nullptr) { + if (triangulation_ == nullptr) { std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation" << std::endl; - return; // ----- >> + return; // ----- >> } - if (triangulation->number_of_vertices() < 1) { + if (triangulation_->number_of_vertices() < 1) { std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices" << std::endl; - return; // ----- >> + return; // ----- >> } - if (triangulation->maximal_dimension() < 1) { + if (triangulation_->maximal_dimension() < 1) { std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation" << std::endl; - return; // ----- >> + return; // ----- >> } if (num_vertices() > 0) { std::cerr << "Alpha_complex init - Cannot init twice" << std::endl; - return; // ----- >> + return; // ----- >> } - set_dimension(triangulation->maximal_dimension()); + set_dimension(triangulation_->maximal_dimension()); // -------------------------------------------------------------------------------------------- - // bimap to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa + // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa // Start to insert at handle = 0 - default integer value Vertex_handle vertex_handle = Vertex_handle(); // Loop on triangulation vertices list - for (CGAL_vertex_iterator vit = triangulation->vertices_begin(); vit != triangulation->vertices_end(); ++vit) { + for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { #ifdef DEBUG_TRACES std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES - vertex_iterator_to_handle[vit] = vertex_handle; - vertex_handle_to_iterator[vertex_handle] = vit; + vertex_iterator_to_handle_[vit] = vertex_handle; + vertex_handle_to_iterator_[vertex_handle] = vit; vertex_handle++; } // -------------------------------------------------------------------------------------------- + Filtration_value filtration_max = 0.0; // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list - for (auto cit = triangulation->finite_full_cells_begin(); cit != triangulation->finite_full_cells_end(); ++cit) { - Vector_vertex vertexVector; + for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { + Vector_vertex vertex_full_cell; #ifdef DEBUG_TRACES std::cout << "Simplex_tree insertion "; #endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { if (*vit != nullptr) { #ifdef DEBUG_TRACES - std::cout << " " << vertex_iterator_to_handle[*vit]; + std::cout << " " << vertex_iterator_to_handle_[*vit]; #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(vertex_iterator_to_handle[*vit]); + vertex_full_cell.push_back(vertex_iterator_to_handle_[*vit]); } } #ifdef DEBUG_TRACES std::cout << std::endl; #endif // DEBUG_TRACES - // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, - std::numeric_limits::quiet_NaN()); + + Simplex_tree<> full_cell; + full_cell.set_dimension(triangulation_->maximal_dimension()); + // Create a simplex tree containing only one of the full cells + Simplex_result insert_result = full_cell.insert_simplex_and_subfaces(vertex_full_cell); if (!insert_result.second) { std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; + exit(-1); // ----->> } - } - // -------------------------------------------------------------------------------------------- - - Filtration_value filtration_max = 0.0; - // -------------------------------------------------------------------------------------------- - // ### For i : d -> 0 - for (int decr_dim = dimension(); decr_dim >= 0; decr_dim--) { - // ### Foreach Sigma of dim i - for (auto f_simplex : skeleton_simplex_range(decr_dim)) { - int f_simplex_dim = dimension(f_simplex); - if (decr_dim == f_simplex_dim) { - Vector_of_CGAL_points pointVector; + bool skip_loop = false; + // +++ For i : d -> 0 + // This loop is skipped in case alpha²(Sigma) > max_alpha_square_ + for (int fc_decr_dim = full_cell.dimension(); (fc_decr_dim >= 0) && (!skip_loop); fc_decr_dim--) { + // +++ Foreach Sigma of dim i + // No need to skip this loop in case alpha²(Sigma) > max_alpha_square_ because of + // if (fc_decr_dim == f_simplex_dim) which means "only for a full cell" + for (auto fc_simplex : full_cell.skeleton_simplex_range(fc_decr_dim)) { + int f_simplex_dim = full_cell.dimension(fc_simplex); + if (fc_decr_dim == f_simplex_dim) { + Vector_of_CGAL_points pointVector; + Vector_vertex current_vertex; #ifdef DEBUG_TRACES - std::cout << "Sigma of dim " << decr_dim << " is"; + std::cout << "Sigma of dim " << fc_decr_dim << " is"; #endif // DEBUG_TRACES - for (auto vertex : simplex_vertex_range(f_simplex)) { - pointVector.push_back(get_point(vertex)); + for (auto vertex : full_cell.simplex_vertex_range(fc_simplex)) { + pointVector.push_back(get_point(vertex)); + current_vertex.push_back(vertex); #ifdef DEBUG_TRACES - std::cout << " " << vertex; + std::cout << " " << vertex; #endif // DEBUG_TRACES - } + } #ifdef DEBUG_TRACES - std::cout << std::endl; + std::cout << std::endl; #endif // DEBUG_TRACES - // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (isnan(filtration(f_simplex))) { - Filtration_value alpha_complex_filtration = 0.0; - // No need to compute squared_radius on a single point - alpha is 0.0 - if (f_simplex_dim > 0) { - // squared_radius function initialization - Squared_Radius squared_radius = kernel.compute_squared_radius_d_object(); - - alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); - } - assign_filtration(f_simplex, alpha_complex_filtration); - filtration_max = fmax(filtration_max, alpha_complex_filtration); + Simplex_handle sigma_handle = find(current_vertex); + // +++ If filt(Sigma) is NaN : filt(Sigma) = alpha²(Sigma) + if ((sigma_handle == null_simplex()) || isnan(filtration(sigma_handle))) { + Filtration_value alpha_complex_filtration = compute_alpha_square(pointVector.begin(), pointVector.end(), + f_simplex_dim); + if (alpha_complex_filtration <= max_alpha_square_) { + // Only insert Sigma in Simplex tree if alpha²(Sigma) <= max_alpha_square_ + if (sigma_handle == null_simplex()) { +#ifdef DEBUG_TRACES + std::cout << "Alpha_complex::init Sigma not found" << std::endl; +#endif // DEBUG_TRACES + insert_result = insert_simplex(current_vertex, std::numeric_limits::quiet_NaN()); + if (!insert_result.second) { + std::cerr << "Alpha_complex::init insert_simplex failed" << std::endl; + exit(-1); // ----->> + } + // Sigma is the new inserted simplex handle + sigma_handle = insert_result.first; + } #ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl; + std::cout << "Alpha_complex::init filtration = " << alpha_complex_filtration << std::endl; #endif // DEBUG_TRACES + assign_filtration(sigma_handle, alpha_complex_filtration); + filtration_max = fmax(filtration_max, alpha_complex_filtration); + } else { + // if alpha²(Sigma) > max_alpha_square_ go to the next full cell + skip_loop = true; +#ifdef DEBUG_TRACES + std::cout << "Alpha_complex::init skip loop on this full cell" << std::endl; +#endif // DEBUG_TRACES + break; + } + } // --- If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) + if (filtration(sigma_handle) <= max_alpha_square_) { + // Propagate alpha filtration value in Simplex tree if alpha²(Sigma) <= max_alpha_square_ + // in case Sigma is not found AND not inserted (alpha_complex_filtration > max_alpha_square_), + // filtration(null_simplex()) returns INFINITY => no propagation + propagate_alpha_filtration(full_cell, fc_simplex, fc_decr_dim, sigma_handle); + } } - propagate_alpha_filtration(f_simplex, decr_dim); - } - } + } // --- Foreach Sigma of dim i + } // --- For i : d -> 0 } // -------------------------------------------------------------------------------------------- @@ -303,41 +327,60 @@ class Alpha_complex : public Simplex_tree<> { set_filtration(filtration_max); } - template - void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { + template + Filtration_value compute_alpha_square(ForwardIterator firstPoint, ForwardIterator lastPoint, int f_simplex_dim) { + Filtration_value alpha_square_value = 0.0; + // No need to compute squared_radius on a single point - alpha is 0.0 + if (f_simplex_dim > 0) { + // squared_radius function initialization + Squared_Radius squared_radius = kernel_.compute_squared_radius_d_object(); + + alpha_square_value = squared_radius(firstPoint, lastPoint); + } + return alpha_square_value; + } + + void propagate_alpha_filtration(Simplex_tree& full_cell, Simplex_handle fc_simplex, int fc_decr_dim, + Simplex_handle sigma_handle) { // ### Foreach Tau face of Sigma - for (auto f_boundary : boundary_simplex_range(f_simplex)) { + for (auto f_boundary : full_cell.boundary_simplex_range(fc_simplex)) { #ifdef DEBUG_TRACES std::cout << " | --------------------------------------------------" << std::endl; std::cout << " | Tau "; - for (auto vertex : simplex_vertex_range(f_boundary)) { +#endif // DEBUG_TRACES + Vector_vertex tau_vertex; + for (auto vertex : full_cell.simplex_vertex_range(f_boundary)) { + tau_vertex.push_back(vertex); +#ifdef DEBUG_TRACES std::cout << vertex << " "; +#endif // DEBUG_TRACES } +#ifdef DEBUG_TRACES std::cout << "is a face of Sigma" << std::endl; - std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl; #endif // DEBUG_TRACES + Simplex_handle tau_handle = find(tau_vertex); // ### If filt(Tau) is not NaN - if (!isnan(filtration(f_boundary))) { + + if ((tau_handle != null_simplex()) && (!isnan(filtration(tau_handle)))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) - Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); - assign_filtration(f_boundary, alpha_complex_filtration); + Filtration_value alpha_complex_filtration = fmin(filtration(tau_handle), filtration(sigma_handle)); + assign_filtration(tau_handle, alpha_complex_filtration); // No need to check for filtration_max, alpha_complex_filtration is a min of an existing filtration value #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << alpha_complex_filtration << std::endl; #endif // DEBUG_TRACES - // ### Else } else { // No need to compute is_gabriel for dimension <= 2 // i.e. : Sigma = (3,1) => Tau = 1 - if (decr_dim > 1) { + if (fc_decr_dim > 1) { // insert the Tau points in a vector for is_gabriel function Vector_of_CGAL_points pointVector; Vertex_handle vertexForGabriel = Vertex_handle(); - for (auto vertex : simplex_vertex_range(f_boundary)) { + for (auto vertex : full_cell.simplex_vertex_range(f_boundary)) { pointVector.push_back(get_point(vertex)); } // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function - for (auto vertex : simplex_vertex_range(f_simplex)) { + for (auto vertex : simplex_vertex_range(sigma_handle)) { if (std::find(pointVector.begin(), pointVector.end(), get_point(vertex)) == pointVector.end()) { // vertex is not found in Tau vertexForGabriel = vertex; @@ -346,7 +389,7 @@ class Alpha_complex : public Simplex_tree<> { } } // is_gabriel function initialization - Is_Gabriel is_gabriel = kernel.side_of_bounded_sphere_d_object(); + Is_Gabriel is_gabriel = kernel_.side_of_bounded_sphere_d_object(); bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), get_point(vertexForGabriel)) != CGAL::ON_BOUNDED_SIDE; #ifdef DEBUG_TRACES @@ -354,23 +397,34 @@ class Alpha_complex : public Simplex_tree<> { #endif // DEBUG_TRACES // ### If Tau is not Gabriel of Sigma if (false == is_gab) { + if (tau_handle == null_simplex()) { +#ifdef DEBUG_TRACES + std::cout << " | Tau not found" << std::endl; +#endif // DEBUG_TRACES + // in case Tau is not yet created + Simplex_result insert_result = insert_simplex(tau_vertex, std::numeric_limits::quiet_NaN()); + if (!insert_result.second) { + std::cerr << "Alpha_complex::propagate_alpha_filtration insert_simplex failed" << std::endl; + exit(-1); // ----->> + } + // Sigma is the new inserted simplex handle + tau_handle = insert_result.first; + } // ### filt(Tau) = filt(Sigma) - Filtration_value alpha_complex_filtration = filtration(f_simplex); - assign_filtration(f_boundary, alpha_complex_filtration); + assign_filtration(tau_handle, filtration(sigma_handle)); // No need to check for filtration_max, alpha_complex_filtration is an existing filtration value #ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl; + std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(sigma_handle) << std::endl; #endif // DEBUG_TRACES } } } } } - }; -} // namespace alphacomplex +} // namespace alphacomplex -} // namespace Gudhi +} // namespace Gudhi -#endif // SRC_ALPHA_COMPLEX_INCLUDE_GUDHI_ALPHA_COMPLEX_H_ +#endif // ALPHA_COMPLEX_H_ diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index b7aceb5e..aa9500e7 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -24,15 +24,17 @@ #include #include #include -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" - #include #include -#include // float comparison +#include // float comparison #include +#include +#include + +// to construct a Delaunay_triangulation from a OFF file +#include "gudhi/Delaunay_triangulation_off_io.h" +#include "gudhi/Alpha_complex.h" // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d; @@ -45,9 +47,11 @@ BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { // // ---------------------------------------------------------------------------- std::string off_file_name("S4_100.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + double max_alpha_square_value = 1e10; + std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); const int DIMENSION = 4; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -59,8 +63,51 @@ BOOST_AUTO_TEST_CASE(S4_100_OFF_file) { const int NUMBER_OF_SIMPLICES = 6879; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + + // + TODO(VR) : in wait of num_simplices fix in Simplex_tree [ + int num_simplices = 0; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + num_simplices++; + } + std::cout << "num_simplices=" << num_simplices << std::endl; + BOOST_CHECK(num_simplices == NUMBER_OF_SIMPLICES); + // - TODO(VR) : in wait of num_simplices fix in Simplex_tree ] +} + +BOOST_AUTO_TEST_CASE(S4_100_OFF_file_filtered) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-complex from a OFF file + // + // ---------------------------------------------------------------------------- + std::string off_file_name("S4_100.off"); + double max_alpha_square_value = 0.999; + std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; + + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); + + const int DIMENSION = 4; + std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); + + const int NUMBER_OF_VERTICES = 13; // Versus 100, because of filtered alpha value + std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 90; // Versus 6879, because of filtered alpha value + std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; + // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + // + TODO(VR) : in wait of num_simplices fix in Simplex_tree [ + int num_simplices = 0; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + num_simplices++; + } + std::cout << "num_simplices=" << num_simplices << std::endl; + BOOST_CHECK(num_simplices == NUMBER_OF_SIMPLICES); + // - TODO(VR) : in wait of num_simplices fix in Simplex_tree ] } BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { @@ -70,9 +117,11 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { // // ---------------------------------------------------------------------------- std::string off_file_name("S8_10.off"); - std::cout << "========== OFF FILE NAME = " << off_file_name << " ==========" << std::endl; + double max_alpha_square_value = 1e10; + std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); const int DIMENSION = 8; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -84,7 +133,51 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file) { const int NUMBER_OF_SIMPLICES = 1007; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + + // + TODO(VR) : in wait of num_simplices fix in Simplex_tree [ + int num_simplices = 0; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + num_simplices++; + } + std::cout << "num_simplices=" << num_simplices << std::endl; + BOOST_CHECK(num_simplices == NUMBER_OF_SIMPLICES); + // - TODO(VR) : in wait of num_simplices fix in Simplex_tree ] +} + +BOOST_AUTO_TEST_CASE(S8_10_OFF_file_filtered) { + // ---------------------------------------------------------------------------- + // + // Init of an alpha-complex from a OFF file + // + // ---------------------------------------------------------------------------- + std::string off_file_name("S8_10.off"); + double max_alpha_square_value = 1.0; + std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << + max_alpha_square_value << "==========" << std::endl; + + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); + + const int DIMENSION = 8; + std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); + + const int NUMBER_OF_VERTICES = 10; + std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); + + const int NUMBER_OF_SIMPLICES = 895; // Versus 1007, because of filtered alpha value + std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; + // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); + + // + TODO(VR) : in wait of num_simplices fix in Simplex_tree [ + int num_simplices = 0; + for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { + num_simplices++; + } + std::cout << "num_simplices=" << num_simplices << std::endl; + BOOST_CHECK(num_simplices == NUMBER_OF_SIMPLICES); + // - TODO(VR) : in wait of num_simplices fix in Simplex_tree ] } bool are_almost_the_same(float a, float b) { @@ -100,57 +193,53 @@ typedef std::vector Vector_of_points; bool is_point_in_list(Vector_of_points points_list, Point point) { for (auto& point_in_list : points_list) { if (point_in_list == point) { - return true; // point found + return true; // point found } } - return false; // point not found + return false; // point not found } BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { - // ---------------------------------------------------------------------------- // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - std::vector coords; - - points.clear(); - coords.clear(); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(1.0); + std::vector coords = { 0.0, 0.0, 0.0, 1.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(1.0); - coords.push_back(0.0); + coords = { 0.0, 0.0, 1.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(0.0); - coords.push_back(1.0); - coords.push_back(0.0); - coords.push_back(0.0); + coords = { 0.0, 1.0, 0.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords.clear(); - coords.push_back(1.0); - coords.push_back(0.0); - coords.push_back(0.0); - coords.push_back(0.0); + coords = { 1.0, 0.0, 0.0, 0.0 }; points.push_back(Point(coords.begin(), coords.end())); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end()); + double max_alpha_square_value = 1e10; + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points.size(), points.begin(), points.end(), + max_alpha_square_value); std::cout << "========== Alpha_complex_from_points ==========" << std::endl; + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + int num_simplices = 0; // TODO(VR) : in wait of num_simplices fix in Simplex_tree + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + num_simplices++; // TODO(VR) : in wait of num_simplices fix in Simplex_tree + std::cout << " ( "; + for (auto vertex : alpha_complex_from_points.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << alpha_complex_from_points.filtration(f_simplex) << "] "; + std::cout << std::endl; + } + std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_points.dimension() == 4); - std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; - BOOST_CHECK(alpha_complex_from_points.num_simplices() == 15); + // TODO(VR) : std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() + // << std::endl; + // TODO(VR) : BOOST_CHECK(alpha_complex_from_points.num_simplices() == 15); + BOOST_CHECK(num_simplices == 15); // TODO(VR) : in wait of num_simplices fix in Simplex_tree std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_points.num_vertices() == 4); @@ -169,11 +258,11 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 3.0/4.0)); break; default: - BOOST_CHECK(false); // Shall not happen + BOOST_CHECK(false); // Shall not happen break; } } - + Point p1 = alpha_complex_from_points.get_point(1); std::cout << "alpha_complex_from_points.get_point(1)=" << p1 << std::endl; BOOST_CHECK(4 == p1.dimension()); @@ -205,5 +294,4 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { Point p1234 = alpha_complex_from_points.get_point(1234); std::cout << "alpha_complex_from_points.get_point(1234)=" << p1234.dimension() << std::endl; BOOST_CHECK(!is_point_in_list(points, p1234)); - } -- cgit v1.2.3 From 3d47e5f4f22e82f2af246ae7d67f19307d57a053 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 18 Aug 2015 06:56:11 +0000 Subject: It is not the loop that must be skipped, but only the propagation, otherwise, points are missed. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@739 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ce88511e64685ee68630db77eddc922dcf8a016e --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 06e69cf3..71d34229 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -168,7 +168,7 @@ class Alpha_complex : public Simplex_tree<> { * @return The founded point. */ Point_d get_point(Vertex_handle vertex) { - Point_d point; + Point_d point(dimension()); try { if (vertex_handle_to_iterator_[vertex] != nullptr) { point = vertex_handle_to_iterator_[vertex]->point(); @@ -251,10 +251,8 @@ class Alpha_complex : public Simplex_tree<> { std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; exit(-1); // ----->> } - bool skip_loop = false; // +++ For i : d -> 0 - // This loop is skipped in case alpha²(Sigma) > max_alpha_square_ - for (int fc_decr_dim = full_cell.dimension(); (fc_decr_dim >= 0) && (!skip_loop); fc_decr_dim--) { + for (int fc_decr_dim = full_cell.dimension(); (fc_decr_dim >= 0); fc_decr_dim--) { // +++ Foreach Sigma of dim i // No need to skip this loop in case alpha²(Sigma) > max_alpha_square_ because of // if (fc_decr_dim == f_simplex_dim) which means "only for a full cell" @@ -277,6 +275,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << std::endl; #endif // DEBUG_TRACES Simplex_handle sigma_handle = find(current_vertex); + bool skip_propagation = false; // +++ If filt(Sigma) is NaN : filt(Sigma) = alpha²(Sigma) if ((sigma_handle == null_simplex()) || isnan(filtration(sigma_handle))) { Filtration_value alpha_complex_filtration = compute_alpha_square(pointVector.begin(), pointVector.end(), @@ -301,15 +300,14 @@ class Alpha_complex : public Simplex_tree<> { assign_filtration(sigma_handle, alpha_complex_filtration); filtration_max = fmax(filtration_max, alpha_complex_filtration); } else { - // if alpha²(Sigma) > max_alpha_square_ go to the next full cell - skip_loop = true; + // if alpha²(Sigma) > max_alpha_square_ skip propagation + skip_propagation = true; #ifdef DEBUG_TRACES - std::cout << "Alpha_complex::init skip loop on this full cell" << std::endl; + std::cout << "Alpha_complex::init skip propagation on this full cell" << std::endl; #endif // DEBUG_TRACES - break; } } // --- If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) - if (filtration(sigma_handle) <= max_alpha_square_) { + if ((filtration(sigma_handle) <= max_alpha_square_) && !skip_propagation) { // Propagate alpha filtration value in Simplex tree if alpha²(Sigma) <= max_alpha_square_ // in case Sigma is not found AND not inserted (alpha_complex_filtration > max_alpha_square_), // filtration(null_simplex()) returns INFINITY => no propagation -- cgit v1.2.3 From 2ca2d175f0b49ff267d9a99e5a4c0a5f03e0d30c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 18 Aug 2015 12:45:13 +0000 Subject: exception throw on get_point not found git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@740 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fd2efc725a140f978d2624fe7879dc32f5566ab0 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 13 +++++-------- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 20 ++++++-------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 71d34229..213436e0 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -166,17 +166,14 @@ class Alpha_complex : public Simplex_tree<> { * * @param[in] vertex Vertex handle of the point to retrieve. * @return The founded point. + * @warning Exception std::out_of_range is thrown in case vertex is not in the map vertex_handle_to_iterator_. */ Point_d get_point(Vertex_handle vertex) { - Point_d point(dimension()); - try { - if (vertex_handle_to_iterator_[vertex] != nullptr) { - point = vertex_handle_to_iterator_[vertex]->point(); - } - } catch (...) { - std::cerr << "Alpha_complex - getPoint not found on vertex " << vertex << std::endl; + if (vertex_handle_to_iterator_[vertex] != nullptr) { + return vertex_handle_to_iterator_[vertex]->point(); + } else { + throw std::out_of_range("Vertex out of vector range"); } - return point; } private: diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index aa9500e7..c15f07e1 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -92,11 +92,11 @@ BOOST_AUTO_TEST_CASE(S4_100_OFF_file_filtered) { std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; BOOST_CHECK(alpha_complex_from_file.dimension() == DIMENSION); - const int NUMBER_OF_VERTICES = 13; // Versus 100, because of filtered alpha value + const int NUMBER_OF_VERTICES = 100; std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 90; // Versus 6879, because of filtered alpha value + const int NUMBER_OF_SIMPLICES = 5966; // Versus 6879, because of filtered alpha value std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); @@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE(S8_10_OFF_file_filtered) { std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 895; // Versus 1007, because of filtered alpha value + const int NUMBER_OF_SIMPLICES = 1004; // Versus 1007, because of filtered alpha value std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; // TODO(VR) : BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); @@ -283,15 +283,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { BOOST_CHECK(4 == p4.dimension()); BOOST_CHECK(is_point_in_list(points, p4)); - Point p5 = alpha_complex_from_points.get_point(5); - std::cout << "alpha_complex_from_points.get_point(5)=" << p5 << std::endl; - BOOST_CHECK(!is_point_in_list(points, p5)); - - Point p0 = alpha_complex_from_points.get_point(0); - std::cout << "alpha_complex_from_points.get_point(0)=" << p0 << std::endl; - BOOST_CHECK(!is_point_in_list(points, p0)); - - Point p1234 = alpha_complex_from_points.get_point(1234); - std::cout << "alpha_complex_from_points.get_point(1234)=" << p1234.dimension() << std::endl; - BOOST_CHECK(!is_point_in_list(points, p1234)); + BOOST_CHECK_THROW (alpha_complex_from_points.get_point(5), std::out_of_range); + BOOST_CHECK_THROW (alpha_complex_from_points.get_point(0), std::out_of_range); + BOOST_CHECK_THROW (alpha_complex_from_points.get_point(1234), std::out_of_range); } -- cgit v1.2.3 From 7955e76b2d410f373809a296de740c225456a0dd Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 24 Aug 2015 12:07:36 +0000 Subject: get_point is const git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@754 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fb4be75f9438bab94b68f551ae3bde73c980d131 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 518d1792..04fb185c 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -166,7 +166,7 @@ class Alpha_complex : public Simplex_tree<> { * @return The founded point. * @warning Exception std::out_of_range is thrown in case vertex is not in the map vertex_handle_to_iterator_. */ - Point_d get_point(Vertex_handle vertex) { + Point_d get_point(Vertex_handle vertex) const { auto found_it = vertex_handle_to_iterator_.find(vertex); if (found_it != vertex_handle_to_iterator_.end()) { return found_it->second->point(); -- cgit v1.2.3 From cb82907d03e3f875a418efc52570970c01c2677d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 31 Aug 2015 14:21:29 +0000 Subject: insert_simplex_and_subfaces no more factoriel complexity. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@764 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 34fd4f5e0221a3899ec98a0cdcbdc83fb83bf463 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 12 ++--- src/Simplex_tree/include/gudhi/Simplex_tree.h | 71 +++++++++++++++++-------- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 04fb185c..d8568be0 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -219,7 +219,7 @@ class Alpha_complex : public Simplex_tree<> { } } // -------------------------------------------------------------------------------------------- - + // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { @@ -242,10 +242,6 @@ class Alpha_complex : public Simplex_tree<> { // Insert each simplex and its subfaces in the simplex tree - filtration is NaN Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); - if (!insert_result.second) { - std::cerr << "Alpha_complex::init insert_simplex_and_subfaces failed" << std::endl; - exit(-1); // ----->> - } } // -------------------------------------------------------------------------------------------- @@ -324,8 +320,10 @@ class Alpha_complex : public Simplex_tree<> { pointVector.push_back(get_point(vertex)); } // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function + Point_d point_for_gabriel; for (auto vertex : simplex_vertex_range(f_simplex)) { - if (std::find(pointVector.begin(), pointVector.end(), get_point(vertex)) == pointVector.end()) { + point_for_gabriel = get_point(vertex); + if (std::find(pointVector.begin(), pointVector.end(), point_for_gabriel) == pointVector.end()) { // vertex is not found in Tau vertexForGabriel = vertex; // No need to continue loop @@ -334,7 +332,7 @@ class Alpha_complex : public Simplex_tree<> { } // is_gabriel function initialization Is_Gabriel is_gabriel = kernel_.side_of_bounded_sphere_d_object(); - bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), get_point(vertexForGabriel)) + bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), point_for_gabriel) != CGAL::ON_BOUNDED_SIDE; #ifdef DEBUG_TRACES std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index fe2faf90..bda7e72a 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -515,33 +515,62 @@ class Simplex_tree { * @param[in] filtration the filtration value assigned to the new N-simplex. */ template - std::pair insert_simplex_and_subfaces(RandomAccessVertexRange& Nsimplex, + std::pair insert_simplex_and_subfaces(const RandomAccessVertexRange& Nsimplex, Filtration_value filtration = 0.0) { - std::pair returned; - if (Nsimplex.size() > 1) { - for (unsigned int NIndex = 0; NIndex < Nsimplex.size(); NIndex++) { - // insert N (N-1)-Simplex - RandomAccessVertexRange NsimplexMinusOne; - for (unsigned int NListIter = 0; NListIter < Nsimplex.size() - 1; NListIter++) { - // (N-1)-Simplex creation - NsimplexMinusOne.push_back(Nsimplex[(NIndex + NListIter) % Nsimplex.size()]); - } - // (N-1)-Simplex recursive call - returned = insert_simplex_and_subfaces(NsimplexMinusOne, filtration); + // Simplex copy + std::vector the_simplex(Nsimplex.begin(), Nsimplex.end()); + // must be sorted in increasing order + std::sort(the_simplex.begin(), the_simplex.end()); + std::vector> to_be_inserted; + std::vector> to_be_propagated; + return rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration); + } + + private: + std::pair rec_insert_simplex_and_subfaces(std::vector& the_simplex, + std::vector>& to_be_inserted, + std::vector>& to_be_propagated, + Filtration_value filtration = 0.0) { + std::pair insert_result; + if (the_simplex.size() > 1) { + // Get and remove last vertex + Vertex_handle last_vertex= the_simplex.back(); + the_simplex.pop_back(); + // Recursive call after last vertex removal + insert_result = rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration); + + // Concatenation of to_be_inserted and to_be_propagated + to_be_inserted.insert(to_be_inserted.end(), to_be_propagated.begin(), to_be_propagated.end()); + to_be_propagated = to_be_inserted; + + // to_be_inserted treatment + for (auto& simplex_tbi : to_be_inserted) { + simplex_tbi.push_back(last_vertex); } - // N-Simplex insert - returned = insert_simplex(Nsimplex, filtration); - if (returned.second == true) { + std::vector last_simplex(1, last_vertex); + to_be_inserted.push_back(last_simplex); + + for (auto& simplex_tbi : to_be_inserted) { + insert_result = insert_simplex(simplex_tbi, filtration); } - } else if (Nsimplex.size() == 1) { - // 1-Simplex insert - End of recursivity - returned = insert_simplex(Nsimplex, filtration); - if (returned.second == true) { + + + } else if (the_simplex.size() == 1) { + // When reaching the end of recursivity, vector of simplices shall be empty and filled on back recursive + if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)){ + std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty" << std::endl; + exit(-1); } + std::vector first_simplex(1, the_simplex.back()); + to_be_inserted.push_back(first_simplex); + + insert_result = insert_simplex(first_simplex, filtration); } else { - // Nothing to insert - empty vector + std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error" << std::endl; + exit(-1); } - return returned; + + return insert_result; } public: -- cgit v1.2.3 From 4b44247f14ddd84bf3e58ba53fe93a3e793f0ce4 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 1 Sep 2015 07:50:33 +0000 Subject: Documentation fix (starts at 0 and not 1 + alpha shape was not correct) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@765 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 99f8d4cd274778f5d7aac04afa84b780dc3678ec --- src/Alpha_complex/doc/Intro_alpha_complex.h | 10 +-- src/Alpha_complex/doc/alpha_complex_doc.ipe | 64 ++++++++--------- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 46226 -> 64997 bytes src/Alpha_complex/doc/alpha_complex_doc_135.ipe | 78 ++++++++++----------- src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 94098 -> 120335 bytes .../doc/alpha_complex_doc_alpha_shape.ipe | 75 +++++++++----------- .../doc/alpha_complex_doc_alpha_shape.png | Bin 70425 -> 136492 bytes 7 files changed, 108 insertions(+), 119 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 34af2b98..d266219b 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -35,7 +35,7 @@ namespace alphacomplex { * * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation. * - * The filtration value of each simplex is computed from the alpha value of the simplex if it is Gabriel or + * The filtration value of each simplex is computed from the alpha square value of the simplex if it is Gabriel or * from the alpha value of the simplex coface that makes the simplex not Gabriel. * * Please refer to \cite AlphaShapesDefinition for a more complete alpha complex definition. @@ -54,7 +54,7 @@ namespace alphacomplex { * * When launching: * - * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off + * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off 60.0 * \endcode * * the program output is: @@ -77,7 +77,7 @@ namespace alphacomplex { * \For{i : dimension $\rightarrow$ 1} * \ForAll{$\sigma$ of dimension i} * \If {filtration($\sigma$) is NaN} - * \State filtration($\sigma$) = $\alpha(\sigma)$ + * \State filtration($\sigma$) = $\alpha^2(\sigma)$ * \EndIf * \ForAll{$\tau$ face of $\sigma$} \Comment{propagate alpha filtration value} * \If {filtration($\tau$) is not NaN} @@ -105,8 +105,8 @@ namespace alphacomplex { * * \section alpha-shape Alpha shape * - * In the example above, the alpha shape of \f$\alpha_{74} < \alpha < \alpha_{73}\f$ is the alpha complex where the - * \f$\alpha_{74} <\f$ filtration value \f$< \alpha_{73}\f$ as described in \cite AlphaShapesIntroduction + * In the example above, the alpha shape of \f$\alpha^2_{74} < \alpha^2 < \alpha^2_{73}\f$ is the alpha complex where the + * \f$\alpha^2_{74} <\f$ filtration value \f$< \alpha^2_{73}\f$ as described in \cite AlphaShapesIntroduction * * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" * \copyright GNU General Public License v3. diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe index 6257b2f4..b5601143 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -1,7 +1,7 @@ - + @@ -260,13 +260,13 @@ h 320 580 l Delaunay triangulation -1 -2 -3 -4 -5 -6 -7 +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -285,30 +285,30 @@ h 320 580 l 280 660 l -1 -2 -3 -3 -2 -3 -3 -4 -4 -4 -4 -5 -5 -5 -5 -7 -7 -7 -7 -7 -7 -6 -7 -6 +0 +1 +2 +2 +1 +2 +2 +3 +3 +3 +3 +4 +4 +4 +4 +6 +6 +6 +6 +6 +6 +5 +6 +5 4 0 0 4 320 704 e diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index ff51ea9a..297c39ae 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc.png and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe index df55639a..28b893b8 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe @@ -1,7 +1,7 @@ - + @@ -259,14 +259,14 @@ h 350 520 l 320 580 l -Cell [5,3,1] -1 -2 -3 -4 -5 -6 -7 +Cell [4,2,0] +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -293,7 +293,7 @@ h 243.428 591.569 m 186.061 643.28 l -$\alpha_{531}$ +$\alpha_{420}$ @@ -321,16 +321,16 @@ h 350 520 l 320 580 l -[3,1] is Gabriel $\rightarrow$ $\alpha_{31}$ is not$\\$ +[2,0] is Gabriel $\rightarrow$ $\alpha_{20}$ is not$\\$ modified (NaN) -1 -2 -3 -4 -5 -6 -7 +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -349,7 +349,7 @@ modified (NaN) 320 580 l 280 660 l -$\alpha_{31}$ +$\alpha_{20}$ 290 530 m 320 580 l @@ -389,14 +389,14 @@ modified (NaN) 350 520 l 320 580 l -[1,5] is not Gabriel $\rightarrow$ $\alpha_{15} = \alpha_{135}$ -1 -2 -3 -4 -5 -6 -7 +[0,4] is not Gabriel $\rightarrow$ $\alpha_{40} = \alpha_{420}$ +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -415,7 +415,7 @@ modified (NaN) 320 580 l 280 660 l -$\alpha_{15}$ +$\alpha_{40}$ 290 530 m 280 660 l @@ -450,12 +450,12 @@ modified (NaN) 350 520 l 320 580 l -1 -2 -3 -4 -6 -7 +0 +1 +2 +3 +5 +6 280 660 m 300 710 l @@ -474,8 +474,8 @@ modified (NaN) 320 580 l 280 660 l -$\alpha_{35}$ -5 +$\alpha_{42}$ +4 406.093 497.775 m 446.094 418.092 l @@ -488,7 +488,7 @@ modified (NaN) 425.854 457.774 m 470.795 457.774 l -[3,5] is Gabriel $\rightarrow$ $\alpha_{35}$ is not modified (NaN) +[2,4] is Gabriel $\rightarrow$ $\alpha_{42}$ is not modified (NaN) 205.028 596.091 m @@ -502,9 +502,9 @@ modified (NaN) 341.123 594.316 m 413.904 554.079 l -For all faces of [5,3,1] +For all faces of [4,2,0] N.B. : is Gabriel on a single point has no sense. -Dimension =2 - $\sigma$ = [5,3,1] +Dimension =2 - $\sigma$ = [4,2,0] 247.333 430.892 m diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png index edf61368..8ce6a426 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_135.png and b/src/Alpha_complex/doc/alpha_complex_doc_135.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe index 192ea772..7563cf3d 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe @@ -1,7 +1,7 @@ - + @@ -240,37 +240,37 @@ h Alpha shape -1 -2 -3 -4 -5 -6 -7 -1 -2 -3 -3 -2 -3 -3 -4 -4 -4 -4 -5 -5 -5 -5 -7 -7 -7 -7 -7 -7 -6 -7 -6 +0 +1 +2 +3 +4 +5 +6 +0 +1 +2 +2 +1 +2 +2 +3 +3 +3 +3 +4 +4 +4 +4 +6 +6 +6 +6 +6 +6 +5 +6 +5 4 0 0 4 320 704 e @@ -398,15 +398,9 @@ h 58.1341 0 0 58.1341 218.925 692.601 e - -58.1341 0 0 58.1341 218.925 692.601 e - 58.1341 0 0 58.1341 218.925 692.601 e - -58.1341 0 0 58.1341 218.925 692.601 e - 58.1341 0 0 58.1341 218.925 692.601 e @@ -449,11 +443,6 @@ h 80 580 l -80 580 m -110 520 l -110 520 l - - 130 580 m 130 690 l diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png index 516de126..87da0884 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png and b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png differ -- cgit v1.2.3 From cdd296b1c849cde74835d4043b9c4ecfe0ab16c2 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 1 Sep 2015 08:04:55 +0000 Subject: doc images size was not correct. bad cut in simplex_tree.h (assign_key was badly removed). git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@766 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 05761f615e4518d7816c08121402980625409014 --- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 64997 -> 46746 bytes src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 120335 -> 127130 bytes .../doc/alpha_complex_doc_alpha_shape.png | Bin 136492 -> 62759 bytes src/Simplex_tree/include/gudhi/Simplex_tree.h | 6 ++++++ 4 files changed, 6 insertions(+) diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index 297c39ae..601ac051 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc.png and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png index 8ce6a426..5dce5edd 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_135.png and b/src/Alpha_complex/doc/alpha_complex_doc_135.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png index 87da0884..2d5f59a3 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png and b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png differ diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index bda7e72a..4a75852e 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -574,6 +574,12 @@ class Simplex_tree { } public: + /** \brief Assign a value 'key' to the key of the simplex + * represented by the Simplex_handle 'sh'. */ + void assign_key(Simplex_handle sh, Simplex_key key) { + sh->second.assign_key(key); + } + /** Returns the two Simplex_handle corresponding to the endpoints of * and edge. sh must point to a 1-dimensional simplex. This is an * optimized version of the boundary computation. */ -- cgit v1.2.3 From 0d55fc06c82882327a8af82b20fc001b7cd71a66 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 1 Sep 2015 13:55:49 +0000 Subject: order was not correct in rec_insert_simplex_and_subfaces. + UT fix according to this fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@767 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a6c7bcc3776e01c2247fbd862b4a3842b76aefe0 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 13 ++- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 139 +++++++++++++++-------- 2 files changed, 104 insertions(+), 48 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 4a75852e..279327f7 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -540,7 +540,7 @@ class Simplex_tree { insert_result = rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration); // Concatenation of to_be_inserted and to_be_propagated - to_be_inserted.insert(to_be_inserted.end(), to_be_propagated.begin(), to_be_propagated.end()); + to_be_inserted.insert(to_be_inserted.begin(), to_be_propagated.begin(), to_be_propagated.end()); to_be_propagated = to_be_inserted; // to_be_inserted treatment @@ -548,8 +548,14 @@ class Simplex_tree { simplex_tbi.push_back(last_vertex); } std::vector last_simplex(1, last_vertex); - to_be_inserted.push_back(last_simplex); - + to_be_inserted.insert(to_be_inserted.begin(), last_simplex); + // i.e. (0,1,2) => + // [to_be_inserted | to_be_propagated] = [(1) (0,1) | (0)] + // [to_be_inserted | to_be_propagated] = [(2) (0,2) (1,2) (0,1,2) | (0) (1) (0,1)] + // N.B. : it is important the last inserted to be the highest in dimension + // in order to return the "last" insert_simplex result + + // insert all to_be_inserted for (auto& simplex_tbi : to_be_inserted) { insert_result = insert_simplex(simplex_tbi, filtration); } @@ -562,6 +568,7 @@ class Simplex_tree { exit(-1); } std::vector first_simplex(1, the_simplex.back()); + // i.e. (0,1,2) => [to_be_inserted | to_be_propagated] = [(0) | ] to_be_inserted.push_back(first_simplex); insert_result = insert_simplex(first_simplex, filtration); diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 20403e2a..9340aaa3 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -157,16 +157,16 @@ void set_and_test_simplex_tree_dim_fil(typeST& simplexTree, int vectorSize, cons std::cout << " set_and_test_simplex_tree_dim_fil - max_fil=" << max_fil << std::endl; } - + BOOST_CHECK(simplexTree.dimension() == dim_max); BOOST_CHECK(AreAlmostTheSame(simplexTree.filtration(), max_fil)); // Another way to count simplices: - long long int num_simp = 0; + size_t num_simp = 0; for (auto f_simplex : simplexTree.complex_simplex_range()) { num_simp++; } - + BOOST_CHECK(simplexTree.num_simplices() == num_simp); } @@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ FIRST std::cout << " - INSERT 0" << std::endl; - typeVectorVertex firstSimplexVector { 0 }; + typeVectorVertex firstSimplexVector{0}; BOOST_CHECK(firstSimplexVector.size() == 1); typeSimplex firstSimplex = std::make_pair(firstSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); typePairSimplexBool returnValue = st.insert_simplex(firstSimplex.first, firstSimplex.second); @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ SECOND std::cout << " - INSERT 1" << std::endl; - typeVectorVertex secondSimplexVector { 1 }; + typeVectorVertex secondSimplexVector{1}; BOOST_CHECK(secondSimplexVector.size() == 1); typeSimplex secondSimplex = std::make_pair(secondSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); returnValue = st.insert_simplex(secondSimplex.first, secondSimplex.second); @@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ THIRD std::cout << " - INSERT (0,1)" << std::endl; - typeVectorVertex thirdSimplexVector { 0, 1 }; + typeVectorVertex thirdSimplexVector{0, 1}; BOOST_CHECK(thirdSimplexVector.size() == 2); typeSimplex thirdSimplex = std::make_pair(thirdSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); returnValue = st.insert_simplex(thirdSimplex.first, thirdSimplex.second); @@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ FOURTH std::cout << " - INSERT 2" << std::endl; - typeVectorVertex fourthSimplexVector { 2 }; + typeVectorVertex fourthSimplexVector{2}; BOOST_CHECK(fourthSimplexVector.size() == 1); typeSimplex fourthSimplex = std::make_pair(fourthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); returnValue = st.insert_simplex(fourthSimplex.first, fourthSimplex.second); @@ -243,7 +243,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ FIFTH std::cout << " - INSERT (2,0)" << std::endl; - typeVectorVertex fifthSimplexVector { 2, 0 }; + typeVectorVertex fifthSimplexVector{2, 0}; BOOST_CHECK(fifthSimplexVector.size() == 2); typeSimplex fifthSimplex = std::make_pair(fifthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); returnValue = st.insert_simplex(fifthSimplex.first, fifthSimplex.second); @@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ SIXTH std::cout << " - INSERT (2,1)" << std::endl; - typeVectorVertex sixthSimplexVector { 2, 1 }; + typeVectorVertex sixthSimplexVector{2, 1}; BOOST_CHECK(sixthSimplexVector.size() == 2); typeSimplex sixthSimplex = std::make_pair(sixthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); returnValue = st.insert_simplex(sixthSimplex.first, sixthSimplex.second); @@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ SEVENTH std::cout << " - INSERT (2,1,0)" << std::endl; - typeVectorVertex seventhSimplexVector { 2, 1, 0 }; + typeVectorVertex seventhSimplexVector{2, 1, 0}; BOOST_CHECK(seventhSimplexVector.size() == 3); typeSimplex seventhSimplex = std::make_pair(seventhSimplexVector, Filtration_value(THIRD_FILTRATION_VALUE)); returnValue = st.insert_simplex(seventhSimplex.first, seventhSimplex.second); @@ -276,7 +276,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ EIGHTH std::cout << " - INSERT 3" << std::endl; - typeVectorVertex eighthSimplexVector { 3 }; + typeVectorVertex eighthSimplexVector{3}; BOOST_CHECK(eighthSimplexVector.size() == 1); typeSimplex eighthSimplex = std::make_pair(eighthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); returnValue = st.insert_simplex(eighthSimplex.first, eighthSimplex.second); @@ -287,7 +287,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ NINETH std::cout << " - INSERT (3,0)" << std::endl; - typeVectorVertex ninethSimplexVector { 3, 0 }; + typeVectorVertex ninethSimplexVector{3, 0}; BOOST_CHECK(ninethSimplexVector.size() == 2); typeSimplex ninethSimplex = std::make_pair(ninethSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); returnValue = st.insert_simplex(ninethSimplex.first, ninethSimplex.second); @@ -298,7 +298,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ TENTH std::cout << " - INSERT 0 (already inserted)" << std::endl; - typeVectorVertex tenthSimplexVector { 0 }; + typeVectorVertex tenthSimplexVector{0}; BOOST_CHECK(tenthSimplexVector.size() == 1); // With a different filtration value typeSimplex tenthSimplex = std::make_pair(tenthSimplexVector, Filtration_value(FOURTH_FILTRATION_VALUE)); @@ -313,7 +313,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // ++ ELEVENTH std::cout << " - INSERT (2,1,0) (already inserted)" << std::endl; - typeVectorVertex eleventhSimplexVector { 2, 1, 0 }; + typeVectorVertex eleventhSimplexVector{2, 1, 0}; BOOST_CHECK(eleventhSimplexVector.size() == 3); typeSimplex eleventhSimplex = std::make_pair(eleventhSimplexVector, Filtration_value(FOURTH_FILTRATION_VALUE)); returnValue = st.insert_simplex(eleventhSimplex.first, eleventhSimplex.second); @@ -375,60 +375,122 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { } +bool sort_in_decr_order (Vertex_handle i,Vertex_handle j) { return (i>j); } + BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { - // TEST OF INSERTION + // TEST OF INSERTION WITH SUBFACES std::cout << "********************************************************************" << std::endl; - std::cout << "TEST OF INSERTION" << std::endl; + std::cout << "TEST OF INSERTION WITH SUBFACES" << std::endl; typeST st; + typePairSimplexBool returnValue; + int position = 0; // ++ FIRST std::cout << " - INSERT (2,1,0)" << std::endl; - typeVectorVertex SimplexVector1 { 2, 1, 0 }; + typeVectorVertex SimplexVector1{2, 1, 0}; BOOST_CHECK(SimplexVector1.size() == 3); - st.insert_simplex_and_subfaces(SimplexVector1); + returnValue = st.insert_simplex_and_subfaces(SimplexVector1); BOOST_CHECK(st.num_vertices() == (size_t) 3); // +3 (2, 1 and 0 are not existing) + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector1.begin(), SimplexVector1.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector1[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector1[position]); + position++; + } + // ++ SECOND std::cout << " - INSERT 3" << std::endl; - typeVectorVertex SimplexVector2 { 3 }; + typeVectorVertex SimplexVector2{3}; BOOST_CHECK(SimplexVector2.size() == 1); - st.insert_simplex_and_subfaces(SimplexVector2); + returnValue = st.insert_simplex_and_subfaces(SimplexVector2); BOOST_CHECK(st.num_vertices() == (size_t) 4); // +1 (3 is not existing) + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector2.begin(), SimplexVector2.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector2[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector2[position]); + position++; + } + // ++ THIRD std::cout << " - INSERT (0,3)" << std::endl; - typeVectorVertex SimplexVector3 { 3, 0 }; + typeVectorVertex SimplexVector3{3, 0}; BOOST_CHECK(SimplexVector3.size() == 2); - st.insert_simplex_and_subfaces(SimplexVector3); + returnValue = st.insert_simplex_and_subfaces(SimplexVector3); BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented (all are existing) + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector3.begin(), SimplexVector3.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector3[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector3[position]); + position++; + } + // ++ FOURTH std::cout << " - INSERT (1,0) (already inserted)" << std::endl; - typeVectorVertex SimplexVector4 { 1, 0 }; + typeVectorVertex SimplexVector4{1, 0}; BOOST_CHECK(SimplexVector4.size() == 2); - st.insert_simplex_and_subfaces(SimplexVector4); + returnValue = st.insert_simplex_and_subfaces(SimplexVector4); BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented (all are existing) + // Check it was not inserted (already there from {2,1,0} insertion) + BOOST_CHECK(false == returnValue.second); + // ++ FIFTH std::cout << " - INSERT (3,4,5)" << std::endl; - typeVectorVertex SimplexVector5 { 3, 4, 5 }; + typeVectorVertex SimplexVector5{3, 4, 5}; BOOST_CHECK(SimplexVector5.size() == 3); - st.insert_simplex_and_subfaces(SimplexVector5); + returnValue = st.insert_simplex_and_subfaces(SimplexVector5); BOOST_CHECK(st.num_vertices() == (size_t) 6); + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector5.begin(), SimplexVector5.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector5[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector5[position]); + position++; + } + // ++ SIXTH std::cout << " - INSERT (0,1,6,7)" << std::endl; - typeVectorVertex SimplexVector6 { 0, 1, 6, 7 }; + typeVectorVertex SimplexVector6{0, 1, 6, 7}; BOOST_CHECK(SimplexVector6.size() == 4); - st.insert_simplex_and_subfaces(SimplexVector6); + returnValue = st.insert_simplex_and_subfaces(SimplexVector6); BOOST_CHECK(st.num_vertices() == (size_t) 8); // +2 (6 and 7 are not existing - 0 and 1 are already existing) + // Check it is well inserted + BOOST_CHECK(true == returnValue.second); + position = 0; + std::sort(SimplexVector6.begin(), SimplexVector6.end(), sort_in_decr_order); + for (auto vertex : st.simplex_vertex_range(returnValue.first)) { + // Check returned Simplex_handle + std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector6[position] << std::endl; + BOOST_CHECK(vertex == SimplexVector6[position]); + position++; + } + /* Inserted simplex: */ /* 1 6 */ /* o---o */ @@ -444,23 +506,10 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { /* A facet [3,4,5] */ /* A cell [0,1,6,7] */ - typeSimplex simplexPair1 = std::make_pair(SimplexVector1, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair2 = std::make_pair(SimplexVector2, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair3 = std::make_pair(SimplexVector3, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair4 = std::make_pair(SimplexVector4, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair5 = std::make_pair(SimplexVector5, DEFAULT_FILTRATION_VALUE); - typeSimplex simplexPair6 = std::make_pair(SimplexVector6, DEFAULT_FILTRATION_VALUE); - test_simplex_tree_contains(st, simplexPair1, 6); // (2,1,0) is in position 6 - test_simplex_tree_contains(st, simplexPair2, 7); // (3) is in position 7 - test_simplex_tree_contains(st, simplexPair3, 8); // (3,0) is in position 8 - test_simplex_tree_contains(st, simplexPair4, 2); // (1,0) is in position 2 - test_simplex_tree_contains(st, simplexPair5, 14); // (3,4,5) is in position 14 - test_simplex_tree_contains(st, simplexPair6, 26); // (7,6,1,0) is in position 26 - // ------------------------------------------------------------------------------------------------------------------ // Find in the simplex_tree // ------------------------------------------------------------------------------------------------------------------ - typeVectorVertex simpleSimplexVector { 1 }; + typeVectorVertex simpleSimplexVector{1}; Simplex_tree<>::Simplex_handle simplexFound = st.find(simpleSimplexVector); std::cout << "**************IS THE SIMPLEX {1} IN THE SIMPLEX TREE ?\n"; if (simplexFound != st.null_simplex()) @@ -470,7 +519,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { // Check it is found BOOST_CHECK(simplexFound != st.null_simplex()); - typeVectorVertex unknownSimplexVector { 15 }; + typeVectorVertex unknownSimplexVector{15}; simplexFound = st.find(unknownSimplexVector); std::cout << "**************IS THE SIMPLEX {15} IN THE SIMPLEX TREE ?\n"; if (simplexFound != st.null_simplex()) @@ -489,7 +538,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { // Check it is found BOOST_CHECK(simplexFound != st.null_simplex()); - typeVectorVertex otherSimplexVector { 1, 15 }; + typeVectorVertex otherSimplexVector{1, 15}; simplexFound = st.find(otherSimplexVector); std::cout << "**************IS THE SIMPLEX {15,1} IN THE SIMPLEX TREE ?\n"; if (simplexFound != st.null_simplex()) @@ -499,7 +548,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { // Check it is NOT found BOOST_CHECK(simplexFound == st.null_simplex()); - typeVectorVertex invSimplexVector { 1, 2, 0 }; + typeVectorVertex invSimplexVector{1, 2, 0}; simplexFound = st.find(invSimplexVector); std::cout << "**************IS THE SIMPLEX {1,2,0} IN THE SIMPLEX TREE ?\n"; if (simplexFound != st.null_simplex()) -- cgit v1.2.3 From 89d8caff43f3c38ee3ce3fd96000eaa549ba0481 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 1 Sep 2015 15:04:46 +0000 Subject: UT fix to compile and run under osX git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@768 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a8351f5bd12a2d5e4869a61c298ddf76ad04f91d --- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 8 ++++---- src/common/test/dtoffrw_unit_test.cpp | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index b2597eff..7a0800e4 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -20,10 +20,10 @@ * along with this program. If not, see . */ -#define BOOST_TEST_MODULE alpha_complex -#include -#include -#include +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "alpha_complex" +#include + #include #include diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp index d2705955..ada218ac 100644 --- a/src/common/test/dtoffrw_unit_test.cpp +++ b/src/common/test/dtoffrw_unit_test.cpp @@ -20,8 +20,6 @@ * along with this program. If not, see . */ -#define BOOST_TEST_MODULE DelaunayTriangulationOffFileReadWrite test - // to construct a Delaunay_triangulation from a OFF file #include "gudhi/Delaunay_triangulation_off_io.h" @@ -32,9 +30,9 @@ #include #include -#include -#include -//#include +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "delaunay_triangulation_off_read_write" +#include // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -- cgit v1.2.3 From ba47def14a25fb1299ef0980366c2c5479fb1ccc Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 2 Oct 2015 09:34:09 +0000 Subject: Review fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@816 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d112bf6b1b07a75947392576baa53321326e65c4 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 8 ++++---- .../example/Alpha_complex_from_off.cpp | 8 +++----- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 4 ++-- .../example/Delaunay_triangulation_off_rw.cpp | 5 ++--- .../include/gudhi/Delaunay_triangulation_off_io.h | 24 +++++++++++----------- 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index d266219b..2cb37578 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -93,8 +93,8 @@ namespace alphacomplex { * \end{algorithmic} * \f} * - * From the example above, it means the algorithm will look into each triangulation ([1,2,3], [2,3,4], [1,3,5], ...), - * will compute the filtration value of the triangulation, and then will propagate the filtration value as described + * From the example above, it means the algorithm will look into each triangle ([1,2,3], [2,3,4], [1,3,5], ...), + * will compute the filtration value of the triangle, and then will propagate the filtration value as described * here : * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" * Then, the algorithm will look into each edge ([1,2], [2,3], [1,3], ...), @@ -105,8 +105,8 @@ namespace alphacomplex { * * \section alpha-shape Alpha shape * - * In the example above, the alpha shape of \f$\alpha^2_{74} < \alpha^2 < \alpha^2_{73}\f$ is the alpha complex where the - * \f$\alpha^2_{74} <\f$ filtration value \f$< \alpha^2_{73}\f$ as described in \cite AlphaShapesIntroduction + * In the example above, the alpha shape of \f$\alpha^2_{63} < \alpha^2 < \alpha^2_{62}\f$ is the alpha complex where the + * \f$\alpha^2_{63} <\f$ filtration value \f$< \alpha^2_{62}\f$ as described in \cite AlphaShapesIntroduction * * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" * \copyright GNU General Public License v3. diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index b698d6d7..e140fe3d 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,11 +1,9 @@ -#include -#include - +#include #include // to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" +#include +#include void usage(char * const progName) { std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value" << std::endl; diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 7a0800e4..b630e999 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -33,8 +33,8 @@ #include // to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" +#include +#include // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel_d; diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp index d1aa7988..75e4fafb 100644 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -1,11 +1,10 @@ // to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" +#include #include #include -#include -#include +#include #include // Use dynamic_dimension_tag for the user to be able to set dimension diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index de5fa2af..0c5474c9 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -39,7 +39,7 @@ namespace Gudhi { template class Delaunay_triangulation_off_visitor_reader { private: - Complex* _complex; + Complex* complex_; typedef typename Complex::Point Point; public: @@ -48,10 +48,10 @@ class Delaunay_triangulation_off_visitor_reader { /** \brief Delaunay_triangulation_off_visitor_reader constructor * - * @param[in] _complex_ptr pointer on a Delaunay triangulation. + * @param[in] complex_ptr_ pointer on a Delaunay triangulation. */ - Delaunay_triangulation_off_visitor_reader(Complex* _complex_ptr) - : _complex(nullptr) { } + Delaunay_triangulation_off_visitor_reader(Complex* complex_ptr_) + : complex_(nullptr) { } /** \brief Off_reader visitor init implementation. * @@ -77,7 +77,7 @@ class Delaunay_triangulation_off_visitor_reader { "file for Delaunay triangulation - edges are computed." << std::endl; } // Complex construction with dimension from file - _complex = new Complex(dim); + complex_ = new Complex(dim); } /** \brief Off_reader visitor point implementation. @@ -95,7 +95,7 @@ class Delaunay_triangulation_off_visitor_reader { } std::cout << std::endl; #endif // DEBUG_TRACES - _complex->insert(Point(point.size(), point.begin(), point.end())); + complex_->insert(Point(point.size(), point.begin(), point.end())); } // Off_reader visitor maximal_face implementation - not used @@ -115,7 +115,7 @@ class Delaunay_triangulation_off_visitor_reader { * @warning The returned pointer can be nullptr. */ Complex* get_complex() const { - return _complex; + return complex_; } }; @@ -157,12 +157,12 @@ class Delaunay_triangulation_off_reader { : valid_(false) { std::ifstream stream(name_file); if (stream.is_open()) { - Delaunay_triangulation_off_visitor_reader off_visitor(_complex); + Delaunay_triangulation_off_visitor_reader off_visitor(complex_); Off_reader off_reader(stream); valid_ = off_reader.read(off_visitor); if (valid_) { - _complex = off_visitor.get_complex(); - if (_complex == nullptr) { + complex_ = off_visitor.get_complex(); + if (complex_ == nullptr) { std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader off_visitor returns an empty pointer" << std::endl; valid_ = false; } @@ -190,7 +190,7 @@ class Delaunay_triangulation_off_reader { */ Complex* get_complex() const { if (valid_) - return _complex; + return complex_; return nullptr; } @@ -199,7 +199,7 @@ class Delaunay_triangulation_off_reader { /** \brief OFF file read status.*/ bool valid_; /** \brief A pointer on the Delaunay triangulation.*/ - Complex* _complex; + Complex* complex_; }; /** \brief OFF file writer from a Delaunay triangulation. -- cgit v1.2.3 From 2f54f68e92f2a953f49c4864e9c55f5f55c9cf15 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 2 Oct 2015 12:46:09 +0000 Subject: revert commit git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@818 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: cbb03379cd5d8dac58204430b9e80c05497f1db8 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 124 ++++++++++---------------- 1 file changed, 49 insertions(+), 75 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 28c6fee4..279327f7 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -450,16 +450,43 @@ class Simplex_tree { Simplex_handle find_vertex(Vertex_handle v) { return root_.members_.begin() + v; } + + /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. + * + * @param[in] simplex range of Vertex_handles, representing the vertices of the new simplex + * @param[in] filtration the filtration value assigned to the new simplex. + * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the + * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned + * to the new simplex. + * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion + * fails and the simplex already in the complex has a filtration value strictly bigger than 'filtration', + * we assign this simplex with the new value 'filtration', and set the Simplex_handle filed of the + * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to + * null_simplex. + * + * All subsimplices do not necessary need to be already in the simplex tree to proceed to an + * insertion. However, the property of being a simplicial complex will be violated. This allows + * us to insert a stream of simplices contained in a simplicial complex without considering any + * order on them. + * + * The filtration value + * assigned to the new simplex must preserve the monotonicity of the filtration. + * + * The type RandomAccessVertexRange must be a range for which .begin() and + * .end() return random access iterators, with 'value_type' Vertex_handle. */ + template + std::pair insert_simplex(RandomAccessVertexRange & simplex, + Filtration_value filtration) { + if (simplex.empty()) { + return std::pair(null_simplex(), true); + } + // must be sorted in increasing order + sort(simplex.begin(), simplex.end()); - private: - /** \brief Inserts a simplex represented by a vector of vertex. - \warning the vector must be sorted by increasing vertex handle order */ - std::pair insert_vertex_vector(const std::vector& simplex, - Filtration_value filtration) { Siblings * curr_sib = &root_; std::pair res_insert; - auto vi = simplex.begin(); - for (; vi != simplex.end() - 1; ++vi) { + typename RandomAccessVertexRange::iterator vi; + for (vi = simplex.begin(); vi != simplex.end() - 1; ++vi) { res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration)); if (!(has_children(res_insert.first))) { res_insert.first->second.assign_children(new Siblings(curr_sib, *vi)); @@ -481,77 +508,24 @@ class Simplex_tree { return res_insert; } - public: - /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. - * - * @param[in] simplex range of Vertex_handles, representing the vertices of the new simplex - * @param[in] filtration the filtration value assigned to the new simplex. - * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the - * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned - * to the new simplex. - * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion - * fails and the simplex already in the complex has a filtration value strictly bigger than 'filtration', - * we assign this simplex with the new value 'filtration', and set the Simplex_handle field of the - * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to - * null_simplex. - * - * All subsimplices do not necessary need to be already in the simplex tree to proceed to an - * insertion. However, the property of being a simplicial complex will be violated. This allows - * us to insert a stream of simplices contained in a simplicial complex without considering any - * order on them. - * - * The filtration value - * assigned to the new simplex must preserve the monotonicity of the filtration. - * - * The type InputVertexRange must be a range for which .begin() and - * .end() return input iterators, with 'value_type' Vertex_handle. */ - template - std::pair insert_simplex(const InputVertexRange & simplex, - Filtration_value filtration = 0) { - auto first = std::begin(simplex); - auto last = std::end(simplex); - - if (first == last) - return std::pair(null_simplex(), true); // ----->> - - // Copy before sorting - std::vector copy(first, last); - std::sort(std::begin(copy), std::end(copy)); - return insert_vertex_vector(copy, filtration); - } - - /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of + /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of * Vertex_handles, in the simplicial complex. * * @param[in] Nsimplex range of Vertex_handles, representing the vertices of the new N-simplex * @param[in] filtration the filtration value assigned to the new N-simplex. - * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the - * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned - * to the new simplex. - * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion - * fails and the simplex already in the complex has a filtration value strictly bigger than 'filtration', - * we assign this simplex with the new value 'filtration', and set the Simplex_handle field of the - * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to - * null_simplex. */ - template - std::pair insert_simplex_and_subfaces(const InputVertexRange& Nsimplex, - Filtration_value filtration = 0) { - auto first = std::begin(Nsimplex); - auto last = std::end(Nsimplex); - - if (first == last) - return std::pair(null_simplex(), true); // ----->> - - // Copy before sorting - std::vector copy(first, last); - std::sort(std::begin(copy), std::end(copy)); - + template + std::pair insert_simplex_and_subfaces(const RandomAccessVertexRange& Nsimplex, + Filtration_value filtration = 0.0) { + // Simplex copy + std::vector the_simplex(Nsimplex.begin(), Nsimplex.end()); + // must be sorted in increasing order + std::sort(the_simplex.begin(), the_simplex.end()); std::vector> to_be_inserted; std::vector> to_be_propagated; - return rec_insert_simplex_and_subfaces(copy, to_be_inserted, to_be_propagated, filtration); + return rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration); } - + private: std::pair rec_insert_simplex_and_subfaces(std::vector& the_simplex, std::vector>& to_be_inserted, @@ -560,7 +534,7 @@ class Simplex_tree { std::pair insert_result; if (the_simplex.size() > 1) { // Get and remove last vertex - Vertex_handle last_vertex = the_simplex.back(); + Vertex_handle last_vertex= the_simplex.back(); the_simplex.pop_back(); // Recursive call after last vertex removal insert_result = rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration); @@ -583,21 +557,21 @@ class Simplex_tree { // insert all to_be_inserted for (auto& simplex_tbi : to_be_inserted) { - insert_result = insert_vertex_vector(simplex_tbi, filtration); + insert_result = insert_simplex(simplex_tbi, filtration); } } else if (the_simplex.size() == 1) { // When reaching the end of recursivity, vector of simplices shall be empty and filled on back recursive - if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)) { + if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)){ std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty" << std::endl; exit(-1); } std::vector first_simplex(1, the_simplex.back()); // i.e. (0,1,2) => [to_be_inserted | to_be_propagated] = [(0) | ] to_be_inserted.push_back(first_simplex); - - insert_result = insert_vertex_vector(first_simplex, filtration); + + insert_result = insert_simplex(first_simplex, filtration); } else { std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error" << std::endl; exit(-1); -- cgit v1.2.3 -- cgit v1.2.3 From c14909eae41883308428095758360de3a7202a0d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 2 Oct 2015 13:13:38 +0000 Subject: Backmerge of trunk git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@820 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 812e0b84d187dd5e30a6a18c12612ebc9bf9206a --- src/GudhUI/gui/MainWindow.h | 2 + src/GudhUI/gui/Menu_edge_contraction.h | 2 + src/GudhUI/view/Viewer.h | 3 + src/GudhUI/view/Viewer_instructor.h | 2 + .../include/gudhi/Persistent_cohomology.h | 28 +- .../Persistent_cohomology_column.h | 14 +- src/Simplex_tree/concept/IndexingTag.h | 2 +- src/Simplex_tree/concept/SimplexKey.h | 4 +- src/Simplex_tree/concept/SimplexTreeOptions.h | 41 +++ src/Simplex_tree/concept/VertexHandle.h | 3 +- src/Simplex_tree/example/CMakeLists.txt | 9 +- src/Simplex_tree/example/mini_simplex_tree.cpp | 68 ++++ src/Simplex_tree/include/gudhi/Simplex_tree.h | 354 ++++++++++++++------- .../Simplex_tree_node_explicit_storage.h | 43 +-- .../gudhi/Simplex_tree/Simplex_tree_siblings.h | 6 +- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 276 +++++++++------- src/common/include/gudhi/Simple_object_pool.h | 64 ++++ 17 files changed, 629 insertions(+), 292 deletions(-) create mode 100644 src/Simplex_tree/concept/SimplexTreeOptions.h create mode 100644 src/Simplex_tree/example/mini_simplex_tree.cpp create mode 100644 src/common/include/gudhi/Simple_object_pool.h diff --git a/src/GudhUI/gui/MainWindow.h b/src/GudhUI/gui/MainWindow.h index 587f1c6f..e46b72a3 100644 --- a/src/GudhUI/gui/MainWindow.h +++ b/src/GudhUI/gui/MainWindow.h @@ -1,6 +1,8 @@ #ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H +// Workaround for moc-qt4 not parsing boost headers +#include #include #include "ui_main_window.h" diff --git a/src/GudhUI/gui/Menu_edge_contraction.h b/src/GudhUI/gui/Menu_edge_contraction.h index e497a90f..81d37bd8 100644 --- a/src/GudhUI/gui/Menu_edge_contraction.h +++ b/src/GudhUI/gui/Menu_edge_contraction.h @@ -8,6 +8,8 @@ #ifndef MENU_EDGE_CONTRACTION_H_ #define MENU_EDGE_CONTRACTION_H_ +// Workaround for moc-qt4 not parsing boost headers +#include #include "gui/MainWindow.h" #include "gui/ui_MenuEdgeContraction.h" diff --git a/src/GudhUI/view/Viewer.h b/src/GudhUI/view/Viewer.h index 5639aa56..00f9b245 100644 --- a/src/GudhUI/view/Viewer.h +++ b/src/GudhUI/view/Viewer.h @@ -1,6 +1,9 @@ #ifndef VIEWER_H #define VIEWER_H +// Workaround for moc-qt4 not parsing boost headers +#include + #include #include "View_parameter.h" #include "model/Complex_typedefs.h" diff --git a/src/GudhUI/view/Viewer_instructor.h b/src/GudhUI/view/Viewer_instructor.h index 9a2a236b..62b3755e 100644 --- a/src/GudhUI/view/Viewer_instructor.h +++ b/src/GudhUI/view/Viewer_instructor.h @@ -3,6 +3,8 @@ // todo do a viewer instructor that have directely a pointer to a QGLviewer and buffer ot not triangles +// Workaround for moc-qt4 not parsing boost headers +#include #include diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index 4c818ffa..5f399f1a 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -25,12 +25,12 @@ #include #include +#include #include #include #include #include -#include #include #include @@ -243,7 +243,7 @@ class Persistent_cohomology { column_pool_(), // memory pools for the CAM cell_pool_() { Simplex_key idx_fil = 0; - for (auto & sh : cpx_->filtration_simplex_range()) { + for (auto sh : cpx_->filtration_simplex_range()) { cpx_->assign_key(sh, idx_fil); ++idx_fil; dsets_.make_set(cpx_->key(sh)); @@ -266,13 +266,10 @@ class Persistent_cohomology { } ~Persistent_cohomology() { -// Clean the remaining columns in the matrix. - for (auto & cam_ref : cam_) { - cam_ref.col_.clear(); - } -// Clean the transversal lists + // Clean the transversal lists for (auto & transverse_ref : transverse_idx_) { - transverse_ref.second.row_->clear(); + // Destruct all the cells + transverse_ref.second.row_->clear_and_dispose([&](Cell*p){p->~Cell();}); delete transverse_ref.second.row_; } } @@ -572,9 +569,8 @@ class Persistent_cohomology { Column * curr_col = row_cell_it->self_col_; ++row_cell_it; // Disconnect the column from the rows in the CAM. - for (auto col_cell_it = curr_col->col_.begin(); - col_cell_it != curr_col->col_.end(); ++col_cell_it) { - col_cell_it->base_hook_cam_h::unlink(); + for (auto& col_cell : curr_col->col_) { + col_cell.base_hook_cam_h::unlink(); } // Remove the column from the CAM before modifying its value @@ -589,9 +585,9 @@ class Persistent_cohomology { // Find whether the column obtained is already in the CAM result_insert_cam = cam_.insert(*curr_col); if (result_insert_cam.second) { // If it was not in the CAM before: insertion has succeeded - for (auto col_cell_it = curr_col->col_.begin(); col_cell_it != curr_col->col_.end(); ++col_cell_it) { + for (auto& col_cell : curr_col->col_) { // re-establish the row links - transverse_idx_[col_cell_it->key_].row_->push_front(*col_cell_it); + transverse_idx_[col_cell.key_].row_->push_front(col_cell); } } else { // There is already an identical column in the CAM: // merge two disjoint sets. @@ -601,6 +597,8 @@ class Persistent_cohomology { Simplex_key key_tmp = dsets_.find_set(curr_col->class_key_); ds_repr_[key_tmp] = &(*(result_insert_cam.first)); result_insert_cam.first->class_key_ = key_tmp; + // intrusive containers don't own their elements, we have to release them manually + curr_col->col_.clear_and_dispose([&](Cell*p){cell_pool_.destroy(p);}); column_pool_.destroy(curr_col); // delete curr_col; } } @@ -766,8 +764,8 @@ class Persistent_cohomology { std::vector persistent_pairs_; length_interval interval_length_policy; - boost::object_pool column_pool_; - boost::object_pool cell_pool_; + Simple_object_pool column_pool_; + Simple_object_pool cell_pool_; }; /** @} */ // end defgroup persistent_cohomology diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h index fcec819a..5ffd1776 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Persistent_cohomology_column.h @@ -93,27 +93,25 @@ class Persistent_cohomology_column : public boost::intrusive::set_base_hook< boost::intrusive::base_hook > Col_type; /** \brief Creates an empty column.*/ - explicit Persistent_cohomology_column(SimplexKey key) { - class_key_ = key; - col_ = Col_type(); - } + explicit Persistent_cohomology_column(SimplexKey key) + : col_(), + class_key_(key) {} public: /** Copy constructor.*/ Persistent_cohomology_column(Persistent_cohomology_column const &other) : col_(), class_key_(other.class_key_) { - if (!other.col_.empty()) - std::cerr << "Copying a non-empty column.\n"; + assert(other.col_.empty()); } /** \brief Returns true iff the column is null.*/ - bool is_null() { + bool is_null() const { return col_.empty(); } /** \brief Returns the key of the representative simplex of * the set of simplices having this column as annotation vector * in the compressed annotation matrix.*/ - SimplexKey class_key() { + SimplexKey class_key() const { return class_key_; } diff --git a/src/Simplex_tree/concept/IndexingTag.h b/src/Simplex_tree/concept/IndexingTag.h index d690da11..1dcdd756 100644 --- a/src/Simplex_tree/concept/IndexingTag.h +++ b/src/Simplex_tree/concept/IndexingTag.h @@ -25,6 +25,6 @@ * continuous maps to a cell complex, and compute its persistent * homology. * - * Must be linear_indexing_tag. + * Must be `Gudhi::linear_indexing_tag`. */ struct IndexingTag {}; diff --git a/src/Simplex_tree/concept/SimplexKey.h b/src/Simplex_tree/concept/SimplexKey.h index ce5b2382..7fdbdd84 100644 --- a/src/Simplex_tree/concept/SimplexKey.h +++ b/src/Simplex_tree/concept/SimplexKey.h @@ -22,7 +22,7 @@ /** \brief Key type used as simplex identifier. * - * Must be int + * Must be a signed integer type. */ struct SimplexKey {}; - \ No newline at end of file + diff --git a/src/Simplex_tree/concept/SimplexTreeOptions.h b/src/Simplex_tree/concept/SimplexTreeOptions.h new file mode 100644 index 00000000..a50a2bf1 --- /dev/null +++ b/src/Simplex_tree/concept/SimplexTreeOptions.h @@ -0,0 +1,41 @@ + /* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Marc Glisse + * + * Copyright (C) 2015 INRIA Saclay - Ile-de-France (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \brief Concept of the template parameter for the class `Gudhi::Simplex_tree`. + * + * One model for this is `Gudhi::Simplex_tree_options_full_featured`. If you want to provide your own, it is recommended that you derive from it and override some parts instead of writing a class from scratch. + */ +struct SimplexTreeOptions { + /// Forced for now. + typedef IndexingTag Indexing_tag; + /// Must be a signed integer type. It admits a total order <. + typedef VertexHandle Vertex_handle; + /// Must be comparable with operator<. + typedef FiltrationValue Filtration_value; + /// Must be a signed integer type. + typedef SimplexKey Simplex_key; + /// If true, each simplex has extra storage for one `Simplex_key`. Necessary for `Persistent_cohomology`. + static constexpr bool store_key; + /// If true, each simplex has extra storage for one `Filtration_value`, and this value is propagated by operations like `Gudhi::Simplex_tree::expansion`. Without it, `Persistent_cohomology` degenerates to computing usual (non-persistent) cohomology. + static constexpr bool store_filtration; +}; + diff --git a/src/Simplex_tree/concept/VertexHandle.h b/src/Simplex_tree/concept/VertexHandle.h index 491f0f56..3efbba61 100644 --- a/src/Simplex_tree/concept/VertexHandle.h +++ b/src/Simplex_tree/concept/VertexHandle.h @@ -22,5 +22,6 @@ /** \brief Handle type for the vertices of a cell complex. * - * Must be int.*/ + * Must be a signed integer type. operator< defines a total order on it. + */ struct VertexHandle {}; diff --git a/src/Simplex_tree/example/CMakeLists.txt b/src/Simplex_tree/example/CMakeLists.txt index 1a3cdfbf..2f924490 100644 --- a/src/Simplex_tree/example/CMakeLists.txt +++ b/src/Simplex_tree/example/CMakeLists.txt @@ -7,15 +7,18 @@ add_test(simplex_tree_from_file_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_ add_executable ( simple_simplex_tree simple_simplex_tree.cpp ) add_test(simple_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/simple_simplex_tree) - + +add_executable ( mini_simplex_tree mini_simplex_tree.cpp ) +add_test(mini_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/mini_simplex_tree) + # An example with Simplex-tree using CGAL alpha_shapes_3 if(GMP_FOUND AND CGAL_FOUND) message("CGAL_lib = ${CGAL_LIBRARIES_DIR}") - message("GMP_LIBRARIES = ${GMP_LIBRARIES}") + message("GMP_LIBRARIES = ${GMP_LIBRARIES}") INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${CGAL_INCLUDE_DIRS}) add_executable ( simplex_tree_from_alpha_shapes_3 simplex_tree_from_alpha_shapes_3.cpp ) target_link_libraries(simplex_tree_from_alpha_shapes_3 ${GMP_LIBRARIES} ${CGAL_LIBRARY}) add_test(simplex_tree_from_alpha_shapes_3 ${CMAKE_CURRENT_BINARY_DIR}/simplex_tree_from_alpha_shapes_3 ${CMAKE_SOURCE_DIR}/data/points/bunny_5000) -endif() +endif() diff --git a/src/Simplex_tree/example/mini_simplex_tree.cpp b/src/Simplex_tree/example/mini_simplex_tree.cpp new file mode 100644 index 00000000..08d626d3 --- /dev/null +++ b/src/Simplex_tree/example/mini_simplex_tree.cpp @@ -0,0 +1,68 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Marc Glisse + * + * Copyright (C) 2015 INRIA Saclay - Ile-de-France (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +using namespace Gudhi; + +struct MyOptions : Simplex_tree_options_full_featured { + // Not doing persistence, so we don't need those + static const bool store_key = false; + static const bool store_filtration = false; + // I have few vertices + typedef short Vertex_handle; +}; +typedef Simplex_tree ST; + +// Dictionary should be private, but for now this is the easiest way. +static_assert(sizeof(ST::Dictionary::value_type) < sizeof(Simplex_tree<>::Dictionary::value_type), + "Not storing the filtration and key should save some space"); + +int main() { + ST st; + + /* Complex to build. */ + /* 1 */ + /* o */ + /* /X\ */ + /* o---o---o */ + /* 2 0 3 */ + + auto triangle012 = {0, 1, 2}; + auto edge03 = {0, 3}; + st.insert_simplex_and_subfaces(triangle012); + st.insert_simplex_and_subfaces(edge03); + // FIXME: Remove this line + st.set_dimension(2); + + auto edge02 = {0, 2}; + ST::Simplex_handle e = st.find(edge02); + assert(st.filtration(e) == 0); // We are not using filtrations so everything has value 0 + for(ST::Simplex_handle t : st.cofaces_simplex_range(e, 1)) // Only coface is 012 + { + for(ST::Vertex_handle v : st.simplex_vertex_range(t)) // v in { 0, 1, 2 } + std::cout << v; + std::cout << '\n'; + } +} diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 279327f7..6a47083c 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -28,6 +28,9 @@ #include #include +#include +#include + #include #include #include @@ -72,6 +75,17 @@ namespace Gudhi { * \copyright GNU General Public License v3. * @{ */ + +/// Model of SimplexTreeOptions. +struct Simplex_tree_options_full_featured { + typedef linear_indexing_tag Indexing_tag; + typedef int Vertex_handle; + typedef double Filtration_value; + typedef int Simplex_key; + static const bool store_key = true; + static const bool store_filtration = true; +}; + /** * \brief Simplex Tree data structure for representing simplicial complexes. * @@ -83,35 +97,63 @@ namespace Gudhi { * \implements FilteredComplex * */ -template + +template class Simplex_tree { public: - typedef IndexingTag Indexing_tag; + typedef SimplexTreeOptions Options; + typedef typename Options::Indexing_tag Indexing_tag; /** \brief Type for the value of the filtration function. * * Must be comparable with <. */ - typedef FiltrationValue Filtration_value; + typedef typename Options::Filtration_value Filtration_value; /** \brief Key associated to each simplex. * * Must be a signed integer type. */ - typedef SimplexKey Simplex_key; + typedef typename Options::Simplex_key Simplex_key; /** \brief Type for the vertex handle. * * Must be a signed integer type. It admits a total order <. */ - typedef VertexHandle Vertex_handle; + typedef typename Options::Vertex_handle Vertex_handle; /* Type of node in the simplex tree. */ typedef Simplex_tree_node_explicit_storage Node; /* Type of dictionary Vertex_handle -> Node for traversing the simplex tree. */ + // Note: this wastes space when Vertex_handle is 32 bits and Node is aligned on 64 bits. It would be better to use a flat_set (with our own comparator) where we can control the layout of the struct (put Vertex_handle and Simplex_key next to each other). typedef typename boost::container::flat_map Dictionary; /* \brief Set of nodes sharing a same parent in the simplex tree. */ /* \brief Set of nodes sharing a same parent in the simplex tree. */ typedef Simplex_tree_siblings Siblings; + struct Key_simplex_base_real { + Key_simplex_base_real() : key_(-1) {} + void assign_key(Simplex_key k) { key_ = k; } + Simplex_key key() const { return key_; } + private: + Simplex_key key_; + }; + struct Key_simplex_base_dummy { + Key_simplex_base_dummy() {} + void assign_key(Simplex_key) { } + Simplex_key key() const { assert(false); return -1; } + }; + typedef typename std::conditional::type Key_simplex_base; + + struct Filtration_simplex_base_real { + Filtration_simplex_base_real() : filt_(0) {} + void assign_filtration(Filtration_value f) { filt_ = f; } + Filtration_value filtration() const { return filt_; } + private: + Filtration_value filt_; + }; + struct Filtration_simplex_base_dummy { + Filtration_simplex_base_dummy() {} + void assign_filtration(Filtration_value f) { assert(f == 0); } + Filtration_value filtration() const { return 0; } + }; + typedef typename std::conditional::type Filtration_simplex_base; + public: /** \brief Handle type to a simplex contained in the simplicial complex represented * by the simplex tree. */ @@ -170,12 +212,12 @@ class Simplex_tree { /** \brief Range over the simplices of the skeleton of the simplicial complex, for a given * dimension. */ typedef boost::iterator_range Skeleton_simplex_range; + /** \brief Range over the simplices of the simplicial complex, ordered by the filtration. */ + typedef std::vector Filtration_simplex_range; /** \brief Iterator over the simplices of the simplicial complex, ordered by the filtration. * * 'value_type' is Simplex_handle. */ - typedef typename std::vector::iterator Filtration_simplex_iterator; - /** \brief Range over the simplices of the simplicial complex, ordered by the filtration. */ - typedef boost::iterator_range Filtration_simplex_range; + typedef typename Filtration_simplex_range::const_iterator Filtration_simplex_iterator; /* @} */ // end name range and iterator types /** \name Range and iterator methods @@ -226,17 +268,13 @@ class Simplex_tree { * order is used. * * The filtration must be valid. If the filtration has not been initialized yet, the - * method initializes it (i.e. order the simplices). */ - Filtration_simplex_range filtration_simplex_range(Indexing_tag) { + * method initializes it (i.e. order the simplices). If the complex has changed since the last time the filtration + * was initialized, please call `initialize_filtration()` to recompute it. */ + Filtration_simplex_range const& filtration_simplex_range(Indexing_tag=Indexing_tag()) { if (filtration_vect_.empty()) { initialize_filtration(); } - return Filtration_simplex_range(filtration_vect_.begin(), - filtration_vect_.end()); - } - - Filtration_simplex_range filtration_simplex_range() { - return filtration_simplex_range(Indexing_tag()); + return filtration_vect_; } /** \brief Returns a range over the vertices of a simplex. @@ -278,9 +316,47 @@ class Simplex_tree { Simplex_tree() : null_vertex_(-1), threshold_(0), - root_(NULL, null_vertex_), + root_(nullptr, null_vertex_), + filtration_vect_(), + dimension_(-1) { } + + /** \brief User-defined copy constructor reproduces the whole tree structure. */ + Simplex_tree(const Simplex_tree& simplex_source) + : null_vertex_(simplex_source.null_vertex_), + threshold_(simplex_source.threshold_), filtration_vect_(), - dimension_(-1) { + dimension_(simplex_source.dimension_) { + auto root_source = simplex_source.root_; + auto memb_source = root_source.members(); + root_ = Siblings(nullptr, null_vertex_, memb_source); + rec_copy(&root_, &root_source); + } + + /** \brief depth first search, inserts simplices when reaching a leaf. */ + void rec_copy(Siblings *sib, Siblings *sib_source) { + for (auto sh = sib->members().begin(), sh_source = sib_source->members().begin(); + sh != sib->members().end(); ++sh, ++sh_source) { + if (has_children(sh_source)) { + Siblings * newsib = new Siblings(sib, sh_source->first); + newsib->members_.reserve(sh_source->second.children()->members().size()); + for (auto & child : sh_source->second.children()->members()) + newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(sib, child.second.filtration())); + rec_copy(newsib, sh_source->second.children()); + sh->second.assign_children(newsib); + } + } + } + + /** \brief User-defined move constructor moves the whole tree structure. */ + Simplex_tree(Simplex_tree && old) + : null_vertex_(std::move(old.null_vertex_)), + threshold_(std::move(old.threshold_)), + root_(std::move(old.root_)), + filtration_vect_(std::move(old.filtration_vect_)), + dimension_(std::move(old.dimension_)) { + old.dimension_ = -1; + old.threshold_ = 0; + old.root_ = Siblings(nullptr, null_vertex_); } /** \brief Destructor; deallocates the whole tree structure. */ @@ -303,24 +379,64 @@ class Simplex_tree { delete sib; } + public: + /** \brief Checks if two simplex trees are equal. */ + bool operator==(Simplex_tree& st2) { + if ((null_vertex_ != st2.null_vertex_) || + (threshold_ != st2.threshold_) || + (dimension_ != st2.dimension_)) + return false; + return rec_equal(&root_, &st2.root_); + } + + /** \brief Checks if two simplex trees are different. */ + bool operator!=(Simplex_tree& st2) { + return (!(*this == st2)); + } + + private: + /** rec_equal: Checks recursively whether or not two simplex trees are equal, using depth first search. */ + bool rec_equal(Siblings* s1, Siblings* s2) { + if (s1->members().size() != s2->members().size()) + return false; + for (auto sh1 = s1->members().begin(), sh2 = s2->members().begin(); + (sh1 != s1->members().end() && sh2 != s2->members().end()); ++sh1, ++sh2) { + if (sh1->first != sh2->first || sh1->second.filtration() != sh2->second.filtration()) + return false; + if (has_children(sh1) != has_children(sh2)) + return false; + // Recursivity on children only if both have children + else if (has_children(sh1)) + if (!rec_equal(sh1->second.children(), sh2->second.children())) + return false; + } + return true; + } + public: /** \brief Returns the key associated to a simplex. * - * The filtration must be initialized. */ + * The filtration must be initialized. + * \pre SimplexTreeOptions::store_key + */ static Simplex_key key(Simplex_handle sh) { return sh->second.key(); } /** \brief Returns the simplex associated to a key. * - * The filtration must be initialized. */ + * The filtration must be initialized. + * \pre SimplexTreeOptions::store_key + */ Simplex_handle simplex(Simplex_key key) const { return filtration_vect_[key]; } /** \brief Returns the filtration value of a simplex. * - * Called on the null_simplex, returns INFINITY. */ + * Called on the null_simplex, returns INFINITY. + * If SimplexTreeOptions::store_filtration is false, returns 0. + */ static Filtration_value filtration(Simplex_handle sh) { if (sh != null_simplex()) { return sh->second.filtration(); @@ -348,7 +464,7 @@ class Simplex_tree { * * One can call filtration(null_simplex()). */ static Simplex_handle null_simplex() { - return Dictionary_it(NULL); + return Dictionary_it(nullptr); } /** \brief Returns a key different for all keys associated to the @@ -395,7 +511,7 @@ class Simplex_tree { int dimension(Simplex_handle sh) { Siblings * curr_sib = self_siblings(sh); int dim = 0; - while (curr_sib != NULL) { + while (curr_sib != nullptr) { ++dim; curr_sib = curr_sib->oncles(); } @@ -413,26 +529,34 @@ class Simplex_tree { return (sh->second.children()->parent() == sh->first); } - public: - /** \brief Given a range of Vertex_handles, returns the Simplex_handle + /** \brief Given a range of Vertex_handles, returns the Simplex_handle * of the simplex in the simplicial complex containing the corresponding * vertices. Return null_simplex() if the simplex is not in the complex. * - * The type RandomAccessVertexRange must be a range for which .begin() and - * .end() return random access iterators, with value_type - * Vertex_handle. + * The type InputVertexRange must be a range of Vertex_handle + * on which we can call std::begin() function */ - template - Simplex_handle find(RandomAccessVertexRange & s) { - if (s.begin() == s.end()) // Empty simplex - return null_simplex(); - - sort(s.begin(), s.end()); + template + Simplex_handle find(const InputVertexRange & s) { + auto first = std::begin(s); + auto last = std::end(s); + + if (first == last) + return null_simplex(); // ----->> + + // Copy before sorting + std::vector copy(first, last); + std::sort(std::begin(copy), std::end(copy)); + return find_simplex(copy); + } + private: + /** Find function, with a sorted range of vertices. */ + Simplex_handle find_simplex(const std::vector & simplex) { Siblings * tmp_sib = &root_; Dictionary_it tmp_dit; - Vertex_handle last = s[s.size() - 1]; - for (auto v : s) { + Vertex_handle last = simplex.back(); + for (auto v : simplex) { tmp_dit = tmp_sib->members_.find(v); if (tmp_dit == tmp_sib->members_.end()) { return null_simplex(); @@ -450,43 +574,17 @@ class Simplex_tree { Simplex_handle find_vertex(Vertex_handle v) { return root_.members_.begin() + v; } - - /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. - * - * @param[in] simplex range of Vertex_handles, representing the vertices of the new simplex - * @param[in] filtration the filtration value assigned to the new simplex. - * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the - * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned - * to the new simplex. - * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion - * fails and the simplex already in the complex has a filtration value strictly bigger than 'filtration', - * we assign this simplex with the new value 'filtration', and set the Simplex_handle filed of the - * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to - * null_simplex. - * - * All subsimplices do not necessary need to be already in the simplex tree to proceed to an - * insertion. However, the property of being a simplicial complex will be violated. This allows - * us to insert a stream of simplices contained in a simplicial complex without considering any - * order on them. - * - * The filtration value - * assigned to the new simplex must preserve the monotonicity of the filtration. - * - * The type RandomAccessVertexRange must be a range for which .begin() and - * .end() return random access iterators, with 'value_type' Vertex_handle. */ - template - std::pair insert_simplex(RandomAccessVertexRange & simplex, - Filtration_value filtration) { - if (simplex.empty()) { - return std::pair(null_simplex(), true); - } - // must be sorted in increasing order - sort(simplex.begin(), simplex.end()); + //{ return root_.members_.find(v); } + private: + /** \brief Inserts a simplex represented by a vector of vertex. + \warning the vector must be sorted by increasing vertex handle order */ + std::pair insert_vertex_vector(const std::vector& simplex, + Filtration_value filtration) { Siblings * curr_sib = &root_; std::pair res_insert; - typename RandomAccessVertexRange::iterator vi; - for (vi = simplex.begin(); vi != simplex.end() - 1; ++vi) { + auto vi = simplex.begin(); + for (; vi != simplex.end() - 1; ++vi) { res_insert = curr_sib->members_.emplace(*vi, Node(curr_sib, filtration)); if (!(has_children(res_insert.first))) { res_insert.first->second.assign_children(new Siblings(curr_sib, *vi)); @@ -508,24 +606,77 @@ class Simplex_tree { return res_insert; } - /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of + public: + /** \brief Insert a simplex, represented by a range of Vertex_handles, in the simplicial complex. + * + * @param[in] simplex range of Vertex_handles, representing the vertices of the new simplex + * @param[in] filtration the filtration value assigned to the new simplex. + * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the + * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned + * to the new simplex. + * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion + * fails and the simplex already in the complex has a filtration value strictly bigger than 'filtration', + * we assign this simplex with the new value 'filtration', and set the Simplex_handle field of the + * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to + * null_simplex. + * + * All subsimplices do not necessary need to be already in the simplex tree to proceed to an + * insertion. However, the property of being a simplicial complex will be violated. This allows + * us to insert a stream of simplices contained in a simplicial complex without considering any + * order on them. + * + * The filtration value + * assigned to the new simplex must preserve the monotonicity of the filtration. + * + * The type InputVertexRange must be a range for which .begin() and + * .end() return input iterators, with 'value_type' Vertex_handle. */ + template + std::pair insert_simplex(const InputVertexRange & simplex, + Filtration_value filtration = 0) { + auto first = std::begin(simplex); + auto last = std::end(simplex); + + if (first == last) + return std::pair(null_simplex(), true); // ----->> + + // Copy before sorting + std::vector copy(first, last); + std::sort(std::begin(copy), std::end(copy)); + return insert_vertex_vector(copy, filtration); + } + + /** \brief Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of * Vertex_handles, in the simplicial complex. * * @param[in] Nsimplex range of Vertex_handles, representing the vertices of the new N-simplex * @param[in] filtration the filtration value assigned to the new N-simplex. + * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the + * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned + * to the new simplex. + * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion + * fails and the simplex already in the complex has a filtration value strictly bigger than 'filtration', + * we assign this simplex with the new value 'filtration', and set the Simplex_handle field of the + * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to + * null_simplex. */ - template - std::pair insert_simplex_and_subfaces(const RandomAccessVertexRange& Nsimplex, - Filtration_value filtration = 0.0) { - // Simplex copy - std::vector the_simplex(Nsimplex.begin(), Nsimplex.end()); - // must be sorted in increasing order - std::sort(the_simplex.begin(), the_simplex.end()); + template + std::pair insert_simplex_and_subfaces(const InputVertexRange& Nsimplex, + Filtration_value filtration = 0) { + auto first = std::begin(Nsimplex); + auto last = std::end(Nsimplex); + + if (first == last) + return std::pair(null_simplex(), true); // ----->> + + // Copy before sorting + std::vector copy(first, last); + std::sort(std::begin(copy), std::end(copy)); + std::vector> to_be_inserted; std::vector> to_be_propagated; - return rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration); + return rec_insert_simplex_and_subfaces(copy, to_be_inserted, to_be_propagated, filtration); } - + private: std::pair rec_insert_simplex_and_subfaces(std::vector& the_simplex, std::vector>& to_be_inserted, @@ -534,15 +685,15 @@ class Simplex_tree { std::pair insert_result; if (the_simplex.size() > 1) { // Get and remove last vertex - Vertex_handle last_vertex= the_simplex.back(); + Vertex_handle last_vertex = the_simplex.back(); the_simplex.pop_back(); // Recursive call after last vertex removal insert_result = rec_insert_simplex_and_subfaces(the_simplex, to_be_inserted, to_be_propagated, filtration); - + // Concatenation of to_be_inserted and to_be_propagated to_be_inserted.insert(to_be_inserted.begin(), to_be_propagated.begin(), to_be_propagated.end()); to_be_propagated = to_be_inserted; - + // to_be_inserted treatment for (auto& simplex_tbi : to_be_inserted) { simplex_tbi.push_back(last_vertex); @@ -557,26 +708,23 @@ class Simplex_tree { // insert all to_be_inserted for (auto& simplex_tbi : to_be_inserted) { - insert_result = insert_simplex(simplex_tbi, filtration); + insert_result = insert_vertex_vector(simplex_tbi, filtration); } - - } else if (the_simplex.size() == 1) { // When reaching the end of recursivity, vector of simplices shall be empty and filled on back recursive - if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)){ + if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)) { std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty" << std::endl; exit(-1); } std::vector first_simplex(1, the_simplex.back()); // i.e. (0,1,2) => [to_be_inserted | to_be_propagated] = [(0) | ] to_be_inserted.push_back(first_simplex); - - insert_result = insert_simplex(first_simplex, filtration); + + insert_result = insert_vertex_vector(first_simplex, filtration); } else { std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error" << std::endl; exit(-1); } - return insert_result; } @@ -603,17 +751,6 @@ class Simplex_tree { return sh->second.children(); } - // void display_simplex(Simplex_handle sh) - // { - // std::cout << " " << "[" << filtration(sh) << "] "; - // for( auto vertex : simplex_vertex_range(sh) ) - // { std::cout << vertex << " "; } - // } - - // void print(Simplex_handle sh, std::ostream& os = std::cout) - // { for(auto v : simplex_vertex_range(sh)) {os << v << " ";} - // os << std::endl; } - public: /** Returns a pointer to the root nodes of the simplex tree. */ Siblings * root() { @@ -778,8 +915,9 @@ class Simplex_tree { : st_(st) { } bool operator()(const Simplex_handle sh1, const Simplex_handle sh2) const { - if (st_->filtration(sh1) != st_->filtration(sh2)) { - return st_->filtration(sh1) < st_->filtration(sh2); + // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. + if (sh1->second.filtration() != sh2->second.filtration()) { + return sh1->second.filtration() < sh2->second.filtration(); } // is sh1 a proper subface of sh2 return st_->reverse_lexicographic_order(sh1, sh2); @@ -925,7 +1063,7 @@ class Simplex_tree { while (true) { if (begin1->first == begin2->first) { Filtration_value filt = (std::max)({begin1->second.filtration(), begin2->second.filtration(), filtration_}); - intersection.emplace_back(begin1->first, Node(NULL, filt)); + intersection.emplace_back(begin1->first, Node(nullptr, filt)); if (++begin1 == end1 || ++begin2 == end2) return; // ----->> } else if (begin1->first < begin2->first) { @@ -947,7 +1085,7 @@ class Simplex_tree { * of the simplex, and fil is its filtration value. */ void print_hasse(std::ostream& os) { os << num_simplices() << " " << std::endl; - for (auto sh : filtration_simplex_range(Indexing_tag())) { + for (auto sh : filtration_simplex_range()) { os << dimension(sh) << " "; for (auto b_sh : boundary_simplex_range(sh)) { os << key(b_sh) << " "; diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h index 1f1a34cc..c49e30b9 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h @@ -39,62 +39,31 @@ namespace Gudhi { * It stores explicitely its own filtration value and its own Simplex_key. */ template -class Simplex_tree_node_explicit_storage { - public: +struct Simplex_tree_node_explicit_storage : SimplexTree::Filtration_simplex_base, SimplexTree::Key_simplex_base { typedef typename SimplexTree::Siblings Siblings; typedef typename SimplexTree::Filtration_value Filtration_value; typedef typename SimplexTree::Simplex_key Simplex_key; - // Default constructor. - Simplex_tree_node_explicit_storage() - : children_(NULL), - simplex_key_(-1), - filtration_(0) { - } - - Simplex_tree_node_explicit_storage(Siblings * sib, - Filtration_value filtration) - : children_(sib), - simplex_key_(-1), - filtration_(filtration) { - } - - void assign_key(Simplex_key key) { - simplex_key_ = key; + Simplex_tree_node_explicit_storage(Siblings * sib = nullptr, + Filtration_value filtration = 0) + : children_(sib) { + this->assign_filtration(filtration); } /* - * Assign a children to the node + * Assign children to the node */ void assign_children(Siblings * children) { children_ = children; } - /* - * - */ - void assign_filtration(double filtration_value) { - filtration_ = filtration_value; - } - - Filtration_value filtration() { - return filtration_; - } /* Careful -> children_ can be NULL*/ Siblings * children() { return children_; } - Simplex_key key() { - return simplex_key_; - } - private: Siblings * children_; - - // Data attached to simplex, explicit storage - Simplex_key simplex_key_; - Filtration_value filtration_; // value in the filtration }; /* @} */ // end addtogroup simplex_tree diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h index de350f2d..d20a91d7 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h @@ -71,15 +71,15 @@ class Simplex_tree_siblings { /* \brief Constructor with initialized set of members. * * 'members' must be sorted and unique.*/ - Simplex_tree_siblings(Simplex_tree_siblings * oncles, Vertex_handle parent, - const std::vector > & members) + template + Simplex_tree_siblings(Simplex_tree_siblings * oncles, Vertex_handle parent, const RandomAccessVertexRange & members) : oncles_(oncles), parent_(parent), members_(boost::container::ordered_unique_range, members.begin(), members.end()) { for (auto& map_el : members_) { map_el.second.assign_children(this); - } + } } /* diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 9340aaa3..a4871cfd 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -9,8 +9,8 @@ #define BOOST_TEST_MODULE "simplex_tree" #include -#include "gudhi/graph_simplicial_complex.h" -#include "gudhi/reader_utils.h" +// ^ +// /!\ Nothing else from Simplex_tree shall be included to test includes are well defined. #include "gudhi/Simplex_tree.h" using namespace Gudhi; @@ -59,7 +59,6 @@ void test_iterators_on_empty_simplex_tree(typeST& tst) { BOOST_AUTO_TEST_CASE(simplex_tree_when_empty) { const Filtration_value DEFAULT_FILTRATION_VALUE = 0; - // TEST OF DEFAULT CONSTRUCTOR std::cout << "********************************************************************" << std::endl; std::cout << "TEST OF DEFAULT CONSTRUCTOR" << std::endl; typeST st; @@ -126,6 +125,7 @@ void test_simplex_tree_contains(typeST& simplexTree, typeSimplex& simplex, int p BOOST_CHECK(AreAlmostTheSame(simplexTree.filtration(*f_simplex), simplex.second)); int simplexIndex = simplex.first.size() - 1; + std::sort(simplex.first.begin(), simplex.first.end()); // if the simplex wasn't sorted, the next test could fail for (auto vertex : simplexTree.simplex_vertex_range(*f_simplex)) { std::cout << "test_simplex_tree_contains - vertex=" << vertex << "||" << simplex.first.at(simplexIndex) << std::endl; BOOST_CHECK(vertex == simplex.first.at(simplexIndex)); @@ -170,22 +170,6 @@ void set_and_test_simplex_tree_dim_fil(typeST& simplexTree, int vectorSize, cons BOOST_CHECK(simplexTree.num_simplices() == num_simp); } -void test_cofaces(typeST& st, std::vector v, int dim, std::vector res) { - typeST::Cofaces_simplex_range cofaces; - if (dim == 0) - cofaces = st.star_simplex_range(st.find(v)); - else - cofaces = st.cofaces_simplex_range(st.find(v), dim); - for (auto simplex = cofaces.begin(); simplex != cofaces.end(); ++simplex) { - typeST::Simplex_vertex_range rg = st.simplex_vertex_range(*simplex); - for (auto vertex = rg.begin(); vertex != rg.end(); ++vertex) { - std::cout << "(" << *vertex << ")"; - } - std::cout << std::endl; - BOOST_CHECK(std::find(res.begin(), res.end(), *simplex) != res.end()); - } -} - BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { const Filtration_value FIRST_FILTRATION_VALUE = 0.1; const Filtration_value SECOND_FILTRATION_VALUE = 0.2; @@ -378,9 +362,8 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { bool sort_in_decr_order (Vertex_handle i,Vertex_handle j) { return (i>j); } BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { - // TEST OF INSERTION WITH SUBFACES std::cout << "********************************************************************" << std::endl; - std::cout << "TEST OF INSERTION WITH SUBFACES" << std::endl; + std::cout << "TEST OF RECURSIVE INSERTION" << std::endl; typeST st; typePairSimplexBool returnValue; int position = 0; @@ -569,114 +552,179 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { } std::cout << std::endl; } +} +void test_cofaces(typeST& st, std::vector expected, int dim, std::vector res) { + typeST::Cofaces_simplex_range cofaces; + if (dim == 0) + cofaces = st.star_simplex_range(st.find(expected)); + else + cofaces = st.cofaces_simplex_range(st.find(expected), dim); + for (auto simplex = cofaces.begin(); simplex != cofaces.end(); ++simplex) { + typeST::Simplex_vertex_range rg = st.simplex_vertex_range(*simplex); + for (auto vertex = rg.begin(); vertex != rg.end(); ++vertex) { + std::cout << "(" << *vertex << ")"; + } + std::cout << std::endl; + BOOST_CHECK(std::find(res.begin(), res.end(), *simplex) != res.end()); + } +} + +BOOST_AUTO_TEST_CASE(coface_on_simplex_tree) { std::cout << "********************************************************************" << std::endl; - // TEST COFACE ALGORITHM + std::cout << "TEST COFACE ALGORITHM" << std::endl; + typeST st; + + typeVectorVertex SimplexVector{2, 1, 0}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {3, 0}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {3, 4, 5}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {0, 1, 6, 7}; + st.insert_simplex_and_subfaces(SimplexVector); + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + // FIXME st.set_dimension(3); - std::cout << "COFACE ALGORITHM" << std::endl; - std::vector v; - std::vector simplex; + + std::vector simplex_result; std::vector result; - v.push_back(3); - std::cout << "First test : " << std::endl; - std::cout << "Star of (3):" << std::endl; - - simplex.push_back(3); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(3); - simplex.push_back(0); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(4); - simplex.push_back(3); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(5); - simplex.push_back(4); - simplex.push_back(3); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(5); - simplex.push_back(3); - result.push_back(st.find(simplex)); - simplex.clear(); - - test_cofaces(st, v, 0, result); - v.clear(); + std::cout << "First test - Star of (3):" << std::endl; + + simplex_result = {3}; + result.push_back(st.find(simplex_result)); + + simplex_result = {3, 0}; + result.push_back(st.find(simplex_result)); + + simplex_result = {4, 3}; + result.push_back(st.find(simplex_result)); + + simplex_result = {5, 4, 3}; + result.push_back(st.find(simplex_result)); + + simplex_result = {5, 3}; + result.push_back(st.find(simplex_result)); + simplex_result.clear(); + + std::vector vertex = {3}; + test_cofaces(st, vertex, 0, result); + vertex.clear(); result.clear(); - v.push_back(1); - v.push_back(7); - std::cout << "Second test : " << std::endl; - std::cout << "Star of (1,7): " << std::endl; - - simplex.push_back(7); - simplex.push_back(1); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(7); - simplex.push_back(6); - simplex.push_back(1); - simplex.push_back(0); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(7); - simplex.push_back(1); - simplex.push_back(0); - result.push_back(st.find(simplex)); - simplex.clear(); - - simplex.push_back(7); - simplex.push_back(6); - simplex.push_back(1); - result.push_back(st.find(simplex)); - simplex.clear(); - - test_cofaces(st, v, 0, result); + vertex.push_back(1); + vertex.push_back(7); + std::cout << "Second test - Star of (1,7): " << std::endl; + + simplex_result = {7, 1}; + result.push_back(st.find(simplex_result)); + + simplex_result = {7, 6, 1, 0}; + result.push_back(st.find(simplex_result)); + + simplex_result = {7, 1, 0}; + result.push_back(st.find(simplex_result)); + + simplex_result = {7, 6, 1}; + result.push_back(st.find(simplex_result)); + + test_cofaces(st, vertex, 0, result); result.clear(); - std::cout << "Third test : " << std::endl; - std::cout << "2-dimension Cofaces of simplex(1,7) : " << std::endl; + std::cout << "Third test - 2-dimension Cofaces of simplex(1,7) : " << std::endl; - simplex.push_back(7); - simplex.push_back(1); - simplex.push_back(0); - result.push_back(st.find(simplex)); - simplex.clear(); + simplex_result = {7, 1, 0}; + result.push_back(st.find(simplex_result)); - simplex.push_back(7); - simplex.push_back(6); - simplex.push_back(1); - result.push_back(st.find(simplex)); - simplex.clear(); + simplex_result = {7, 6, 1}; + result.push_back(st.find(simplex_result)); - test_cofaces(st, v, 1, result); + test_cofaces(st, vertex, 1, result); result.clear(); std::cout << "Cofaces with a codimension too high (codimension + vetices > tree.dimension) :" << std::endl; - test_cofaces(st, v, 5, result); - // std::cout << "Cofaces with an empty codimension" << std::endl; - // test_cofaces(st, v, -1, result); + test_cofaces(st, vertex, 5, result); + + //std::cout << "Cofaces with an empty codimension" << std::endl; + //test_cofaces(st, vertex, -1, result); // std::cout << "Cofaces in an empty simplex tree" << std::endl; // typeST empty_tree; - // test_cofaces(empty_tree, v, 1, result); - // std::cout << "Cofaces of an empty simplex" << std::endl; - // v.clear(); - // test_cofaces(st, v, 1, result); - - /* - // TEST Off read - std::cout << "********************************************************************" << std::endl; - typeST st2; - st2.tree_from_off("test.off"); - std::cout << st2; - */ + // test_cofaces(empty_tree, vertex, 1, result); + //std::cout << "Cofaces of an empty simplex" << std::endl; + //vertex.clear(); + // test_cofaces(st, vertex, 1, result); + +} + +BOOST_AUTO_TEST_CASE(copy_move_on_simplex_tree) { + std::cout << "********************************************************************" << std::endl; + std::cout << "TEST COPY MOVE CONSTRUCTORS" << std::endl; + typeST st; + + typeVectorVertex SimplexVector{2, 1, 0}; + st.insert_simplex_and_subfaces(SimplexVector); + SimplexVector = {3, 0}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {3, 4, 5}; + st.insert_simplex_and_subfaces(SimplexVector); + + SimplexVector = {0, 1, 6, 7}; + st.insert_simplex_and_subfaces(SimplexVector); + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + // FIXME + st.set_dimension(3); + + std::cout << "Printing st - address = " << &st << std::endl; + + // Copy constructor + typeST st_copy = st; + std::cout << "Printing a copy of st - address = " << &st_copy << std::endl; + + // Check the data are the same + BOOST_CHECK(st == st_copy); + // Check there is a new simplex tree reference + BOOST_CHECK(&st != &st_copy); + + // Move constructor + typeST st_move = std::move(st); + std::cout << "Printing a move of st - address = " << &st_move << std::endl; + + // Check the data are the same + BOOST_CHECK(st_move == st_copy); + // Check there is a new simplex tree reference + BOOST_CHECK(&st_move != &st_copy); + BOOST_CHECK(&st_move != &st); + + typeST st_empty; + // Check st has been emptied by the move + BOOST_CHECK(st == st_empty); + BOOST_CHECK(st.filtration() == 0); + BOOST_CHECK(st.dimension() == -1); + BOOST_CHECK(st.num_simplices() == 0); + BOOST_CHECK(st.num_vertices() == (size_t)0); + + std::cout << "Printing st once again- address = " << &st << std::endl; } diff --git a/src/common/include/gudhi/Simple_object_pool.h b/src/common/include/gudhi/Simple_object_pool.h new file mode 100644 index 00000000..fffcb2ef --- /dev/null +++ b/src/common/include/gudhi/Simple_object_pool.h @@ -0,0 +1,64 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Marc Glisse + * + * Copyright (C) 2015 INRIA Saclay - Ile de France + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +namespace Gudhi { + /** \private + * This is a simpler version of boost::object_pool, that requires + * that users explicitly destroy all objects. This lets the + * performance scale much better, see + * https://svn.boost.org/trac/boost/ticket/3789 . + */ +template +class Simple_object_pool : protected boost::pool +{ + protected: + typedef boost::pool Base; + typedef T* pointer; + Base& base(){return *this;} + Base const& base()const{return *this;} + public: + typedef T element_type; + typedef boost::default_user_allocator_malloc_free user_allocator; + typedef typename Base::size_type size_type; + typedef typename Base::difference_type difference_type; + template + Simple_object_pool(U&&...u) : Base(sizeof(T), std::forward(u)...) {} + template + pointer construct(U&&...u){ + void* p=base().malloc BOOST_PREVENT_MACRO_SUBSTITUTION(); + assert(p); + try { new(p) T(std::forward(u)...); } + catch(...) { + base().free BOOST_PREVENT_MACRO_SUBSTITUTION(p); + throw; + } + return static_cast(p); + } + void destroy(pointer p){ + p->~T(); + base().free BOOST_PREVENT_MACRO_SUBSTITUTION(p); + } +}; +} -- cgit v1.2.3 From 03b68a5206201bf5bbffb7e4f6a6718907f23b2a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 9 Nov 2015 09:18:55 +0000 Subject: Modification for Porquerolles Workshop Bar_code_persistence and alpha_complex_persistence git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@893 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 63d2d21d5ff7c9a94a67eafc326bf8a561bf8166 --- src/Alpha_complex/example/CMakeLists.txt | 14 ++++ src/GudhUI/CMakeLists.txt | 40 +++++++++++ src/GudhUI/alpha_complex_persistence.cpp | 78 ++++++++++++++++++++ src/GudhUI/model/Model.h | 2 +- src/GudhUI/utils/Bar_code_persistence.h | 84 ++++++++++++++++++++++ src/GudhUI/view/FirstCoordProjector.h | 5 +- src/Persistent_cohomology/example/CMakeLists.txt | 44 ++++++++++++ .../example/alpha_complex_persistence.cpp | 55 ++++++++++++++ .../example/alpha_shapes_persistence.cpp | 14 ++-- .../include/gudhi/Persistent_cohomology.h | 8 +++ src/Simplex_tree/include/gudhi/Simplex_tree.h | 2 +- .../include/gudhi/Delaunay_triangulation_off_io.h | 2 +- src/common/include/gudhi/Off_reader.h | 2 +- 13 files changed, 338 insertions(+), 12 deletions(-) create mode 100644 src/GudhUI/alpha_complex_persistence.cpp create mode 100644 src/GudhUI/utils/Bar_code_persistence.h create mode 100644 src/Persistent_cohomology/example/alpha_complex_persistence.cpp diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 04fc34af..10b87f04 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -8,6 +8,20 @@ if(CGAL_FOUND) message(STATUS "CGAL version: ${CGAL_VERSION}.") include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index 71f4fd1a..5c2afdd0 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -78,6 +78,46 @@ if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND ) target_link_libraries( GudhUI ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} ) target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) +############################################################################### + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() + + add_executable (acp alpha_complex_persistence.cpp) + target_link_libraries(acp ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${QT_LIBRARIES}) + + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () +############################################################################### + else() message(STATUS "NOTICE: GudhUI requires CGAL, the QGLViewer, OpenGL and Qt4, and will not be compiled.") endif() diff --git a/src/GudhUI/alpha_complex_persistence.cpp b/src/GudhUI/alpha_complex_persistence.cpp new file mode 100644 index 00000000..4f85459a --- /dev/null +++ b/src/GudhUI/alpha_complex_persistence.cpp @@ -0,0 +1,78 @@ +#include +#include + + +#include + +// to construct a Delaunay_triangulation from a OFF file +#include +#include +#include + +#include "utils/Bar_code_persistence.h" + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " filename.off " << // alpha_square_max_value[double] " << + "coeff_field_characteristic[integer > 0] min_persistence[double >= -1.0]" << std::endl; + std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0 2 0.02" << std::endl; + exit(-1); // ----- >> +} + +int main(int argc, char **argv) { + if (argc != 4) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + QApplication qtapp(argc, argv); + + std::string off_file_name(argv[1]); + // double alpha_square_max_value = atof(argv[2]); + double alpha_square_max_value = 1e20; + int coeff_field_characteristic = atoi(argv[2]); // argv[3] + double min_persistence = atof(argv[3]); // argv[4] + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from an OFF file + // ---------------------------------------------------------------------------- + typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); + + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << + " - " << alpha_complex_from_file.num_simplices() << " simplices - " << + alpha_complex_from_file.num_vertices() << " vertices." << std::endl; + + // Sort the simplices in the order of the filtration + alpha_complex_from_file.initialize_filtration(); + + std::cout << "Simplex_tree dim: " << alpha_complex_from_file.dimension() << std::endl; + // Compute the persistence diagram of the complex + Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::alphacomplex::Alpha_complex, + Gudhi::persistent_cohomology::Field_Zp > pcoh(alpha_complex_from_file); + + std::cout << "coeff_field_characteristic " << coeff_field_characteristic << + " - min_persistence " << min_persistence << std::endl; + + // initializes the coefficient field for homology + pcoh.init_coefficients(coeff_field_characteristic); + + pcoh.compute_persistent_cohomology(min_persistence); + + pcoh.output_diagram(); + + std::vector> persistence_vector; + pcoh.get_persistence(persistence_vector); + + Bar_code_persistence bc_persistence; + + for (auto persistence : persistence_vector) { + bc_persistence.insert(persistence.first, persistence.second); + } + + bc_persistence.show(); + + return qtapp.exec(); +} diff --git a/src/GudhUI/model/Model.h b/src/GudhUI/model/Model.h index d78cbad9..4f8d48ee 100644 --- a/src/GudhUI/model/Model.h +++ b/src/GudhUI/model/Model.h @@ -71,7 +71,7 @@ class CGAL_geometric_flag_complex_wrapper { void maximal_face(std::vector vertices) { if (!load_only_points_) { - std::cout << "size:" << vertices.size() << std::endl; + //std::cout << "size:" << vertices.size() << std::endl; for (int i = 0; i < vertices.size(); ++i) for (int j = i + 1; j < vertices.size(); ++j) complex_.add_edge(Vertex_handle(vertices[i]), Vertex_handle(vertices[j])); diff --git a/src/GudhUI/utils/Bar_code_persistence.h b/src/GudhUI/utils/Bar_code_persistence.h new file mode 100644 index 00000000..a1a46ea8 --- /dev/null +++ b/src/GudhUI/utils/Bar_code_persistence.h @@ -0,0 +1,84 @@ +#include // isfinite + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include // NaN, infinity +#include // for pair + +class Bar_code_persistence { + private: + typedef std::vector> Persistence; + Persistence persistence_vector; + double min_birth; + double max_death; + + public: + + Bar_code_persistence() + : min_birth(std::numeric_limits::quiet_NaN()), + max_death(std::numeric_limits::quiet_NaN()) { } + + void insert(double birth, double death) { + persistence_vector.push_back(std::make_pair(birth, death)); + if (std::isfinite(birth)) { + if ((birth < min_birth) || (std::isnan(min_birth))) + min_birth = birth; + if ((birth > max_death) || (std::isnan(max_death))) + max_death = birth; + } + if (std::isfinite(death)) + if ((death > max_death) || (std::isnan(max_death))) + max_death = death; + } + + void show() { + // Create a view, put a scene in it + QGraphicsView * view = new QGraphicsView(); + QGraphicsScene * scene = new QGraphicsScene(); + view->setScene(scene); + double ratio = 600.0 / (max_death - min_birth); + //std::cout << "min_birth=" << min_birth << " - max_death=" << max_death << " - ratio=" << ratio << std::endl; + + double height = 0.0, birth = 0.0, death = 0.0; + int pers_num = 1; + for (auto& persistence : persistence_vector) { + height = 5.0 * pers_num; + //std::cout << "[" << pers_num << "] birth=" << persistence.first << " - death=" << persistence.second << std::endl; + if (std::isfinite(persistence.first)) + birth = ((persistence.first - min_birth) * ratio) + 50.0; + else + birth = 0.0; + + if (std::isfinite(persistence.second)) + death = ((persistence.second - min_birth) * ratio) + 50.0; + else + death = 700.0; + + scene->addLine(birth, height, death, height, QPen(Qt::blue, 2)); + pers_num++; + } + height += 10.0; + // scale line + scene->addLine(0, height, 700.0, height, QPen(Qt::black, 1)); + int modulo = 0; + for (double scale = 50.0; scale < 700.0; scale += 50.0) { + modulo++; + // scale small dash + scene->addLine(scale, height - 3.0, scale, height + 3.0, QPen(Qt::black, 1)); + // scale text + QString scale_value = QString::number(((scale - 50.0) / ratio) + min_birth); + QGraphicsTextItem* dimText = scene->addText(scale_value, QFont("Helvetica", 8)); + dimText->setPos(scale - (3.0 * scale_value.size()), height + 9.0 * (modulo % 2)); + } + // Show the view + view->show(); + } +}; diff --git a/src/GudhUI/view/FirstCoordProjector.h b/src/GudhUI/view/FirstCoordProjector.h index 529d2d42..3ceda3f5 100644 --- a/src/GudhUI/view/FirstCoordProjector.h +++ b/src/GudhUI/view/FirstCoordProjector.h @@ -32,8 +32,11 @@ class FirstCoordProjector3D : public Projector3D { typedef Projector3D::Point_3 Point_3; Point_3 operator()(const Point& p) const { - assert(p.dimension() >= 3); + if (p.dimension() >= 3) return Point_3(p.x(), p.y(), p.z()); + else if (p.dimension() >= 2) + return Point_3(p.x(), p.y(), 0.0); + } }; diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index ea69352e..74c2e778 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -39,6 +39,50 @@ if(GMPXX_FOUND AND GMP_FOUND) target_link_libraries(alpha_shapes_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) add_test(alpha_shapes_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) + + + + + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() + + add_executable (alphacomplexpersistence alpha_complex_persistence.cpp) + target_link_libraries(alphacomplexpersistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() + else() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () + + + endif() endif() diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp new file mode 100644 index 00000000..fbadf673 --- /dev/null +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -0,0 +1,55 @@ +#include +#include + +// to construct a Delaunay_triangulation from a OFF file +#include +#include +#include + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value[double] " << + "coeff_field_characteristic[integer > 0] min_persistence[double >= -1.0]" << std::endl; + std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0 2 0.02" << std::endl; + exit(-1); // ----- >> +} + +int main(int argc, char **argv) { + if (argc != 5) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + std::string off_file_name(argv[1]); + double alpha_square_max_value = atof(argv[2]); + int coeff_field_characteristic = atoi(argv[3]); + double min_persistence = atof(argv[4]); + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from an OFF file + // ---------------------------------------------------------------------------- + typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); + + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << + " - " << alpha_complex_from_file.num_simplices() << " simplices - " << + alpha_complex_from_file.num_vertices() << " vertices." << std::endl; + + // Sort the simplices in the order of the filtration + alpha_complex_from_file.initialize_filtration(); + + std::cout << "Simplex_tree dim: " << alpha_complex_from_file.dimension() << std::endl; + // Compute the persistence diagram of the complex + Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::alphacomplex::Alpha_complex, + Gudhi::persistent_cohomology::Field_Zp > pcoh(alpha_complex_from_file); + // initializes the coefficient field for homology + pcoh.init_coefficients(coeff_field_characteristic); + + pcoh.compute_persistent_cohomology(min_persistence); + + pcoh.output_diagram(); + + return 0; +} diff --git a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp b/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp index 6d5eebcf..235ea141 100644 --- a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp @@ -124,6 +124,12 @@ void usage(char * const progName) { } int main(int argc, char * const argv[]) { + // program args management + if (argc != 4) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; + usage(argv[0]); + } + int coeff_field_characteristic = 0; int returnedScanValue = sscanf(argv[2], "%d", &coeff_field_characteristic); if ((returnedScanValue == EOF) || (coeff_field_characteristic <= 0)) { @@ -138,12 +144,6 @@ int main(int argc, char * const argv[]) { usage(argv[0]); } - // program args management - if (argc != 4) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; - usage(argv[0]); - } - // Read points from file std::string filegraph = argv[1]; std::list lp; @@ -239,7 +239,7 @@ int main(int argc, char * const argv[]) { } } // Construction of the simplex_tree - Filtration_value filtr = std::sqrt(*the_alpha_value_iterator); + Filtration_value filtr = /*std::sqrt*/(*the_alpha_value_iterator); #ifdef DEBUG_TRACES std::cout << "filtration = " << filtr << std::endl; #endif // DEBUG_TRACES diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index d096792f..f6773bac 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -713,6 +713,14 @@ class Persistent_cohomology { } } + void get_persistence(std::vector>& persistence) { + cmp_intervals_by_length cmp(cpx_); + std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp); + for (auto pair : persistent_pairs_) { + persistence.push_back(std::make_pair(cpx_->filtration(get<0>(pair)), cpx_->filtration(get<1>(pair)))); + } + } + void write_output_diagram(std::string diagram_name) { std::ofstream diagram_out(diagram_name.c_str()); cmp_intervals_by_length cmp(cpx_); diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index c7a0b5d5..1ca43ff9 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1096,7 +1096,7 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } - + private: Vertex_handle null_vertex_; /** \brief Upper bound on the filtration values of the simplices.*/ diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 0c5474c9..47066a94 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -278,7 +278,7 @@ class Delaunay_triangulation_off_writer { std::vector vertexVector; stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - stream << points_to_vh[(*vit)->point()] << " "; + stream << points_to_vh[(*vit)->point()] - 1 << " "; } stream << std::endl; } diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index bba5a63a..e45a7600 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -160,7 +160,7 @@ class Off_reader { iss >> num_face_vertices; std::vector face; face.assign(std::istream_iterator(iss), std::istream_iterator()); - if (face.size() != off_info_.dim) return false; + //if (face.size() != (off_info_.dim + 1)) return false; visitor.maximal_face(face); } return true; -- cgit v1.2.3 From 493372a01e24220d16ef0405eb7cdc4bbe96fe1c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 9 Nov 2015 15:58:16 +0000 Subject: Code review fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@895 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: aa5f6a30b847dd8a2add83fab50762338095de26 --- .../example/Alpha_complex_from_points.cpp | 2 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 35 ++++++++++------------ src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 2 +- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index e2610dbd..e460f177 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -33,7 +33,7 @@ int main(int argc, char **argv) { // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- double max_alpha_square_value = 1e10; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points, max_alpha_square_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, max_alpha_square_value); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 6b47ace7..562b80c3 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -32,9 +32,6 @@ #include #include -#include -#include -#include #include #include @@ -73,6 +70,7 @@ class Alpha_complex : public Simplex_tree<> { typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; + typedef typename Kernel::Point_dimension_d Point_Dimension; typedef typename Kernel::Point_d Point_d; @@ -87,13 +85,15 @@ class Alpha_complex : public Simplex_tree<> { // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; - typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; + //typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; + typedef typename std::vector< CGAL_vertex_iterator > Vector_vertex_iterator; private: /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ Map_vertex_iterator_to_handle vertex_iterator_to_handle_; - /** \brief Map to switch from simplex tree vertex handle to CGAL vertex iterator.*/ - Map_vertex_handle_to_iterator vertex_handle_to_iterator_; + /** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator. + * Vertex handles are inserted sequentially, starting at 0.*/ + Vector_vertex_iterator vertex_handle_to_iterator_; /** \brief Pointer on the CGAL Delaunay triangulation.*/ Delaunay_triangulation* triangulation_; /** \brief Kernel for triangulation_ functions access.*/ @@ -131,8 +131,6 @@ class Alpha_complex : public Simplex_tree<> { } /** \brief Alpha_complex constructor from a list of points. - * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize - * the Alpha_complex. * * @param[in] dimension Dimension of points to be inserted. * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d @@ -141,12 +139,16 @@ class Alpha_complex : public Simplex_tree<> { * std::end return input iterators on a Kernel::Point_d. */ template - Alpha_complex(int dimension, const InputPointRange& points, + Alpha_complex(const InputPointRange& points, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(nullptr) { - triangulation_ = new Delaunay_triangulation(dimension); auto first = std::begin(points); auto last = std::end(points); + // point_dimension function initialization + Point_Dimension point_dimension = kernel_.point_dimension_d_object(); + + // Delaunay triangulation is point dimension minus one. + triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); size_type inserted = triangulation_->insert(first, last); if (inserted != (last -first)) { @@ -168,16 +170,11 @@ class Alpha_complex : public Simplex_tree<> { /** \brief get_point returns the point corresponding to the vertex given as parameter. * * @param[in] vertex Vertex handle of the point to retrieve. - * @return The founded point. - * @warning Exception std::out_of_range is thrown in case vertex is not in the map vertex_handle_to_iterator_. + * @return The point found. + * @warning Exception std::out_of_range is thrown in case vertex is not found. */ Point_d get_point(Vertex_handle vertex) const { - auto found_it = vertex_handle_to_iterator_.find(vertex); - if (found_it != vertex_handle_to_iterator_.end()) { - return found_it->second->point(); - } else { - throw std::out_of_range("Vertex out of vector range"); - } + return vertex_handle_to_iterator_.at(vertex)->point(); } private: @@ -219,7 +216,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES vertex_iterator_to_handle_.emplace(vit, vertex_handle); - vertex_handle_to_iterator_.emplace(vertex_handle, vit); + vertex_handle_to_iterator_.push_back(vit); vertex_handle++; } } diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 3aa835ec..f64a8ea9 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- double max_alpha_square_value = 1e10; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(3, points, max_alpha_square_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, max_alpha_square_value); std::cout << "========== Alpha_complex_from_points ==========" << std::endl; -- cgit v1.2.3 From 8881190bccba9da4af0a07c701369099fd7f2277 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 12 Nov 2015 16:26:05 +0000 Subject: code review fix prune_above_filtration and remove_maximal_simplex in Simplex_tree.h make_filtration_non_decreasing and rec_make_filtration_non_decreasing in Simplex_tree.h git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@910 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a20c9da65a5a3294e42ad2dd45a399d77fb5ad30 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 5 ++ .../example/Alpha_complex_from_off.cpp | 6 +- src/Alpha_complex/example/CMakeLists.txt | 2 + src/Alpha_complex/include/gudhi/Alpha_complex.h | 24 ++++-- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 54 +++++++++---- src/Simplex_tree/include/gudhi/Simplex_tree.h | 91 ++++++++++++++++++++++ .../include/gudhi/Delaunay_triangulation_off_io.h | 7 +- src/common/test/dtoffrw_alphashapedoc_result.off | 12 +-- 8 files changed, 166 insertions(+), 35 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 2cb37578..1fb8fdee 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -20,6 +20,9 @@ * along with this program. If not, see . */ +#ifndef INTRO_ALPHA_COMPLEX_H_ +#define INTRO_ALPHA_COMPLEX_H_ + // needs namespace for Doxygen to link on classes namespace Gudhi { // needs namespace for Doxygen to link on classes @@ -117,3 +120,5 @@ namespace alphacomplex { } // namespace alphacomplex } // namespace Gudhi + +#endif // INTRO_ALPHA_COMPLEX_H_ diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index e140fe3d..cd6f5a4b 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -25,7 +25,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); - + // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- @@ -35,14 +35,14 @@ int main(int argc, char **argv) { std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - if (alpha_complex_from_file.filtration(f_simplex) <= alpha_complex_from_file.filtration()) { + //if (alpha_complex_from_file.filtration(f_simplex) <= alpha_complex_from_file.filtration()) { std::cout << " ( "; for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { std::cout << vertex << " "; } std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; std::cout << std::endl; - } + //} } return 0; } diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 10b87f04..24f3a9dc 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIAlphaShapesExample) +add_executable ( flat flat.cpp ) + # need CGAL 4.7 # cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. if(CGAL_FOUND) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 562b80c3..10b290b5 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -105,6 +105,7 @@ class Alpha_complex : public Simplex_tree<> { * the Alpha_complex. * * @param[in] off_file_name OFF file [path and] name. + * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. */ Alpha_complex(const std::string& off_file_name, Filtration_value max_alpha_square = std::numeric_limits::infinity()) @@ -115,25 +116,24 @@ class Alpha_complex : public Simplex_tree<> { exit(-1); // ----- >> } triangulation_ = off_reader.get_complex(); - set_filtration(max_alpha_square); - init(); + init(max_alpha_square); } /** \brief Alpha_complex constructor from a Delaunay triangulation. * * @param[in] triangulation_ptr Pointer on a Delaunay triangulation. + * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. */ Alpha_complex(Delaunay_triangulation* triangulation_ptr, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(triangulation_ptr) { - set_filtration(max_alpha_square); - init(); + init(max_alpha_square); } /** \brief Alpha_complex constructor from a list of points. * - * @param[in] dimension Dimension of points to be inserted. * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d + * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. @@ -155,8 +155,7 @@ class Alpha_complex : public Simplex_tree<> { std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << std::endl; exit(-1); // ----- >> } - set_filtration(max_alpha_square); - init(); + init(max_alpha_square); } /** \brief Alpha_complex destructor from a Delaunay triangulation. @@ -180,12 +179,14 @@ class Alpha_complex : public Simplex_tree<> { private: /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * + * @param[in] max_alpha_square maximum for alpha square value. + * * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more * than 0. * * Initialization can be launched once. */ - void init() { + void init(Filtration_value max_alpha_square) { if (triangulation_ == nullptr) { std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation" << std::endl; return; // ----- >> @@ -287,6 +288,13 @@ class Alpha_complex : public Simplex_tree<> { } } // -------------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------------- + // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension + make_filtration_non_decreasing(); + // Remove all simplices that have a filtration value greater than max_alpha_square + prune_above_filtration(max_alpha_square); + // -------------------------------------------------------------------------------------------- } template diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index f64a8ea9..2912019d 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -88,20 +88,9 @@ BOOST_AUTO_TEST_CASE(ALPHA_DOC_OFF_file_filtered) { std::cout << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_vertices() == NUMBER_OF_VERTICES); - const int NUMBER_OF_SIMPLICES = 25; + const int NUMBER_OF_SIMPLICES = 23; std::cout << "alpha_complex_from_file.num_simplices()=" << alpha_complex_from_file.num_simplices() << std::endl; BOOST_CHECK(alpha_complex_from_file.num_simplices() == NUMBER_OF_SIMPLICES); - - int num_filtered_simplices = 0; - for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - if (alpha_complex_from_file.filtration(f_simplex) <= alpha_complex_from_file.filtration()) { - num_filtered_simplices++; - } - } - const int NUMBER_OF_FILTERED_SIMPLICES = 23; - std::cout << "num_filtered_simplices=" << num_filtered_simplices << std::endl; - BOOST_CHECK(num_filtered_simplices == NUMBER_OF_FILTERED_SIMPLICES); - } bool are_almost_the_same(float a, float b) { @@ -140,8 +129,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - double max_alpha_square_value = 1e10; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, max_alpha_square_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points); std::cout << "========== Alpha_complex_from_points ==========" << std::endl; @@ -210,4 +198,42 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { BOOST_CHECK_THROW (alpha_complex_from_points.get_point(4), std::out_of_range); BOOST_CHECK_THROW (alpha_complex_from_points.get_point(-1), std::out_of_range); BOOST_CHECK_THROW (alpha_complex_from_points.get_point(1234), std::out_of_range); + + // Test after prune_above_filtration + alpha_complex_from_points.prune_above_filtration(0.6); + // Another way to check num_simplices + std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + num_simplices = 0; + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + num_simplices++; + std::cout << " ( "; + for (auto vertex : alpha_complex_from_points.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << alpha_complex_from_points.filtration(f_simplex) << "] "; + std::cout << std::endl; + } + BOOST_CHECK(num_simplices == 10); + std::cout << "alpha_complex_from_points.num_simplices()=" << alpha_complex_from_points.num_simplices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_simplices() == 10); + + std::cout << "alpha_complex_from_points.dimension()=" << alpha_complex_from_points.dimension() << std::endl; + BOOST_CHECK(alpha_complex_from_points.dimension() == 4); + std::cout << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() == 4); + + for (auto f_simplex : alpha_complex_from_points.filtration_simplex_range()) { + switch (alpha_complex_from_points.dimension(f_simplex)) { + case 0: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 0.0)); + break; + case 1: + BOOST_CHECK(are_almost_the_same(alpha_complex_from_points.filtration(f_simplex), 1.0/2.0)); + break; + default: + BOOST_CHECK(false); // Shall not happen + break; + } + } + } diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 35d839e2..8c1beaef 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -39,6 +39,7 @@ #include #include #include // for greater<> +#include // for numeric_limits infinity namespace Gudhi { /** \defgroup simplex_tree Filtered Complexes @@ -1098,6 +1099,96 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } + + public: + /** \brief Browse the simplex tree to ensure the filtration is not decreasing. + * @return The filtration modification information in order to trigger initialize_filtration. + * \warning initialize_filtration is launched again in case of filtration modification change. + */ + bool make_filtration_non_decreasing() { + bool modified = false; + for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { + if (has_children(sh)) { + modified = modified || rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + } + } + if (modified) { + initialize_filtration(); + } + return modified; + } + + private: + /** \brief Recursively Browse the simplex tree to ensure the filtration is not decreasing. + * @param[in] sib Siblings to be parsed. + * @param[in] upper_filtration Upper level filtration value in the simplex tree. + * @return The filtration modification information in order to trigger initialize_filtration. + */ + bool rec_make_filtration_non_decreasing(Siblings * sib, Filtration_value upper_filtration) { + bool modified = false; + for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { + if (sh->second.filtration() < upper_filtration) { + // Store the filtration modification information + modified = true; + std::cout << "modified" << std::endl; + sh->second.assign_filtration(upper_filtration); + } + if (has_children(sh)) { + modified = modified || rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + } + } + // Make the modified information to be traced by upper call + return modified; + } + + public: + /** \brief Prune above filtration value given as parameter. + * @param[in] filtration Maximum threshold value. + * \warning threshold_ is set from filtration given as parameter. + * \warning The filtration must be valid. If the filtration has not been initialized yet, the method initializes it + * (i.e. order the simplices). If the complex has changed since the last time the filtration was initialized, please + * call `initialize_filtration()` to recompute it. + */ + void prune_above_filtration(Filtration_value filtration) { + threshold_ = filtration; + if (filtration != std::numeric_limits::infinity()) { + // Initialize filtration_vect_ if required + if (filtration_vect_.empty()) { + initialize_filtration(); + } + + // Loop in reverse mode until threshold is reached + auto f_simplex = filtration_vect_.rbegin(); + for (; f_simplex != filtration_vect_.rend() && ((*f_simplex)->second.filtration() > threshold_); f_simplex++) { + remove_maximal_simplex(*f_simplex); + } + // Do not forget to update filtration_vect_ - resize is enough + std::size_t new_size = filtration_vect_.size() - (f_simplex - filtration_vect_.rbegin()); + filtration_vect_.resize(new_size); + } + } + + private: + /** \brief Remove a maximal simplex. + * @param[in] sh Simplex handle on the maximal simplex to remove. + * \warning Exception std::invalid_argument is thrown in sh has children. + */ + void remove_maximal_simplex(Simplex_handle sh) { + // Guarantee the simplex is maximal + if (has_children(sh)) { + throw std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument is not a maximal simplex"); + } + // Simplex is a leaf, it means the child is the Siblings owning the leaf. + Siblings* child = sh->second.children(); + if (child->size() > 1) { + // Not alone, just remove it from members + child->members().erase(sh->first); + } else { + // Sibling is emptied : must be deleted, and its parent must point on his own Sibling + child->oncles()->members().at(child->parent()).assign_children(child->oncles()); + delete child; + } + } private: Vertex_handle null_vertex_; diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 47066a94..4d26bb71 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -19,8 +19,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ -#define SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ +#ifndef DELAUNAY_TRIANGULATION_OFF_IO_H_ +#define DELAUNAY_TRIANGULATION_OFF_IO_H_ #include #include @@ -256,7 +256,6 @@ class Delaunay_triangulation_off_writer { // no endl on next line - don't know why... stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << complex_ptr->number_of_finite_full_cells() << " 0"; - } // bimap to retrieve vertex handles from points and vice versa @@ -305,4 +304,4 @@ class Delaunay_triangulation_off_writer { } // namespace Gudhi -#endif // SRC_ALPHA_SHAPES_INCLUDE_GUDHI_ALPHA_SHAPES_DELAUNAY_TRIANGULATION_OFF_IO_H_ +#endif // DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off index 13c255c6..03b7ca75 100644 --- a/src/common/test/dtoffrw_alphashapedoc_result.off +++ b/src/common/test/dtoffrw_alphashapedoc_result.off @@ -7,9 +7,9 @@ nOFF 0 14 2 19 9 17 -3 1 2 3 -3 4 3 2 -3 5 1 3 -3 5 3 7 -3 7 3 4 -3 6 5 7 +3 0 1 2 +3 3 2 1 +3 4 0 2 +3 4 2 6 +3 6 2 3 +3 5 4 6 -- cgit v1.2.3 From c972b77524faec5d6f297d442539f65b9351654e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 13 Nov 2015 16:41:12 +0000 Subject: Utils.h -> Debug_utils.h More verbose in debug mode (use NDEBUG instead of DEBUG_TRACES) GUDHI_CHECK function to throw in debug or ignore in release mode git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@911 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 250dc0c0f5146f0b9e3fce0e9a8ca0da6af7cf98 --- CMakeLists.txt | 21 +++-- src/Alpha_complex/example/CMakeLists.txt | 4 - src/Alpha_complex/include/gudhi/Alpha_complex.h | 96 +++++++++------------- src/Alpha_complex/test/CMakeLists.txt | 4 - src/CMakeLists.txt | 13 ++- .../policies/Link_condition_valid_contraction.h | 2 +- src/Contraction/include/gudhi/Edge_contraction.h | 2 +- .../include/gudhi/Skeleton_blocker_contractor.h | 2 +- src/Simplex_tree/include/gudhi/Simplex_tree.h | 40 ++++----- .../include/gudhi/Skeleton_blocker.h | 2 +- .../Skeleton_blocker_sub_complex.h | 2 +- .../Skeleton_blockers_simplices_iterators.h | 2 +- .../include/gudhi/Skeleton_blocker_complex.h | 2 +- .../gudhi/Skeleton_blocker_geometric_complex.h | 2 +- .../include/gudhi/Skeleton_blocker_link_complex.h | 2 +- .../test/TestSkeletonBlockerComplex.cpp | 2 +- .../example/Delaunay_triangulation_off_rw.cpp | 5 ++ src/common/include/gudhi/Debug_utils.h | 53 ++++++++++++ .../include/gudhi/Delaunay_triangulation_off_io.h | 19 ++--- src/common/include/gudhi/Utils.h | 46 ----------- 20 files changed, 162 insertions(+), 159 deletions(-) create mode 100644 src/common/include/gudhi/Debug_utils.h delete mode 100644 src/common/include/gudhi/Utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 460196d7..b7fb4540 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,17 +2,26 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIdev) include(CMakeGUDHIVersion.txt) -# Generate GUDHI official version file -configure_file(GUDHIVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIVersion.cmake" @ONLY) -find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework chrono timer program_options thread REQUIRED) +if (NOT CMAKE_BUILD_TYPE) + # Set default build type to Release + set(CMAKE_BUILD_TYPE "Release") +endif() + +if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DNDEBUG) +endif() + +enable_testing() set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/src/cmake/modules/") -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/src/cmake/modules/") -message("CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}") message("CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") -enable_testing() +# Generate GUDHI official version file +configure_file(GUDHIVersion.cmake.in "${PROJECT_BINARY_DIR}/GUDHIVersion.cmake" @ONLY) + +find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework chrono timer program_options thread REQUIRED) if(MSVC) # Turn off some VC++ warnings diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 24f3a9dc..47e42b72 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -29,10 +29,6 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 10b290b5..2cc93a0a 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -26,6 +26,7 @@ // to construct a simplex_tree from Delaunay_triangulation #include #include +#include #include #include // isnan, fmax @@ -39,6 +40,7 @@ #include // NaN #include #include // std::pair +#include namespace Gudhi { @@ -112,7 +114,7 @@ class Alpha_complex : public Simplex_tree<> { : triangulation_(nullptr) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { - std::cerr << "Alpha_complex - Unable to read file " << off_file_name << std::endl; + std::cerr << "Alpha_complex - Unable to read file " << off_file_name; exit(-1); // ----- >> } triangulation_ = off_reader.get_complex(); @@ -137,6 +139,8 @@ class Alpha_complex : public Simplex_tree<> { * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. + * \warning In debug mode, the exception std::invalid_argument is thrown if an empty input point range is passed as + * argument. */ template Alpha_complex(const InputPointRange& points, @@ -144,18 +148,24 @@ class Alpha_complex : public Simplex_tree<> { : triangulation_(nullptr) { auto first = std::begin(points); auto last = std::end(points); - // point_dimension function initialization - Point_Dimension point_dimension = kernel_.point_dimension_d_object(); + + GUDHI_CHECK((first == last), + std::invalid_argument ("Alpha_complex::Alpha_complex(InputPointRange) - Empty input point range")); + + if (first != last) { + // point_dimension function initialization + Point_Dimension point_dimension = kernel_.point_dimension_d_object(); - // Delaunay triangulation is point dimension minus one. - triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); + // Delaunay triangulation is point dimension minus one. + triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); - size_type inserted = triangulation_->insert(first, last); - if (inserted != (last -first)) { - std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << std::endl; - exit(-1); // ----- >> + size_type inserted = triangulation_->insert(first, last); + if (inserted != (last -first)) { + std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first); + exit(-1); // ----- >> + } + init(max_alpha_square); } - init(max_alpha_square); } /** \brief Alpha_complex destructor from a Delaunay triangulation. @@ -188,23 +198,25 @@ class Alpha_complex : public Simplex_tree<> { */ void init(Filtration_value max_alpha_square) { if (triangulation_ == nullptr) { - std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation" << std::endl; + std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation"; return; // ----- >> } if (triangulation_->number_of_vertices() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices" << std::endl; + std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices"; return; // ----- >> } if (triangulation_->maximal_dimension() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation" << std::endl; + std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation"; return; // ----- >> } if (num_vertices() > 0) { - std::cerr << "Alpha_complex init - Cannot init twice" << std::endl; + std::cerr << "Alpha_complex init - Cannot init twice"; return; // ----- >> } set_dimension(triangulation_->maximal_dimension()); + // set_filtration to +inf for prune_above_filtration to be done (if necessary) + set_filtration(std::numeric_limits::infinity()); // -------------------------------------------------------------------------------------------- // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa @@ -213,9 +225,9 @@ class Alpha_complex : public Simplex_tree<> { // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { if (!triangulation_->is_infinite(*vit)) { -#ifdef DEBUG_TRACES - std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; -#endif // DEBUG_TRACES + DBGMSG("Vertex insertion - ", vertex_handle); + DBGMSG(" -> ", vit->point()); + vertex_iterator_to_handle_.emplace(vit, vertex_handle); vertex_handle_to_iterator_.push_back(vit); vertex_handle++; @@ -227,21 +239,12 @@ class Alpha_complex : public Simplex_tree<> { // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { Vector_vertex vertexVector; -#ifdef DEBUG_TRACES - std::cout << "Simplex_tree insertion "; -#endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { if (*vit != nullptr) { -#ifdef DEBUG_TRACES - std::cout << " " << vertex_iterator_to_handle_[*vit]; -#endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure vertexVector.push_back(vertex_iterator_to_handle_[*vit]); } } -#ifdef DEBUG_TRACES - std::cout << std::endl; -#endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); @@ -256,18 +259,11 @@ class Alpha_complex : public Simplex_tree<> { int f_simplex_dim = dimension(f_simplex); if (decr_dim == f_simplex_dim) { Vector_of_CGAL_points pointVector; -#ifdef DEBUG_TRACES - std::cout << "Sigma of dim " << decr_dim << " is"; -#endif // DEBUG_TRACES + DBGMSG("Sigma of dim ", decr_dim); for (auto vertex : simplex_vertex_range(f_simplex)) { pointVector.push_back(get_point(vertex)); -#ifdef DEBUG_TRACES - std::cout << " " << vertex; -#endif // DEBUG_TRACES } -#ifdef DEBUG_TRACES - std::cout << std::endl; -#endif // DEBUG_TRACES + DBGCONT(simplex_vertex_range(f_simplex)); // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) if (isnan(filtration(f_simplex))) { Filtration_value alpha_complex_filtration = 0.0; @@ -279,9 +275,7 @@ class Alpha_complex : public Simplex_tree<> { alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } assign_filtration(f_simplex, alpha_complex_filtration); -#ifdef DEBUG_TRACES - std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl; -#endif // DEBUG_TRACES + DBGMSG("filt(Sigma) is NaN : filt(Sigma) =", filtration(f_simplex)); } propagate_alpha_filtration(f_simplex, decr_dim); } @@ -301,23 +295,16 @@ class Alpha_complex : public Simplex_tree<> { void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { // ### Foreach Tau face of Sigma for (auto f_boundary : boundary_simplex_range(f_simplex)) { -#ifdef DEBUG_TRACES - std::cout << " | --------------------------------------------------\n"; - std::cout << " | Tau "; - for (auto vertex : simplex_vertex_range(f_boundary)) { - std::cout << vertex << " "; - } - std::cout << "is a face of Sigma\n"; - std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl; -#endif // DEBUG_TRACES + DBG("------------- TAU -------------"); + DBGCONT(simplex_vertex_range(f_boundary)); + DBG("is a face of Sigma"); + DBGMSG("isnan(filtration(Tau)=", isnan(filtration(f_boundary))); // ### If filt(Tau) is not NaN if (!isnan(filtration(f_boundary))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); assign_filtration(f_boundary, alpha_complex_filtration); -#ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl; -#endif // DEBUG_TRACES + DBGMSG("filt(Tau) = fmin(filt(Tau), filt(Sigma)) = ", filtration(f_boundary)); // ### Else } else { // No need to compute is_gabriel for dimension <= 2 @@ -344,17 +331,14 @@ class Alpha_complex : public Simplex_tree<> { Is_Gabriel is_gabriel = kernel_.side_of_bounded_sphere_d_object(); bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), point_for_gabriel) != CGAL::ON_BOUNDED_SIDE; -#ifdef DEBUG_TRACES - std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; -#endif // DEBUG_TRACES + DBGMSG("Tau is_gabriel(Sigma)=", is_gab); + DBGMSG(" - vertexForGabriel=", vertexForGabriel); // ### If Tau is not Gabriel of Sigma if (false == is_gab) { // ### filt(Tau) = filt(Sigma) Filtration_value alpha_complex_filtration = filtration(f_simplex); assign_filtration(f_boundary, alpha_complex_filtration); -#ifdef DEBUG_TRACES - std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl; -#endif // DEBUG_TRACES + DBGMSG("filt(Tau) = filt(Sigma) = ", filtration(f_boundary)); } } } diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 847581aa..fa24e1b1 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -14,10 +14,6 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) include_directories (BEFORE "../../include") - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp ) target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd7f4991..0f946e3b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,15 +3,22 @@ project(GUDHI) include("CMakeGUDHIVersion.txt") +if (NOT CMAKE_BUILD_TYPE) + # Set default build type to Release + set(CMAKE_BUILD_TYPE "Release") +endif() + +if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DNDEBUG) +endif() + enable_testing() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") find_package(Boost REQUIRED COMPONENTS system filesystem program_options chrono timer REQUIRED) -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release") -endif() if(MSVC) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4668 /wd4311 /wd4800 /wd4820 /wd4503 /wd4244 /wd4345 /wd4996 /wd4396 /wd4018") else() diff --git a/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h b/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h index 919df243..250bba27 100644 --- a/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h +++ b/src/Contraction/include/gudhi/Contraction/policies/Link_condition_valid_contraction.h @@ -23,8 +23,8 @@ #ifndef CONTRACTION_POLICIES_LINK_CONDITION_VALID_CONTRACTION_H_ #define CONTRACTION_POLICIES_LINK_CONDITION_VALID_CONTRACTION_H_ -#include #include +#include namespace Gudhi { diff --git a/src/Contraction/include/gudhi/Edge_contraction.h b/src/Contraction/include/gudhi/Edge_contraction.h index 349bb7d8..011ca9bd 100644 --- a/src/Contraction/include/gudhi/Edge_contraction.h +++ b/src/Contraction/include/gudhi/Edge_contraction.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include namespace Gudhi { diff --git a/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h b/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h index 2759b540..47d798c0 100644 --- a/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h +++ b/src/Contraction/include/gudhi/Skeleton_blocker_contractor.h @@ -37,7 +37,7 @@ #include #include -#include +#include #include diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 8c1beaef..dc8591fc 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -39,7 +40,8 @@ #include #include #include // for greater<> -#include // for numeric_limits infinity +#include +#include // Inf namespace Gudhi { /** \defgroup simplex_tree Filtered Complexes @@ -717,7 +719,7 @@ class Simplex_tree { } else if (the_simplex.size() == 1) { // When reaching the end of recursivity, vector of simplices shall be empty and filled on back recursive if ((to_be_inserted.size() != 0) || (to_be_propagated.size() != 0)) { - std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty" << std::endl; + std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Error vector not empty"; exit(-1); } std::vector first_simplex(1, the_simplex.back()); @@ -726,7 +728,7 @@ class Simplex_tree { insert_result = insert_vertex_vector(first_simplex, filtration); } else { - std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error" << std::endl; + std::cerr << "Simplex_tree::rec_insert_simplex_and_subfaces - Recursivity error"; exit(-1); } return insert_result; @@ -1099,22 +1101,23 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } - + public: /** \brief Browse the simplex tree to ensure the filtration is not decreasing. - * @return The filtration modification information in order to trigger initialize_filtration. - * \warning initialize_filtration is launched again in case of filtration modification change. + * The simplex tree is browsed starting from the root until the leaf, and the filtration values are set with their + * parent value (increased), in case the values are decreasing. + * @return The filtration modification information. + * \warning Some simplex tree functions require the filtration to be valid. `make_filtration_non_decreasing()` + * function is not launching `initialize_filtration()` but returns the filtration modification information. If the + * complex has changed , please call `initialize_filtration()` to recompute it. */ bool make_filtration_non_decreasing() { bool modified = false; for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { if (has_children(sh)) { - modified = modified || rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); } } - if (modified) { - initialize_filtration(); - } return modified; } @@ -1134,7 +1137,7 @@ class Simplex_tree { sh->second.assign_filtration(upper_filtration); } if (has_children(sh)) { - modified = modified || rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); } } // Make the modified information to be traced by upper call @@ -1150,8 +1153,8 @@ class Simplex_tree { * call `initialize_filtration()` to recompute it. */ void prune_above_filtration(Filtration_value filtration) { - threshold_ = filtration; - if (filtration != std::numeric_limits::infinity()) { + if (filtration < threshold_) { + threshold_ = filtration; // Initialize filtration_vect_ if required if (filtration_vect_.empty()) { initialize_filtration(); @@ -1168,16 +1171,15 @@ class Simplex_tree { } } - private: /** \brief Remove a maximal simplex. * @param[in] sh Simplex handle on the maximal simplex to remove. - * \warning Exception std::invalid_argument is thrown in sh has children. + * \warning In debug mode, the exception std::invalid_argument is thrown if sh has children. */ void remove_maximal_simplex(Simplex_handle sh) { - // Guarantee the simplex is maximal - if (has_children(sh)) { - throw std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument is not a maximal simplex"); - } + // Guarantee the simplex has no children + GUDHI_CHECK(has_children(sh), + std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument is not a maximal simplex")); + // Simplex is a leaf, it means the child is the Siblings owning the leaf. Siblings* child = sh->second.children(); if (child->size() > 1) { diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h index 3be480fd..20df93eb 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker.h @@ -31,7 +31,7 @@ #include #include -#include // xxx +#include namespace Gudhi { diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h index b33b9606..1b1fe3f0 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h index 4d71b3f5..27411fc1 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h index d26d12b0..dc2d9e29 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_complex.h @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h index b8395251..3725b7a2 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_geometric_complex.h @@ -22,9 +22,9 @@ #ifndef SKELETON_BLOCKER_GEOMETRIC_COMPLEX_H_ #define SKELETON_BLOCKER_GEOMETRIC_COMPLEX_H_ -#include #include #include +#include namespace Gudhi { diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h index 95d8fa97..3d0039a1 100644 --- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h +++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h @@ -22,8 +22,8 @@ #ifndef SKELETON_BLOCKER_LINK_COMPLEX_H_ #define SKELETON_BLOCKER_LINK_COMPLEX_H_ -#include #include +#include namespace Gudhi { diff --git a/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp b/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp index 319e3c43..d56a5c91 100644 --- a/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp +++ b/src/Skeleton_blocker/test/TestSkeletonBlockerComplex.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "gudhi/Utils.h" +#include "gudhi/Debug_utils.h" #include "gudhi/Test.h" #include "gudhi/Skeleton_blocker.h" //#include "gudhi/Skeleton_blocker_link_complex.h" diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp index 75e4fafb..12accd10 100644 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -24,6 +24,11 @@ int main(int argc, char **argv) { usage(argv[0]); } + +#ifdef GUDHI_NDEBUG + std::cout << "pouet pouet !!" << std::endl; +#endif + std::string offInputFile(argv[1]); // Read the OFF file (input file name given as parameter) and triangulates points Gudhi::Delaunay_triangulation_off_reader off_reader(offInputFile); diff --git a/src/common/include/gudhi/Debug_utils.h b/src/common/include/gudhi/Debug_utils.h new file mode 100644 index 00000000..c479d435 --- /dev/null +++ b/src/common/include/gudhi/Debug_utils.h @@ -0,0 +1,53 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): David Salinas + * + * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef DEBUG_UTILS_H_ +#define DEBUG_UTILS_H_ + +#include + +#ifdef NDEBUG + // GUDHI_NDEBUG is the Gudhi official flag for debug mode. + #define GUDHI_NDEBUG +#endif + +#define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl + +#ifdef GUDHI_NDEBUG + #define DBG(a) std::cout << "DBG: " << (a) << std::endl + #define DBGMSG(a, b) std::cout << "DBG: " << a << b << std::endl + #define DBGVALUE(a) std::cout << "DBG: " << #a << ": " << a << std::endl + #define DBGCONT(a) std::cout << "DBG: container " << #a << " -> "; for (auto x : a) std::cout << x << ","; std::cout << std::endl +#else + #define DBG(a) (void) 0 + #define DBGMSG(a, b) (void) 0 + #define DBGVALUE(a) (void) 0 + #define DBGCONT(a) (void) 0 +#endif + +// GUDHI_CHECK throw an exception on condition in debug mode, but does nothing in release mode +#ifdef GUDHI_NDEBUG + #define GUDHI_CHECK(cond, excpt) if (cond) throw excpt +#else + #define GUDHI_CHECK(cond, excpt) (void) 0 +#endif + +#endif // DEBUG_UTILS_H_ diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 4d26bb71..dfa70e40 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -22,6 +22,8 @@ #ifndef DELAUNAY_TRIANGULATION_OFF_IO_H_ #define DELAUNAY_TRIANGULATION_OFF_IO_H_ +#include + #include #include #include @@ -64,10 +66,10 @@ class Delaunay_triangulation_off_visitor_reader { * @param[in] num_edges number of edges in the OFF file (not used). */ void init(int dim, int num_vertices, int num_faces, int num_edges) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << - num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; -#endif // DEBUG_TRACES + DBGMSG("Delaunay_triangulation_off_visitor_reader::init - dim=", dim); + DBGMSG(" - num_vertices=", num_vertices); + DBGMSG(" - num_faces=", num_faces); + DBGMSG(" - num_edges=", num_edges); if (num_faces > 0) { std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << "file for Delaunay triangulation - faces are computed." << std::endl; @@ -88,13 +90,8 @@ class Delaunay_triangulation_off_visitor_reader { * @param[in] point vector of vertex coordinates. */ void point(const std::vector& point) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::point "; - for (auto coordinate : point) { - std::cout << coordinate << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES + DBG("Delaunay_triangulation_off_visitor_reader::point"); + DBGCONT(point); complex_->insert(Point(point.size(), point.begin(), point.end())); } diff --git a/src/common/include/gudhi/Utils.h b/src/common/include/gudhi/Utils.h deleted file mode 100644 index 43916f11..00000000 --- a/src/common/include/gudhi/Utils.h +++ /dev/null @@ -1,46 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): David Salinas - * - * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef UTILS_H_ -#define UTILS_H_ - - -#define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl - -// #define DBG_VERBOSE -#ifdef DBG_VERBOSE -#define DBG(a) std::cerr << "DBG: " << (a) << std::endl -#define DBGMSG(a, b) std::cerr << "DBG: " << a << b << std::endl -#define DBGVALUE(a) std::cerr << "DBG: " << #a << ": " << a << std::endl -#define DBGCONT(a) std::cerr << "DBG: container " << #a << " -> "; for (auto x : a) std::cerr << x << ","; std::cerr << -std::endl -#else -// #define DBG(a) a -// #define DBGMSG(a,b) b -// #define DBGVALUE(a) a -// #define DBGCONT(a) a -#define DBG(a) -#define DBGMSG(a, b) -#define DBGVALUE(a) -#define DBGCONT(a) -#endif - -#endif // UTILS_H_ -- cgit v1.2.3 From fe78c077b00e91b3d316f1d64541008a615664e7 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 18 Nov 2015 12:03:43 +0000 Subject: rev911 rollback code review fix fix prune_above_filtration removing every simplices git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@927 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1660da972bd5198214a0f0384be9be66a5312e74 --- CMakeLists.txt | 5 -- src/Alpha_complex/example/CMakeLists.txt | 6 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 67 ++++++++++++++++------ src/CMakeLists.txt | 5 -- src/Simplex_tree/include/gudhi/Simplex_tree.h | 10 ++-- src/common/example/CMakeLists.txt | 4 ++ .../example/Delaunay_triangulation_off_rw.cpp | 5 -- src/common/include/gudhi/Debug_utils.h | 24 ++++---- .../include/gudhi/Delaunay_triangulation_off_io.h | 19 +++--- 9 files changed, 86 insertions(+), 59 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7fb4540..197b6f95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,11 +8,6 @@ if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") endif() -if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DNDEBUG) -endif() - enable_testing() set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/src/cmake/modules/") diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 47e42b72..10b87f04 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIAlphaShapesExample) -add_executable ( flat flat.cpp ) - # need CGAL 4.7 # cmake -DCGAL_DIR=~/workspace/CGAL-4.7-Ic-41 ../../.. if(CGAL_FOUND) @@ -29,6 +27,10 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 2cc93a0a..6adfa2e6 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -114,7 +114,7 @@ class Alpha_complex : public Simplex_tree<> { : triangulation_(nullptr) { Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { - std::cerr << "Alpha_complex - Unable to read file " << off_file_name; + std::cerr << "Alpha_complex - Unable to read file " << off_file_name << "\n"; exit(-1); // ----- >> } triangulation_ = off_reader.get_complex(); @@ -161,7 +161,7 @@ class Alpha_complex : public Simplex_tree<> { size_type inserted = triangulation_->insert(first, last); if (inserted != (last -first)) { - std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first); + std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << "\n"; exit(-1); // ----- >> } init(max_alpha_square); @@ -198,19 +198,19 @@ class Alpha_complex : public Simplex_tree<> { */ void init(Filtration_value max_alpha_square) { if (triangulation_ == nullptr) { - std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation"; + std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation\n"; return; // ----- >> } if (triangulation_->number_of_vertices() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices"; + std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices\n"; return; // ----- >> } if (triangulation_->maximal_dimension() < 1) { - std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation"; + std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation\n"; return; // ----- >> } if (num_vertices() > 0) { - std::cerr << "Alpha_complex init - Cannot init twice"; + std::cerr << "Alpha_complex init - Cannot init twice\n"; return; // ----- >> } @@ -225,8 +225,9 @@ class Alpha_complex : public Simplex_tree<> { // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { if (!triangulation_->is_infinite(*vit)) { - DBGMSG("Vertex insertion - ", vertex_handle); - DBGMSG(" -> ", vit->point()); +#ifdef DEBUG_TRACES + std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; +#endif // DEBUG_TRACES vertex_iterator_to_handle_.emplace(vit, vertex_handle); vertex_handle_to_iterator_.push_back(vit); @@ -239,12 +240,21 @@ class Alpha_complex : public Simplex_tree<> { // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { Vector_vertex vertexVector; +#ifdef DEBUG_TRACES + std::cout << "Simplex_tree insertion "; +#endif // DEBUG_TRACES for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { if (*vit != nullptr) { +#ifdef DEBUG_TRACES + std::cout << " " << vertex_iterator_to_handle_[*vit]; +#endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure vertexVector.push_back(vertex_iterator_to_handle_[*vit]); } } +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); @@ -259,11 +269,18 @@ class Alpha_complex : public Simplex_tree<> { int f_simplex_dim = dimension(f_simplex); if (decr_dim == f_simplex_dim) { Vector_of_CGAL_points pointVector; - DBGMSG("Sigma of dim ", decr_dim); +#ifdef DEBUG_TRACES + std::cout << "Sigma of dim " << decr_dim << " is"; +#endif // DEBUG_TRACES for (auto vertex : simplex_vertex_range(f_simplex)) { pointVector.push_back(get_point(vertex)); +#ifdef DEBUG_TRACES + std::cout << " " << vertex; +#endif // DEBUG_TRACES } - DBGCONT(simplex_vertex_range(f_simplex)); +#ifdef DEBUG_TRACES + std::cout << std::endl; +#endif // DEBUG_TRACES // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) if (isnan(filtration(f_simplex))) { Filtration_value alpha_complex_filtration = 0.0; @@ -275,7 +292,9 @@ class Alpha_complex : public Simplex_tree<> { alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); } assign_filtration(f_simplex, alpha_complex_filtration); - DBGMSG("filt(Sigma) is NaN : filt(Sigma) =", filtration(f_simplex)); +#ifdef DEBUG_TRACES + std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl; +#endif // DEBUG_TRACES } propagate_alpha_filtration(f_simplex, decr_dim); } @@ -295,16 +314,23 @@ class Alpha_complex : public Simplex_tree<> { void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) { // ### Foreach Tau face of Sigma for (auto f_boundary : boundary_simplex_range(f_simplex)) { - DBG("------------- TAU -------------"); - DBGCONT(simplex_vertex_range(f_boundary)); - DBG("is a face of Sigma"); - DBGMSG("isnan(filtration(Tau)=", isnan(filtration(f_boundary))); +#ifdef DEBUG_TRACES + std::cout << " | --------------------------------------------------\n"; + std::cout << " | Tau "; + for (auto vertex : simplex_vertex_range(f_boundary)) { + std::cout << vertex << " "; + } + std::cout << "is a face of Sigma\n"; + std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl; +#endif // DEBUG_TRACES // ### If filt(Tau) is not NaN if (!isnan(filtration(f_boundary))) { // ### filt(Tau) = fmin(filt(Tau), filt(Sigma)) Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex)); assign_filtration(f_boundary, alpha_complex_filtration); - DBGMSG("filt(Tau) = fmin(filt(Tau), filt(Sigma)) = ", filtration(f_boundary)); +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES // ### Else } else { // No need to compute is_gabriel for dimension <= 2 @@ -331,14 +357,17 @@ class Alpha_complex : public Simplex_tree<> { Is_Gabriel is_gabriel = kernel_.side_of_bounded_sphere_d_object(); bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), point_for_gabriel) != CGAL::ON_BOUNDED_SIDE; - DBGMSG("Tau is_gabriel(Sigma)=", is_gab); - DBGMSG(" - vertexForGabriel=", vertexForGabriel); +#ifdef DEBUG_TRACES + std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl; +#endif // DEBUG_TRACES // ### If Tau is not Gabriel of Sigma if (false == is_gab) { // ### filt(Tau) = filt(Sigma) Filtration_value alpha_complex_filtration = filtration(f_simplex); assign_filtration(f_boundary, alpha_complex_filtration); - DBGMSG("filt(Tau) = filt(Sigma) = ", filtration(f_boundary)); +#ifdef DEBUG_TRACES + std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl; +#endif // DEBUG_TRACES } } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0f946e3b..9d1eac80 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,11 +8,6 @@ if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") endif() -if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DNDEBUG) -endif() - enable_testing() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index dc8591fc..9b4d6af6 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1173,17 +1173,19 @@ class Simplex_tree { /** \brief Remove a maximal simplex. * @param[in] sh Simplex handle on the maximal simplex to remove. + * \pre Please check the simplex has no coface before removing it. * \warning In debug mode, the exception std::invalid_argument is thrown if sh has children. */ void remove_maximal_simplex(Simplex_handle sh) { // Guarantee the simplex has no children GUDHI_CHECK(has_children(sh), - std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument is not a maximal simplex")); - - // Simplex is a leaf, it means the child is the Siblings owning the leaf. + std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument has children")); + + // Simplex is a leaf, it means the child is the Siblings owning the leaf Siblings* child = sh->second.children(); - if (child->size() > 1) { + if ((child->size() > 1) || (child == root())) { // Not alone, just remove it from members + // Special case when child is the root of the simplex tree, just remove it from members child->members().erase(sh->first); } else { // Sibling is emptied : must be deleted, and its parent must point on his own Sibling diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index d29e31e7..089f0c04 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -26,6 +26,10 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) + if (CMAKE_BUILD_TYPE MATCHES Debug) + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp index 12accd10..75e4fafb 100644 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -24,11 +24,6 @@ int main(int argc, char **argv) { usage(argv[0]); } - -#ifdef GUDHI_NDEBUG - std::cout << "pouet pouet !!" << std::endl; -#endif - std::string offInputFile(argv[1]); // Read the OFF file (input file name given as parameter) and triangulates points Gudhi::Delaunay_triangulation_off_reader off_reader(offInputFile); diff --git a/src/common/include/gudhi/Debug_utils.h b/src/common/include/gudhi/Debug_utils.h index c479d435..48d61fef 100644 --- a/src/common/include/gudhi/Debug_utils.h +++ b/src/common/include/gudhi/Debug_utils.h @@ -24,14 +24,23 @@ #include -#ifdef NDEBUG - // GUDHI_NDEBUG is the Gudhi official flag for debug mode. - #define GUDHI_NDEBUG +#ifndef NDEBUG + // GUDHI_DEBUG is the Gudhi official flag for debug mode. + #define GUDHI_DEBUG +#endif + +// GUDHI_CHECK throw an exception on condition in debug mode, but does nothing in release mode +// Could assert in release mode, but cmake sets NDEBUG (for "NO DEBUG") in this mode, means assert does nothing. +#ifdef GUDHI_DEBUG + #define GUDHI_CHECK(cond, excpt) if (cond) throw excpt +#else + #define GUDHI_CHECK(cond, excpt) (void) 0 #endif #define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl -#ifdef GUDHI_NDEBUG +// #define DBG_VERBOSE +#ifdef DBG_VERBOSE #define DBG(a) std::cout << "DBG: " << (a) << std::endl #define DBGMSG(a, b) std::cout << "DBG: " << a << b << std::endl #define DBGVALUE(a) std::cout << "DBG: " << #a << ": " << a << std::endl @@ -43,11 +52,4 @@ #define DBGCONT(a) (void) 0 #endif -// GUDHI_CHECK throw an exception on condition in debug mode, but does nothing in release mode -#ifdef GUDHI_NDEBUG - #define GUDHI_CHECK(cond, excpt) if (cond) throw excpt -#else - #define GUDHI_CHECK(cond, excpt) (void) 0 -#endif - #endif // DEBUG_UTILS_H_ diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index dfa70e40..4d26bb71 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -22,8 +22,6 @@ #ifndef DELAUNAY_TRIANGULATION_OFF_IO_H_ #define DELAUNAY_TRIANGULATION_OFF_IO_H_ -#include - #include #include #include @@ -66,10 +64,10 @@ class Delaunay_triangulation_off_visitor_reader { * @param[in] num_edges number of edges in the OFF file (not used). */ void init(int dim, int num_vertices, int num_faces, int num_edges) { - DBGMSG("Delaunay_triangulation_off_visitor_reader::init - dim=", dim); - DBGMSG(" - num_vertices=", num_vertices); - DBGMSG(" - num_faces=", num_faces); - DBGMSG(" - num_edges=", num_edges); +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; +#endif // DEBUG_TRACES if (num_faces > 0) { std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << "file for Delaunay triangulation - faces are computed." << std::endl; @@ -90,8 +88,13 @@ class Delaunay_triangulation_off_visitor_reader { * @param[in] point vector of vertex coordinates. */ void point(const std::vector& point) { - DBG("Delaunay_triangulation_off_visitor_reader::point"); - DBGCONT(point); +#ifdef DEBUG_TRACES + std::cout << "Delaunay_triangulation_off_visitor_reader::point "; + for (auto coordinate : point) { + std::cout << coordinate << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES complex_->insert(Point(point.size(), point.begin(), point.end())); } -- cgit v1.2.3 From c79ddda239336378d50255ef99ea6c34ceefbb47 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 27 Nov 2015 17:05:22 +0000 Subject: After doc review git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@931 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 578da0e6fff453560e666e8f00147f9e10cb6de6 --- CMakeLists.txt | 6 + src/Alpha_complex/doc/Intro_alpha_complex.h | 91 +++- .../doc/alpha_complex_doc_alpha_shape.ipe | 482 --------------------- .../doc/alpha_complex_doc_alpha_shape.png | Bin 62759 -> 0 bytes .../doc/alpha_complex_representation.ipe | 321 ++++++++++++++ .../example/Alpha_complex_from_off.cpp | 16 +- .../example/Alpha_complex_from_points.cpp | 36 +- src/Alpha_complex/example/CMakeLists.txt | 4 - .../example/alphaoffreader_for_doc.txt | 27 -- .../example/alphaoffreader_for_doc_32.txt | 22 + .../example/alphaoffreader_for_doc_60.txt | 27 ++ src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 + src/CMakeLists.txt | 6 + src/Doxyfile | 3 +- src/GudhUI/CMakeLists.txt | 4 - src/Persistent_cohomology/example/CMakeLists.txt | 8 - src/common/doc/main_page.h | 2 +- src/common/example/CMakeLists.txt | 4 - 18 files changed, 486 insertions(+), 575 deletions(-) delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png create mode 100644 src/Alpha_complex/doc/alpha_complex_representation.ipe delete mode 100644 src/Alpha_complex/example/alphaoffreader_for_doc.txt create mode 100644 src/Alpha_complex/example/alphaoffreader_for_doc_32.txt create mode 100644 src/Alpha_complex/example/alphaoffreader_for_doc_60.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 197b6f95..d42f7af7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,12 @@ else() message(STATUS "boost include dirs:" ${Boost_INCLUDE_DIRS}) message(STATUS "boost library dirs:" ${Boost_LIBRARY_DIRS}) + if (DEBUG_TRACES) + # For programs to be more verbose + message(STATUS "DEBUG_TRACES are activated") + add_definitions(-DDEBUG_TRACES) + endif() + include_directories(src/common/include/) include_directories(src/Alpha_complex/include/) include_directories(src/Bottleneck/include/) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 1fb8fdee..685a4c2f 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -36,48 +36,58 @@ namespace alphacomplex { * * \section definition Definition * - * Alpha_complex is a Simplex_tree constructed from each finite cell of a Delaunay Triangulation. + * Alpha_complex is a simplicial complex + * constructed from each finite cell of a Delaunay Triangulation. * * The filtration value of each simplex is computed from the alpha square value of the simplex if it is Gabriel or * from the alpha value of the simplex coface that makes the simplex not Gabriel. * - * Please refer to \cite AlphaShapesDefinition for a more complete alpha complex definition. + * All simplices that have a filtration value strictly greater than a given alpha square value are not inserted into + * the simplex. * - * Alpha complex are interesting because it looks like an \ref alpha-shape "Alpha shape" as described in - * \cite AlphaShapesIntroduction (an alpha complex concept vulgarization). + * \image html "alpha_complex_representation.png" "Alpha simplicial complex representation" * - * \section example Example + * Alpha_complex is constructing a `Simplex_tree` using Delaunay Triangulation + * \cite cgal:hdj-t-15b from CGAL (the Computational Geometry + * Algorithms Library \cite cgal:eb-15b). * - * This example loads points from an OFF file, builds the Delaunay triangulation from the points, and finally - * initialize the alpha complex with it. + * The complex is a template class requiring a dD Geometry Kernel + * \cite cgal:s-gkd-15b from CGAL as template. + * + * \section pointsexample Example from points + * + * This example builds the Delaunay triangulation from the given points in a 2D static kernel, and initializes the + * alpha complex with it. * * Then, it is asked to display information about the alpha complex. * - * \include Alpha_complex_from_off.cpp + * \include Alpha_complex_from_points.cpp * * When launching: * - * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off 60.0 + * \code $> ./alphapoints 60.0 * \endcode * * the program output is: * - * \include alphaoffreader_for_doc.txt + * \include alphaoffreader_for_doc_60.txt * * \section algorithm Algorithm * - * Data structure + * \subsection datastructure Data structure * * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. * (The filtration value is set to NaN, which stands for unknown value): * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" * - * Filtration value computation algorithm - * + * \subsection filtrationcomputation Filtration value computation algorithm + * * \f{algorithm}{ * \caption{Filtration value computation algorithm}\label{alpha} * \begin{algorithmic} - * \For{i : dimension $\rightarrow$ 1} + * \For{i : dimension $\rightarrow$ 0} * \ForAll{$\sigma$ of dimension i} * \If {filtration($\sigma$) is NaN} * \State filtration($\sigma$) = $\alpha^2(\sigma)$ @@ -93,25 +103,58 @@ namespace alphacomplex { * \EndFor * \EndFor * \EndFor + * \State make\_filtration\_non\_decreasing() + * \State prune\_above\_filtration() * \end{algorithmic} * \f} * - * From the example above, it means the algorithm will look into each triangle ([1,2,3], [2,3,4], [1,3,5], ...), - * will compute the filtration value of the triangle, and then will propagate the filtration value as described + * \subsubsection dimension2 Dimension 2 + * + * From the example above, it means the algorithm looks into each triangle ([1,2,3], [2,3,4], [1,3,5], ...), + * computes the filtration value of the triangle, and then propagates the filtration value as described * here : * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" - * Then, the algorithm will look into each edge ([1,2], [2,3], [1,3], ...), - * will compute the filtration value of the edge (in this case, propagation will have no effect). * - * Finally, the algorithm will look into each vertex ([1], [2], [3], [4], [5], [6] and [7]), - * will set the filtration value (0 in case of a vertex - propagation will have no effect). + * \subsubsection dimension1 Dimension 1 + * + * Then, the algorithm looks into each edge ([1,2], [2,3], [1,3], ...), + * computes the filtration value of the edge (in this case, propagation will have no effect). + * + * \subsubsection dimension0 Dimension 0 + * + * Finally, the algorithm looks into each vertex ([1], [2], [3], [4], [5], [6] and [7]) and + * sets the filtration value (0 in case of a vertex - propagation will have no effect). + * + * \subsubsection nondecreasing Non decreasing filtration values + * + * As Alpha square value computed from CGAL is an approximation, we have to make filtration non decreasing while + * increasing the dimension for our simplicial complex to be valid (cf. + * `Simplex_tree::make_filtration_non_decreasing()`). + * + * \subsubsection pruneabove Prune above given filtration value + * + * The simplex tree is pruned from the given maximum alpha square value (cf. `Simplex_tree::prune_above_filtration()`). + * In this example, the value is given by the user as argument of the program. * - * \section alpha-shape Alpha shape * - * In the example above, the alpha shape of \f$\alpha^2_{63} < \alpha^2 < \alpha^2_{62}\f$ is the alpha complex where the - * \f$\alpha^2_{63} <\f$ filtration value \f$< \alpha^2_{62}\f$ as described in \cite AlphaShapesIntroduction + * \section offexample Example from OFF file + * + * This example builds the Delaunay triangulation in a dynamic kernel, and initializes the alpha complex with it. + * + * + * Then, it is asked to display information about the alpha complex. + * + * \include Alpha_complex_from_off.cpp + * + * When launching: + * + * \code $> ./alphaoffreader ../../data/points/alphacomplexdoc.off 32.0 + * \endcode + * + * the program output is: + * + * \include alphaoffreader_for_doc_32.txt * - * \image html "alpha_complex_doc_alpha_shape.png" "Alpha shape example" * \copyright GNU General Public License v3. * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim */ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe deleted file mode 100644 index 7563cf3d..00000000 --- a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.ipe +++ /dev/null @@ -1,482 +0,0 @@ - - - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - -0.6 0 0 0.6 0 0 e - - - - - -0.5 0 0 0.5 0 0 e - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h - - - - - --0.5 -0.5 m -0.5 -0.5 l -0.5 0.5 l --0.5 0.5 l -h - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - - - --0.43 -0.57 m -0.57 0.43 l -0.43 0.57 l --0.57 -0.43 l -h - - --0.43 0.57 m -0.57 -0.43 l -0.43 -0.57 l --0.57 0.43 l -h - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - --1 0.333 m -0 0 l --1 -0.333 l - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Alpha shape -0 -1 -2 -3 -4 -5 -6 -0 -1 -2 -2 -1 -2 -2 -3 -3 -3 -3 -4 -4 -4 -4 -6 -6 -6 -6 -6 -6 -5 -6 -5 - -4 0 0 4 320 704 e - - -322.919 706.788 m -317.189 701.058 l -317.189 701.203 l - - -317.551 706.934 m -322.629 701.058 l - - -230 680 m -240 670 l - - -230 680 m -240 670 l - - -230 680 m -240 670 l - - -230 680 m -240 670 l - - -230 680 m -220 670 l - - -230 680 m -230 670 l - - -220 660 m -220 650 l - - -230 660 m -230 650 l - - -260 680 m -260 670 l - - -260 660 m -260 650 l - - -300 680 m -300 670 l - - -300 680 m -290 670 l - - -290 660 m -290 650 l - - -300 660 m -300 650 l - - -330 680 m -330 670 l - - -350 680 m -350 670 l - - -350 660 m -350 650 l - - -320 700 m -240 690 l - - -320 700 m -270 690 l - - -320 700 m -310 690 l - - -320 700 m -330 690 l - - -320 700 m -350 690 l - - -320 700 m -380 690 l - - -320 700 m -400 690 l - -Alpha complex structure - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -58.1341 0 0 58.1341 218.925 692.601 e - - -60 710 m -40 660 l - - -40 660 m -130 690 l - - -130 690 m -60 710 l - - -40 660 m -80 580 l - - -80 580 m -130 580 l -130 580 l - - -130 580 m -110 520 l - - -110 520 m -50 530 l -50 530 l -50 530 l - - -50 530 m -80 580 l - - -130 580 m -130 690 l - - - -108.275 743.531 m -166.45 743.531 l - -$\alpha$ -filtration value $> \alpha$ are greyed - -280 660 m -300 680 l - - -280 660 m -300 640 l - - -370 660 m -350 680 l - - -370 660 m -350 640 l - - -290 670 m -360 670 l - - -290 650 m -360 650 l - -equivalent - - diff --git a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png b/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png deleted file mode 100644 index 2d5f59a3..00000000 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_alpha_shape.png and /dev/null differ diff --git a/src/Alpha_complex/doc/alpha_complex_representation.ipe b/src/Alpha_complex/doc/alpha_complex_representation.ipe new file mode 100644 index 00000000..8687d694 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_representation.ipe @@ -0,0 +1,321 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +109.771 601.912 m +159.595 601.797 l +140.058 541.915 l +h + + +79.8776 552.169 m +109.756 601.699 l +139.812 542.209 l +h + + +69.8453 682.419 m +159.925 712.208 l +90.12 732.039 l +h + +Alpha complex +0 +1 +2 +3 +4 +5 +6 + +58.1341 0 0 58.1341 218.925 692.601 e + + +60 710 m +40 660 l + + +40 660 m +130 690 l + + +130 690 m +60 710 l + + +40 660 m +80 580 l + + +80 580 m +130 580 l +130 580 l + + +130 580 m +110 520 l + + +110 520 m +50 530 l +50 530 l +50 530 l + + +50 530 m +80 580 l + + +130 580 m +130 690 l + + + +108.275 743.531 m +166.45 743.531 l + +$\alpha$ + + + + + + +150.038 609.9 m +179.929 549.727 l + + + + + diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index cd6f5a4b..4f381892 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,8 +1,6 @@ #include #include -// to construct a Delaunay_triangulation from a OFF file -#include #include void usage(char * const progName) { @@ -35,14 +33,12 @@ int main(int argc, char **argv) { std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - //if (alpha_complex_from_file.filtration(f_simplex) <= alpha_complex_from_file.filtration()) { - std::cout << " ( "; - for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { - std::cout << vertex << " "; - } - std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; - std::cout << std::endl; - //} + std::cout << " ( "; + for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; + std::cout << std::endl; } return 0; } diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index e460f177..62f594d1 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -6,34 +6,50 @@ #include #include -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" -#include "gudhi/Alpha_complex.h" +#include -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel; typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; +void usage(char * const progName) { + std::cerr << "Usage: " << progName << " alpha_square_max_value" << std::endl; + std::cerr << " i.e.: " << progName << " 32.0" << std::endl; + exit(-1); // ----- >> +} + int main(int argc, char **argv) { + if (argc != 2) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + usage(argv[0]); + } + + double alpha_square_max_value = atof(argv[1]); + // ---------------------------------------------------------------------------- // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - std::vector coords = { 0.0, 0.0, 0.0, 1.0 }; + std::vector coords = { 1.0, 1.0 }; + points.push_back(Point(coords.begin(), coords.end())); + coords = { 7.0, 0.0 }; + points.push_back(Point(coords.begin(), coords.end())); + coords = { 4.0, 6.0 }; + points.push_back(Point(coords.begin(), coords.end())); + coords = { 9.0, 6.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords = { 0.0, 0.0, 1.0, 0.0 }; + coords = { 0.0, 14.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords = { 0.0, 1.0, 0.0, 0.0 }; + coords = { 2.0, 19.0 }; points.push_back(Point(coords.begin(), coords.end())); - coords = { 1.0, 0.0, 0.0, 0.0 }; + coords = { 9.0, 17.0 }; points.push_back(Point(coords.begin(), coords.end())); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points // ---------------------------------------------------------------------------- - double max_alpha_square_value = 1e10; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, max_alpha_square_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_points(points, alpha_square_max_value); // ---------------------------------------------------------------------------- // Display information about the alpha complex diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 10b87f04..33ff6805 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -27,10 +27,6 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc.txt b/src/Alpha_complex/example/alphaoffreader_for_doc.txt deleted file mode 100644 index 71f29a00..00000000 --- a/src/Alpha_complex/example/alphaoffreader_for_doc.txt +++ /dev/null @@ -1,27 +0,0 @@ -Alpha complex is of dimension 2 - 25 simplices - 7 vertices. -Iterator on alpha complex simplices in the filtration order, with [filtration value]: - ( 0 ) -> [0] - ( 1 ) -> [0] - ( 2 ) -> [0] - ( 3 ) -> [0] - ( 4 ) -> [0] - ( 5 ) -> [0] - ( 6 ) -> [0] - ( 3 2 ) -> [6.25] - ( 5 4 ) -> [7.25] - ( 2 0 ) -> [8.5] - ( 1 0 ) -> [9.25] - ( 3 1 ) -> [10] - ( 2 1 ) -> [11.25] - ( 3 2 1 ) -> [12.5] - ( 2 1 0 ) -> [12.9959] - ( 6 5 ) -> [13.25] - ( 4 2 ) -> [20] - ( 6 4 ) -> [22.7367] - ( 6 5 4 ) -> [22.7367] - ( 6 3 ) -> [30.25] - ( 6 2 ) -> [36.5] - ( 6 3 2 ) -> [36.5] - ( 6 4 2 ) -> [37.2449] - ( 4 0 ) -> [59.7107] - ( 4 2 0 ) -> [59.7107] diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt new file mode 100644 index 00000000..553431a9 --- /dev/null +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt @@ -0,0 +1,22 @@ +Alpha complex is of dimension 2 - 20 simplices - 7 vertices. +Iterator on alpha complex simplices in the filtration order, with [filtration value]: + ( 0 ) -> [0] + ( 1 ) -> [0] + ( 2 ) -> [0] + ( 3 ) -> [0] + ( 4 ) -> [0] + ( 5 ) -> [0] + ( 6 ) -> [0] + ( 5 4 ) -> [6.25] + ( 4 1 ) -> [20] + ( 4 2 ) -> [8.5] + ( 6 2 ) -> [9.25] + ( 6 5 ) -> [10] + ( 6 4 ) -> [11.25] + ( 6 5 4 ) -> [12.5] + ( 6 4 2 ) -> [12.9959] + ( 3 0 ) -> [13.25] + ( 4 1 ) -> [20] + ( 1 0 ) -> [22.7367] + ( 3 1 0 ) -> [22.7367] + ( 5 0 ) -> [30.25] diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt new file mode 100644 index 00000000..71f29a00 --- /dev/null +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt @@ -0,0 +1,27 @@ +Alpha complex is of dimension 2 - 25 simplices - 7 vertices. +Iterator on alpha complex simplices in the filtration order, with [filtration value]: + ( 0 ) -> [0] + ( 1 ) -> [0] + ( 2 ) -> [0] + ( 3 ) -> [0] + ( 4 ) -> [0] + ( 5 ) -> [0] + ( 6 ) -> [0] + ( 3 2 ) -> [6.25] + ( 5 4 ) -> [7.25] + ( 2 0 ) -> [8.5] + ( 1 0 ) -> [9.25] + ( 3 1 ) -> [10] + ( 2 1 ) -> [11.25] + ( 3 2 1 ) -> [12.5] + ( 2 1 0 ) -> [12.9959] + ( 6 5 ) -> [13.25] + ( 4 2 ) -> [20] + ( 6 4 ) -> [22.7367] + ( 6 5 4 ) -> [22.7367] + ( 6 3 ) -> [30.25] + ( 6 2 ) -> [36.5] + ( 6 3 2 ) -> [36.5] + ( 6 4 2 ) -> [37.2449] + ( 4 0 ) -> [59.7107] + ( 4 2 0 ) -> [59.7107] diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 6adfa2e6..2dae4028 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -27,6 +27,8 @@ #include #include #include +// to construct a Delaunay_triangulation from a OFF file +#include #include #include // isnan, fmax diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d1eac80..3a75527e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,6 +42,12 @@ else() INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) + if (DEBUG_TRACES) + message(STATUS "DEBUG_TRACES are activated") + # For programs to be more verbose + add_definitions(-DDEBUG_TRACES) + endif() + #--------------------------------------------------------------------------------------- # Gudhi compilation part include_directories(include) diff --git a/src/Doxyfile b/src/Doxyfile index 81f55e29..9cd73444 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -673,6 +673,7 @@ LAYOUT_FILE = # also \cite for info how to create references. CITE_BIB_FILES = biblio/bibliography.bib \ + biblio/how_to_cite_cgal.bib \ biblio/how_to_cite_gudhi.bib #--------------------------------------------------------------------------- @@ -812,7 +813,7 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = biblio/ +EXAMPLE_PATH = biblio/ \ example/common/ \ example/Alpha_complex/ diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index 5c2afdd0..75adba08 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -102,10 +102,6 @@ if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND ) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable (acp alpha_complex_persistence.cpp) target_link_libraries(acp ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${QT_LIBRARIES}) diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index 8caf7d8b..eb4ee3e3 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -35,10 +35,6 @@ if(GMPXX_FOUND AND GMP_FOUND) target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) if(CGAL_FOUND) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable(alpha_shapes_persistence alpha_shapes_persistence.cpp) target_link_libraries(alpha_shapes_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) add_test(alpha_shapes_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) @@ -70,10 +66,6 @@ if(GMPXX_FOUND AND GMP_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable (alphacomplexpersistence alpha_complex_persistence.cpp) target_link_libraries(alphacomplexpersistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 3edcbd0b..3c42f72d 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -63,7 +63,7 @@ * CGAL is a C++ library which provides easy access to efficient and reliable geometric algorithms. * * The following examples require the Computational Geometry Algorithms - * Library (CGAL) and will not be built if CGAL is not installed: + * Library (CGAL \cite cgal:eb-15b) and will not be built if CGAL is not installed: * \li GudhUI * \li Persistent_cohomology/alpha_shapes_persistence * \li Simplex_tree/simplex_tree_from_alpha_shapes_3 diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index 089f0c04..d29e31e7 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -26,10 +26,6 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - if (CMAKE_BUILD_TYPE MATCHES Debug) - # For programs to be more verbose - add_definitions(-DDEBUG_TRACES) - endif() add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) -- cgit v1.2.3 From f9b5b9b3306f3f00f5bfa2724cbfa087d5161fcb Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 11 Dec 2015 15:41:39 +0000 Subject: Commit code and doc review Still issue and lot of logs in simplex_tree::prune_above_filtration git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@945 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: cd4f60ddcacb0444e0eb3b9323d8042eb49b132e --- CMakeLists.txt | 4 +- biblio/bibliography.bib | 16 -- src/Alpha_complex/doc/Intro_alpha_complex.h | 8 +- src/Alpha_complex/doc/alpha_complex_doc.ipe | 24 +- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 46746 -> 49973 bytes src/Alpha_complex/doc/alpha_complex_doc_135.ipe | 88 +++---- src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 127130 -> 80794 bytes .../doc/alpha_complex_representation.png | Bin 0 -> 16737 bytes .../example/Alpha_complex_from_points.cpp | 22 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +- src/Alpha_complex/test/CMakeLists.txt | 2 + src/Simplex_tree/include/gudhi/Simplex_tree.h | 95 ++++++-- .../gudhi/Simplex_tree/Simplex_tree_siblings.h | 4 + src/Simplex_tree/test/simplex_tree_unit_test.cpp | 266 ++++++++++++++++++++- .../example/dtoffrw_alphashapedoc_result.off | 15 ++ .../example/dtoffrw_alphashapedoc_result.txt | 1 - .../include/gudhi/Delaunay_triangulation_off_io.h | 2 +- src/common/test/dtoffrw_unit_test.cpp | 4 +- 18 files changed, 436 insertions(+), 121 deletions(-) create mode 100644 src/Alpha_complex/doc/alpha_complex_representation.png create mode 100644 src/common/example/dtoffrw_alphashapedoc_result.off diff --git a/CMakeLists.txt b/CMakeLists.txt index d42f7af7..d0770dd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,8 @@ if(MSVC) # Turn off some VC++ warnings SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4668 /wd4311 /wd4800 /wd4820 /wd4503 /wd4244 /wd4345 /wd4996 /wd4396 /wd4018") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -std=c++11 -Wall -Wpedantic -Wsign-compare") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -std=c++11 -fsanitize=memory -fno-omit-frame-pointer -Wall -Wpedantic -Wsign-compare") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O1") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") endif() diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index 859696b4..3fd1c10a 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -897,22 +897,6 @@ language={English} bibsource = {DBLP, http://dblp.uni-trier.de} } -@ARTICLE{AlphaShapesDefinition, - author = {N. Akkiraju, H. Edelsbrunner, M. Facello, P. Fu, E. P. Mucke, and C. Varela}, - title = {\href{http://pub.ist.ac.at/~edels/Papers/1995-P-06-AlphaShapesSoftware.pdf}{Alpha shapes: definition and software}}, - journal = {Proc. Internat. Comput. Geom. Software Workshop 1995}, - year = {1995}, - bibsource = {http://pub.ist.ac.at} -} - -@ARTICLE{AlphaShapesIntroduction, - author = {Kaspar Fischer}, - title = {\href{http://www.cs.uu.nl/docs/vakken/ddm/texts/Delaunay/alphashapes.pdf}{Introduction to Alpha Shapes}}, - journal = {Unknown}, - year = {Unknown}, - bibsource = {http://www.cs.uu.nl} -} - misc{buddha_stanford_scan, author = "", title = "The Stanford 3D Scanning Repository", diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 685a4c2f..12d62ac0 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -37,10 +37,10 @@ namespace alphacomplex { * \section definition Definition * * Alpha_complex is a simplicial complex - * constructed from each finite cell of a Delaunay Triangulation. + * constructed from the finite cells of a Delaunay Triangulation. * - * The filtration value of each simplex is computed from the alpha square value of the simplex if it is Gabriel or - * from the alpha value of the simplex coface that makes the simplex not Gabriel. + * The filtration value of each simplex is computed from the circumradius of the simplex if it is Gabriel or + * from the alpha value of the simplex cofaces that make it not Gabriel. * * All simplices that have a filtration value strictly greater than a given alpha square value are not inserted into * the simplex. @@ -78,7 +78,7 @@ namespace alphacomplex { * * \subsection datastructure Data structure * - * In order to build the alpha complex, first, a Simplex tree is build from the cells of a Delaunay Triangulation. + * In order to build the alpha complex, first, a Simplex tree is built from the cells of a Delaunay Triangulation. * (The filtration value is set to NaN, which stands for unknown value): * \image html "alpha_complex_doc.png" "Simplex tree structure construction example" * diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe index b5601143..e74f9bc4 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -1,7 +1,7 @@ - - + + @@ -202,13 +202,13 @@ h + + - - @@ -232,14 +232,7 @@ h - - - - - - - - + 320 580 m 350 520 l 290 530 l @@ -434,5 +427,12 @@ h 280 610 m 170 610 l + + + + + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index 601ac051..c9eab275 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc.png and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe index 28b893b8..5d1d29d4 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe @@ -1,7 +1,7 @@ - - + + @@ -202,13 +202,13 @@ h + + - - @@ -232,14 +232,7 @@ h - - - - - - - - + 320 580 m 350 520 l 290 530 l @@ -288,19 +281,11 @@ h 77.2727 0 0 77.2727 243.636 591.818 e - 243.428 591.569 m 186.061 643.28 l $\alpha_{420}$ - - - - - - - 320 580 m 350 520 l @@ -325,7 +310,6 @@ h modified (NaN) 0 -1 2 3 4 @@ -357,18 +341,10 @@ modified (NaN) 29.1548 0 0 29.1548 305 555 e - 304.883 555.015 m 334.509 555.015 l - - - - - - - 320 580 m 350 520 l @@ -391,10 +367,7 @@ modified (NaN) [0,4] is not Gabriel $\rightarrow$ $\alpha_{40} = \alpha_{420}$ 0 -1 -2 3 -4 5 6 @@ -420,16 +393,6 @@ modified (NaN) 290 530 m 280 660 l - -65.192 0 0 65.192 285 595 e - - - - - - - - 320 580 m 350 520 l @@ -483,7 +446,6 @@ modified (NaN) 44.5799 0 0 44.5799 425.934 457.774 e - 425.854 457.774 m 470.795 457.774 l @@ -505,10 +467,48 @@ modified (NaN) For all faces of [4,2,0] N.B. : is Gabriel on a single point has no sense. Dimension =2 - $\sigma$ = [4,2,0] - 247.333 430.892 m 311.764 430.892 l + + + + + + + + + + + + + +1 + + + + + +4 + + +1 + + +2 + +65.192 0 0 65.192 285 595 e + + + + + + + + + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png index 5dce5edd..ef7187f7 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_135.png and b/src/Alpha_complex/doc/alpha_complex_doc_135.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_representation.png b/src/Alpha_complex/doc/alpha_complex_representation.png new file mode 100644 index 00000000..06e54c06 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_representation.png differ diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 62f594d1..00e988a6 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -30,21 +30,13 @@ int main(int argc, char **argv) { // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - - std::vector coords = { 1.0, 1.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 7.0, 0.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 4.0, 6.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 9.0, 6.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 0.0, 14.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 2.0, 19.0 }; - points.push_back(Point(coords.begin(), coords.end())); - coords = { 9.0, 17.0 }; - points.push_back(Point(coords.begin(), coords.end())); + points.push_back(Point(1.0, 1.0)); + points.push_back(Point(7.0, 0.0)); + points.push_back(Point(4.0, 6.0)); + points.push_back(Point(9.0, 6.0)); + points.push_back(Point(0.0, 14.0)); + points.push_back(Point(2.0, 19.0)); + points.push_back(Point(9.0, 17.0)); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 2dae4028..9f931066 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -125,7 +125,9 @@ class Alpha_complex : public Simplex_tree<> { /** \brief Alpha_complex constructor from a Delaunay triangulation. * - * @param[in] triangulation_ptr Pointer on a Delaunay triangulation. + * @param[in] triangulation_ptr Pointer on a + * CGAL::Delaunay_triangulation \cite cgal:hdj-t-15b. * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. */ Alpha_complex(Delaunay_triangulation* triangulation_ptr, @@ -170,7 +172,7 @@ class Alpha_complex : public Simplex_tree<> { } } - /** \brief Alpha_complex destructor from a Delaunay triangulation. + /** \brief Alpha_complex destructor. * * @warning Deletes the Delaunay triangulation. */ diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index fa24e1b1..d7c13da0 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -18,6 +18,8 @@ if(CGAL_FOUND) add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp ) target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_executable ( cerr cerr.cpp ) + # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 3adf06d3..4b04e75a 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -530,7 +530,7 @@ class Simplex_tree { return dimension_; } - /** \brief Returns true iff the node in the simplex tree pointed by + /** \brief Returns true if the node in the simplex tree pointed by * sh has children.*/ bool has_children(Simplex_handle sh) const { return (sh->second.children()->parent() == sh->first); @@ -1134,7 +1134,6 @@ class Simplex_tree { if (sh->second.filtration() < upper_filtration) { // Store the filtration modification information modified = true; - std::cout << "modified" << std::endl; sh->second.assign_filtration(upper_filtration); } if (has_children(sh)) { @@ -1154,21 +1153,51 @@ class Simplex_tree { * call `initialize_filtration()` to recompute it. */ void prune_above_filtration(Filtration_value filtration) { - if (filtration < threshold_) { - threshold_ = filtration; - // Initialize filtration_vect_ if required - if (filtration_vect_.empty()) { - initialize_filtration(); - } +std::cout << "prune_above_filtration - filtration=" << filtration << std::endl; + // No action if filtration is not stored + if (Options::store_filtration) { + if (filtration < threshold_) { + threshold_ = filtration; + // Initialize filtration_vect_ if required + if (filtration_vect_.empty()) { +std::cout << "prune_above_filtration - initialize_filtration" << std::endl; + initialize_filtration(); + } + +std::cout << "prune_above_filtration - after initialize_filtration "; +for(auto sh : filtration_vect_) { +for (auto vertex : simplex_vertex_range(sh)) { +std::cout << (int) vertex << ", "; +} +std::cout << " - filtration=" << sh->second.filtration() << " - " << &(sh->second) << std::endl; +} - // Loop in reverse mode until threshold is reached - auto f_simplex = filtration_vect_.rbegin(); - for (; f_simplex != filtration_vect_.rend() && ((*f_simplex)->second.filtration() > threshold_); f_simplex++) { - remove_maximal_simplex(*f_simplex); + + // Loop in reverse mode until threshold is reached + auto f_simplex = filtration_vect_.rbegin(); + for (; (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > threshold_); f_simplex++) { + +std::cout << "prune_above_filtration - remove "; +for (auto vertex : simplex_vertex_range(*f_simplex)) { +std::cout << (int) vertex << ", "; +} +std::cout << " - " << &((*f_simplex)->second) << std::endl; + + remove_maximal_simplex(*f_simplex); + } +std::cout << "prune_above_filtration - remove STOPPED ON "; +for (auto vertex : simplex_vertex_range(*f_simplex)) { +std::cout << (int) vertex << ", "; +} +std::cout << " - filtration=" << (*f_simplex)->second.filtration() << " - " << &(*f_simplex->second) << std::endl; + if (f_simplex != filtration_vect_.rbegin()) { + // Do not forget to update filtration_vect_ - resize is enough + std::size_t new_size = filtration_vect_.size() - (f_simplex - filtration_vect_.rbegin()); +std::cout << "prune_above_filtration - resize" << new_size << std::endl; + filtration_vect_.resize(new_size); + } + } - // Do not forget to update filtration_vect_ - resize is enough - std::size_t new_size = filtration_vect_.size() - (f_simplex - filtration_vect_.rbegin()); - filtration_vect_.resize(new_size); } } @@ -1187,14 +1216,46 @@ class Simplex_tree { if ((child->size() > 1) || (child == root())) { // Not alone, just remove it from members // Special case when child is the root of the simplex tree, just remove it from members - child->members().erase(sh->first); +std::cout << "remove_maximal_simplex - members removal" << std::endl; + child->erase(sh->first); } else { // Sibling is emptied : must be deleted, and its parent must point on his own Sibling +std::cout << "remove_maximal_simplex - members is empty" << std::endl; child->oncles()->members().at(child->parent()).assign_children(child->oncles()); delete child; } } - +/***************************************************************************************************************/ + public: + /** \brief Prints the simplex_tree hierarchically. + * Since it prints the vertices recursively, one can watch its tree shape. + */ + void print_tree() { + for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { + std::cout << sh->first << " "; + if (has_children(sh)) { + std::cout << "("; + rec_print(sh->second.children()); + std::cout << ")"; + } + std::cout << std::endl; + } + } + + + /** \brief Recursively prints the simplex_tree, using depth first search. */ + private: + void rec_print(Siblings * sib) { + for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { + std::cout << " " << sh->first << " "; + if (has_children(sh)) { + std::cout << "("; + rec_print(sh->second.children()); + std::cout << ")"; + } + } + } +/*****************************************************************************************************************/ private: Vertex_handle null_vertex_; /** \brief Upper bound on the filtration values of the simplices.*/ diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h index 158ee1f7..c1ff8bf2 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h @@ -116,6 +116,10 @@ class Simplex_tree_siblings { return members_.size(); } + void erase(const Vertex_handle vh) { + members_.erase(vh); + } + Simplex_tree_siblings * oncles_; Vertex_handle parent_; Dictionary members_; diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 00cf69bc..f6bd5411 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -362,7 +362,9 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { } -bool sort_in_decr_order (Vertex_handle i,Vertex_handle j) { return (i>j); } +bool sort_in_decr_order(Vertex_handle i, Vertex_handle j) { + return (i > j); +} BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { std::cout << "********************************************************************" << std::endl; @@ -476,7 +478,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { BOOST_CHECK(vertex == SimplexVector6[position]); position++; } - + /* Inserted simplex: */ /* 1 6 */ /* o---o */ @@ -720,14 +722,268 @@ BOOST_AUTO_TEST_CASE(copy_move_on_simplex_tree) { // Check there is a new simplex tree reference BOOST_CHECK(&st_move != &st_copy); BOOST_CHECK(&st_move != &st); - + typeST st_empty; // Check st has been emptied by the move BOOST_CHECK(st == st_empty); BOOST_CHECK(st.filtration() == 0); BOOST_CHECK(st.dimension() == -1); BOOST_CHECK(st.num_simplices() == 0); - BOOST_CHECK(st.num_vertices() == (size_t)0); - + BOOST_CHECK(st.num_vertices() == (size_t) 0); + std::cout << "Printing st once again- address = " << &st << std::endl; } + +BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) { + std::cout << "********************************************************************" << std::endl; + std::cout << "MAKE FILTRATION NON DECREASING" << std::endl; + typeST st; + + st.insert_simplex_and_subfaces({2, 1, 0}, 4.0); + st.insert_simplex_and_subfaces({3, 0}, 3.0); + st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); + // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 4.0 + // to 1.0 + st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + // FIXME + st.set_dimension(3); + + // Copy constructor + typeST st_copy = st; + + // Check default insertion ensures the filtration values are non decreasing + BOOST_CHECK(!st.make_filtration_non_decreasing()); + // Check the simplex tree is not modified by the function + BOOST_CHECK(st == st_copy); + + // Make { 0, 1 } decreasing + st.assign_filtration(st.find({0, 1}), 0.5); + // Make { 1, 6, 7 } decreasing + st.assign_filtration(st.find({1, 6, 7}), 0.4); + // Make { 3, 4 } decreasing + st.assign_filtration(st.find({3, 4}), 0.3); + // Make { 4, 5 } decreasing + st.assign_filtration(st.find({4, 5}), 0.1); + + // Check the filtration values were decreasing + BOOST_CHECK(st.make_filtration_non_decreasing()); + // Check the simplex tree has been modified by the function to retrieve the initial simplex tree + BOOST_CHECK(st == st_copy); + + // Change { 0, 3 }, but still non decreasing + st.assign_filtration(st.find({0, 3}), 1.01); + // Change { 0, 1, 6, 7 }, but still non decreasing + st.assign_filtration(st.find({0, 1, 6, 7}), 1.201); + // Change { 1, 2 }, but still non decreasing + st.assign_filtration(st.find({1, 2}), 1.05); + // Change { 4 }, but still non decreasing + st.assign_filtration(st.find({4}), 1.123); + + // Check the filtration values are non decreasing + BOOST_CHECK(!st.make_filtration_non_decreasing()); + // Check the simplex tree has been modified from the original + BOOST_CHECK(st != st_copy); + +} + +struct MyOptions : Simplex_tree_options_full_featured { + // Not doing persistence, so we don't need those + static const bool store_key = false; + static const bool store_filtration = false; + // I have few vertices + typedef short Vertex_handle; +}; +typedef Simplex_tree miniST; + +/*BOOST_AUTO_TEST_CASE(remove_maximal_simplex) { + std::cout << "********************************************************************" << std::endl; + std::cout << "REMOVE MAXIMAL SIMPLEX" << std::endl; + + miniST st; + + // FIXME + st.set_dimension(3); + + st.insert_simplex_and_subfaces({0, 1, 6, 7}); + st.insert_simplex_and_subfaces({3, 4, 5}); + + // Constructs a copy at this state for further test purpose + miniST st_pruned = st; + + st.insert_simplex_and_subfaces({3, 0}); + st.insert_simplex_and_subfaces({2, 1, 0}); + + // Constructs a copy at this state for further test purpose + miniST st_complete = st; + // st_complete and st: + // 1 6 + // o---o + // /X\7/ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 + // st_pruned: + // 1 6 + // o---o + // \7/ + // o o---o + // 0 3\X/4 + // o + // 5 + +#ifdef GUDHI_DEBUG + std::cout << "Check exception throw in debug mode" << std::endl; + // throw excpt because sh has children + BOOST_CHECK_THROW (st.remove_maximal_simplex(st.find({0, 1, 6})), std::invalid_argument); + BOOST_CHECK_THROW (st.remove_maximal_simplex(st.find({3})), std::invalid_argument); + BOOST_CHECK(st == st_complete); +#endif + + st.remove_maximal_simplex(st.find({0, 2})); + st.remove_maximal_simplex(st.find({0, 1, 2})); + st.remove_maximal_simplex(st.find({1, 2})); + st.remove_maximal_simplex(st.find({2})); + st.remove_maximal_simplex(st.find({0, 3})); + + BOOST_CHECK(st == st_pruned); + // Remove all, but as the simplex tree is not storing filtration, there is no modification + st.prune_above_filtration(0.0); + BOOST_CHECK(st == st_pruned); + + miniST st_wo_seven; + // FIXME + st_wo_seven.set_dimension(3); + + st_wo_seven.insert_simplex_and_subfaces({0, 1, 6}); + st_wo_seven.insert_simplex_and_subfaces({3, 4, 5}); + // st_wo_seven: + // 1 6 + // o---o + // \X/ + // o o---o + // 0 3\X/4 + // o + // 5 + + // Remove all 7 to test the both remove_maximal_simplex cases (when _members is empty or not) + st.remove_maximal_simplex(st.find({0, 1, 6, 7})); + st.remove_maximal_simplex(st.find({0, 1, 7})); + st.remove_maximal_simplex(st.find({0, 6, 7})); + st.remove_maximal_simplex(st.find({0, 7})); + st.remove_maximal_simplex(st.find({1, 6, 7})); + st.remove_maximal_simplex(st.find({1, 7})); + st.remove_maximal_simplex(st.find({6, 7})); + st.remove_maximal_simplex(st.find({7})); + + BOOST_CHECK(st == st_wo_seven); +}*/ + +BOOST_AUTO_TEST_CASE(prune_above_filtration) { + std::cout << "********************************************************************" << std::endl; + std::cout << "PRUNE ABOVE FILTRATION" << std::endl; + typeST st; + + // FIXME + st.set_dimension(3); + + st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); + st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); + st.set_filtration(6.0); + + // Constructs a copy at this state for further test purpose + typeST st_pruned = st; + st_pruned.initialize_filtration(); // reset + + st.insert_simplex_and_subfaces({3, 0}, 3.0); + st.insert_simplex_and_subfaces({2, 1, 0}, 4.0); + + // Constructs a copy at this state for further test purpose + typeST st_complete = st; + // st_complete and st: + // 1 6 + // o---o + // /X\7/ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 + // st_pruned: + // 1 6 + // o---o + // \7/ + // o o---o + // 0 3\X/4 + // o + // 5 + + // Check the no action cases + // greater than initial filtration value + st.prune_above_filtration(10.0); + BOOST_CHECK(st == st_complete); + // equal to initial filtration value + st.prune_above_filtration(6.0); + BOOST_CHECK(st == st_complete); + // lower than initial filtration value, but still greater than the maximum filtration value + st_complete.set_filtration(5.0); + st.prune_above_filtration(5.0); + BOOST_CHECK(st == st_complete); + + // Display the Simplex_tree - Can not be done in the middle of 2 inserts + std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + std::cout << " " << "[" << st.filtration(f_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; + } + + // Check the pruned cases + // Set the st_pruned filtration for operator== + st_pruned.set_filtration(2.5); + st.prune_above_filtration(2.5); + /*BOOST_CHECK(st == st_pruned); + + st_pruned.set_filtration(2.0); + st.prune_above_filtration(2.0); + BOOST_CHECK(st == st_pruned); +*/ +/* std::cout << "The complex contains " << st.num_simplices() << " simplices --------------------------" << std::endl; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + st.print_tree(); + + std::cout << "The pruned complex contains " << st_pruned.num_simplices() << " simplices --------------------------" << std::endl; + std::cout << " - dimension " << st_pruned.dimension() << " - filtration " << st_pruned.filtration() << std::endl; + st_pruned.print_tree(); + + typeST st_empty; + // FIXME + st_empty.set_dimension(3); + st.prune_above_filtration(0.0); + */ + /*BOOST_CHECK(st == st_empty); + + // Test case to the limit + st.prune_above_filtration(-1.0); + st_empty.set_filtration(-1.0); + BOOST_CHECK(st == st_empty); +*/ +} + +/*BOOST_AUTO_TEST_CASE(sanitizer) { + int a[2] = {1, 0}; + int b=a[2]; +}*/ diff --git a/src/common/example/dtoffrw_alphashapedoc_result.off b/src/common/example/dtoffrw_alphashapedoc_result.off new file mode 100644 index 00000000..03b7ca75 --- /dev/null +++ b/src/common/example/dtoffrw_alphashapedoc_result.off @@ -0,0 +1,15 @@ +nOFF +2 7 6 0 +1 1 +7 0 +4 6 +9 6 +0 14 +2 19 +9 17 +3 0 1 2 +3 3 2 1 +3 4 0 2 +3 4 2 6 +3 6 2 3 +3 5 4 6 diff --git a/src/common/example/dtoffrw_alphashapedoc_result.txt b/src/common/example/dtoffrw_alphashapedoc_result.txt index 57761d14..8e659740 100644 --- a/src/common/example/dtoffrw_alphashapedoc_result.txt +++ b/src/common/example/dtoffrw_alphashapedoc_result.txt @@ -1,3 +1,2 @@ Number of vertices= 7 Number of finite full cells= 6 - diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 6335d243..b3f4a299 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -135,7 +135,7 @@ class Delaunay_triangulation_off_visitor_reader { * * When launching: * - * \code $> ./dtoffrw ../../data/points/alphashapedoc.off triangulated.off + * \code $> ./dtoffrw ../../data/points/alphacomplexdoc triangulated.off * \endcode * * the program output is: diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp index 20094229..f682df1a 100644 --- a/src/common/test/dtoffrw_unit_test.cpp +++ b/src/common/test/dtoffrw_unit_test.cpp @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE( Delaunay_triangulation_doc_test ) BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) { - Gudhi::Delaunay_triangulation_off_reader off_reader("pouetpouet_tralala.off"); + Gudhi::Delaunay_triangulation_off_reader off_reader("some_impossible_weird_file_name.off"); // Check the read operation was correct BOOST_CHECK(!off_reader.is_valid()); T* triangulation = off_reader.get_complex(); @@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_write_test ) T* triangulation = off_reader.get_complex(); // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces - Gudhi::Delaunay_triangulation_off_writer off_writer("/pouetpouet_tralala/pouetpouet_tralala/pouetpouet_tralala.off", triangulation); + Gudhi::Delaunay_triangulation_off_writer off_writer("/some_impossible_weird_directory_name/another_weird_directory_name/some_impossible_weird_file_name.off", triangulation); // Check the write operation was correct BOOST_CHECK(!off_writer.is_valid()); -- cgit v1.2.3 From 11b195d4e26d48cdc56883957cbad16e298e43ca Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 12 Jan 2016 16:07:10 +0000 Subject: Fix alpha complex remarks and bugs git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@957 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fa837fd1a4373c2322db16353d98767907f34c79 --- CMakeLists.txt | 4 +- biblio/how_to_cite_cgal.bib | 947 +++++++++++++++++++++ src/Alpha_complex/test/CMakeLists.txt | 2 - src/GudhUI/alpha_complex_persistence.cpp | 78 -- src/GudhUI/utils/Bar_code_persistence.h | 3 +- src/GudhUI/utils/Persistence_compute.h | 15 +- src/Persistent_cohomology/example/CMakeLists.txt | 100 ++- .../example/alpha_complex_persistence.cpp | 92 +- .../example/rips_persistence.cpp | 3 +- src/Simplex_tree/include/gudhi/Simplex_tree.h | 81 +- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 56 +- src/common/include/gudhi/distance_functions.h | 4 +- src/common/include/gudhi/reader_utils.h | 4 +- 13 files changed, 1140 insertions(+), 249 deletions(-) create mode 100644 biblio/how_to_cite_cgal.bib delete mode 100644 src/GudhUI/alpha_complex_persistence.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d0770dd7..54e86f72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ endif() enable_testing() -set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/src/cmake/modules/") +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/src/cmake/modules/") message("CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") # Generate GUDHI official version file @@ -22,7 +22,7 @@ if(MSVC) # Turn off some VC++ warnings SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4668 /wd4311 /wd4800 /wd4820 /wd4503 /wd4244 /wd4345 /wd4996 /wd4396 /wd4018") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -std=c++11 -fsanitize=memory -fno-omit-frame-pointer -Wall -Wpedantic -Wsign-compare") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -std=c++11 -Wall -Wpedantic -Wsign-compare") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O1") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") endif() diff --git a/biblio/how_to_cite_cgal.bib b/biblio/how_to_cite_cgal.bib new file mode 100644 index 00000000..7336ee81 --- /dev/null +++ b/biblio/how_to_cite_cgal.bib @@ -0,0 +1,947 @@ +@book{ cgal:eb-15b +, title = "{CGAL} User and Reference Manual" +, author = "{The CGAL Project}" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, year = 2015 +, url = "http://doc.cgal.org/4.7/Manual/packages.html" +} +@incollection{cgal:h-af-15b +, author = "Michael Hemmer" +, title = "Algebraic Foundations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAlgebraicFoundationsSummary" +, year = 2015 +} + +@incollection{cgal:hhkps-nt-15b +, author = "Michael Hemmer and Susan Hert and Sylvain Pion and Stefan Schirra" +, title = "Number Types" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgNumberTypesSummary" +, year = 2015 +} + +@incollection{cgal:h-ma-15b +, author = "Michael Hemmer and Sylvain Pion" +, title = "Modular Arithmetic" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgModularArithmeticSummary" +, year = 2015 +} + +@incollection{cgal:h-p-15b +, author = "Michael Hemmer" +, title = "Polynomial" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolynomialSummary" +, year = 2015 +} + +@incollection{cgal:bht-ak-15b +, author = "Eric Berberich and Michael Hemmer and Michael Kerber and Sylvain Lazard and Luis Pe{\~n}aranda and Monique Teillaud" +, title = "Algebraic Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAlgebraicKerneldSummary" +, year = 2015 +} + +@incollection{cgal:h-msms-15b +, author = "Michael Hoffmann" +, title = "Monotone and Sorted Matrix Search" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMatrixSearchSummary" +, year = 2015 +} + +@incollection{cgal:fgsw-lqps-15b +, author = "Kaspar Fischer and Bernd G{\"a}rtner and Sven Sch{\"o}nherr and Frans Wessendorp" +, title = "Linear and Quadratic Programming Solver" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgQPSolverSummary" +, year = 2015 +} + +@incollection{cgal:bfghhkps-lgk23-15b +, author = "Herv{\'e} Br{\"o}nnimann and Andreas Fabri and Geert-Jan Giezeman and Susan Hert and Michael Hoffmann and Lutz Kettner and Sylvain Pion and Stefan Schirra" +, title = "{2D} and {3D} Linear Geometry Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgKernel23Summary" +, year = 2015 +} + +@incollection{cgal:s-gkd-15b +, author = "Michael Seel" +, title = "{dD} Geometry Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgKernelDSummary" +, year = 2015 +} + +@incollection{cgal:cpt-cgk2-15b +, author = "Pedro Machado Manh{\~a}es de Castro and Sylvain Pion and Monique Teillaud" +, title = "{2D} Circular Geometry Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgCircularKernel2Summary" +, year = 2015 +} + +@incollection{cgal:cclt-sgk3-15b +, author = "Pedro Machado Manh{\~a}es de Castro and Fr{\'e}d{\'e}ric Cazals and S{\'e}bastien Loriot and Monique Teillaud" +, title = "{3D} Spherical Geometry Kernel" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSphericalKernel3Summary" +, year = 2015 +} + +@incollection{cgal:hs-chep2-15b +, author = "Susan Hert and Stefan Schirra" +, title = "{2D} Convex Hulls and Extreme Points" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgConvexHull2Summary" +, year = 2015 +} + +@incollection{cgal:hs-ch3-15b +, author = "Susan Hert and Stefan Schirra" +, title = "{3D} Convex Hulls" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgConvexHull3Summary" +, year = 2015 +} + +@incollection{cgal:hs-chdt3-15b +, author = "Susan Hert and Michael Seel" +, title = "{dD} Convex Hulls and Delaunay Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgConvexHullDSummary" +, year = 2015 +} + +@incollection{cgal:gw-p2-15b +, author = "Geert-Jan Giezeman and Wieger Wesselink" +, title = "{2D} Polygons" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolygon2Summary" +, year = 2015 +} + +@incollection{cgal:fwzh-rbso2-15b +, author = "Efi Fogel and Ophir Setter and Ron Wein and Guy Zucker and Baruch Zukerman and Dan Halperin" +, title = "{2D} Regularized Boolean Set-Operations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBooleanSetOperations2Summary" +, year = 2015 +} + +@incollection{cgal:s-bonp2-15b +, author = "Michael Seel" +, title = "{2D} Boolean Operations on Nef Polygons" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgNef2Summary" +, year = 2015 +} + +@incollection{cgal:hk-bonpes2-15b +, author = "Peter Hachenberger and Lutz Kettner" +, title = "{2D} Boolean Operations on Nef Polygons Embedded on the Sphere" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgNefS2Summary" +, year = 2015 +} + +@incollection{cgal:h-pp2-15b +, author = "Susan Hert" +, title = "{2D} Polygon Partitioning" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolygonPartitioning2Summary" +, year = 2015 +} + +@incollection{cgal:c-sspo2-15b +, author = "Fernando Cacciola" +, title = "{2D} Straight Skeleton and Polygon Offsetting" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgStraightSkeleton2Summary" +, year = 2015 +} + +@incollection{cgal:w-rms2-15b +, author = "Ron Wein and Alon Baram and Eyal Flato and Efi Fogel and Michael Hemmer and Sebastian Morr" +, title = "{2D} Minkowski Sums" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMinkowskiSum2Summary" +, year = 2015 +} + +@incollection{cgal:f-ps2-15b +, author = "Andreas Fabri" +, title = "{2D} Polyline Simplification" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolylineSimplification2Summary" +, year = 2015 +} + +@incollection{hhb-visibility-2-15b +, author = "Michael Hemmer and Kan Huang and Francisc Bungiu and Ning Xu" +, title = "{2D} Visibility Computation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgVisibility_2Summary" +, year = 2015 +} + +@incollection{cgal:k-ps-15b +, author = "Lutz Kettner" +, title = "{3D} Polyhedral Surface" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolyhedronSummary" +, year = 2015 +} + +@incollection{cgal:k-hds-15b +, author = "Lutz Kettner" +, title = "Halfedge Data Structures" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgHDSSummary" +, year = 2015 +} + +@incollection{cgal:bsmf-sm-15b +, author = "Mario Botsch and Daniel Sieger and Philipp Moeller and Andreas Fabri" +, title = "Surface Mesh" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceMeshSummary" +, year = 2015 +} + +@incollection{cgal:d-cm-15b +, author = "Guillaume Damiand" +, title = "Combinatorial Maps" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgCombinatorialMapsSummary" +, year = 2015 +} + +@incollection{cgal:d-lcc-12-15b +, author = "Guillaume Damiand" +, title = "Linear Cell Complex" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgLinearCellComplexSummary" +, year = 2015 +} + +@incollection{cgal:hk-bonp3-15b +, author = "Peter Hachenberger and Lutz Kettner" +, title = "{3D} Boolean Operations on Nef Polyhedra" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgNef3Summary" +, year = 2015 +} + +@incollection{cgal:h-emspe-15b +, author = "Peter Hachenberger" +, title = "Convex Decomposition of Polyhedra" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgConvexDecomposition3Summary" +, year = 2015 +} + +@incollection{cgal:h-msp3-15b +, author = "Peter Hachenberger" +, title = "{3D} Minkowski Sum of Polyhedra" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMinkowskiSum3Summary" +, year = 2015 +} + +@incollection{cgal:wfzh-a2-15b +, author = "Ron Wein and Eric Berberich and Efi Fogel and Dan Halperin and Michael Hemmer and Oren Salzman and Baruch Zukerman" +, title = "{2D} Arrangements" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgArrangement2Summary" +, year = 2015 +} + +@incollection{cgal:wfz-ic2-15b +, author = "Baruch Zukerman and Ron Wein and Efi Fogel" +, title = "{2D} Intersection of Curves" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgIntersectionOfCurves2Summary" +, year = 2015 +} + +@incollection{cgal:p-sr2-15b +, author = "Eli Packer" +, title = "{2D} Snap Rounding" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSnapRounding2Summary" +, year = 2015 +} + +@incollection{cgal:w-e2-15b +, author = "Ron Wein" +, title = "{2D} Envelopes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgEnvelope2Summary" +, year = 2015 +} + +@incollection{cgal:mwz-e3-15b +, author = "Dan Halperin and Michal Meyerovitch and Ron Wein and Baruch Zukerman" +, title = "{3D} Envelopes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgEnvelope3Summary" +, year = 2015 +} + +@incollection{cgal:y-t2-15b +, author = "Mariette Yvinec" +, title = "{2D} Triangulation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTriangulation2Summary" +, year = 2015 +} + +@incollection{cgal:py-tds2-15b +, author = "Sylvain Pion and Mariette Yvinec" +, title = "{2D} Triangulation Data Structure" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTDS2Summary" +, year = 2015 +} + +@incollection{cgal:k-pt2-13-15b +, author = "Nico Kruithof" +, title = "{2D} Periodic Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPeriodic2Triangulation2Summary" +, year = 2015 +} + +@incollection{cgal:pt-t3-15b +, author = "Cl{\'e}ment Jamin and Sylvain Pion and Monique Teillaud" +, title = "{3D} Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTriangulation3Summary" +, year = 2015 +} + +@incollection{cgal:pt-tds3-15b +, author = "Cl{\'e}ment Jamin and Sylvain Pion and Monique Teillaud" +, title = "{3D} Triangulation Data Structure" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTDS3Summary" +, year = 2015 +} + +@incollection{cgal:ct-pt3-15b +, author = "Manuel Caroli and Monique Teillaud" +, title = "{3D} Periodic Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPeriodic3Triangulation3Summary" +, year = 2015 +} + +@incollection{cgal:hdj-t-15b +, author = "Samuel Hornus and Olivier Devillers and Cl{\'e}ment Jamin" +, title = "{dD} Triangulations" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgTriangulationsSummary" +, year = 2015 +} + +@incollection{cgal:d-as2-15b +, author = "Tran Kai Frank Da" +, title = "{2D} Alpha Shapes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAlphaShape2Summary" +, year = 2015 +} + +@incollection{cgal:dy-as3-15b +, author = "Tran Kai Frank Da and S{\'e}bastien Loriot and Mariette Yvinec" +, title = "{3D} Alpha Shapes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAlphaShapes3Summary" +, year = 2015 +} + +@incollection{cgal:k-sdg2-15b +, author = "Menelaos Karavelas" +, title = "{2D} Segment Delaunay Graphs" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSegmentDelaunayGraph2Summary" +, year = 2015 +} + +@incollection{cgal:cdp-sdglinf2-15b +, author = "Panagiotis Cheilaris and Sandeep Kumar Dey and Evanthia Papadopoulou" +, title = "L Infinity Segment Delaunay Graphs" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSDGLinfSummary" +, year = 2015 +} + +@incollection{cgal:ky-ag2-15b +, author = "Menelaos Karavelas and Mariette Yvinec" +, title = "{2D} Apollonius Graphs (Delaunay Graphs of Disks)" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgApolloniusGraph2Summary" +, year = 2015 +} + +@incollection{cgal:k-vda2-15b +, author = "Menelaos Karavelas" +, title = "{2D} Voronoi Diagram Adaptor" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgVoronoiDiagramAdaptor2Summary" +, year = 2015 +} + +@incollection{cgal:r-ctm2-15b +, author = "Laurent Rineau" +, title = "{2D} Conforming Triangulations and Meshes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMesh2Summary" +, year = 2015 +} + +@incollection{cgal:ry-smg-15b +, author = "Laurent Rineau and Mariette Yvinec" +, title = "{3D} Surface Mesh Generation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceMesher3Summary" +, year = 2015 +} + +@incollection{cgal:asg-srps-15b +, author = "Pierre Alliez and Laurent Saboret and Ga{\"e}l Guennebaud" +, title = "Surface Reconstruction from Point Sets" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceReconstructionFromPointSetsSummary" +, year = 2015 +} + +@incollection{cgal:ssr3-15b +, author = "Thijs van Lankveld" +, title = "Scale-Space Surface Reconstruction" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgScaleSpaceReconstruction3Summary" +, year = 2015 +} + +@incollection{cgal:dc-afsr-15b +, author = "Tran Kai Frank Da and David Cohen-Steiner" +, title = "Advancing Front Surface Reconstruction" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAdvancingFrontSurfaceReconstructionSummary" +, year = 2015 +} + +@incollection{cgal:k-ssm3-15b +, author = "Nico Kruithof" +, title = "{3D} Skin Surface Meshing" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSkinSurface3Summary" +, year = 2015 +} + +@incollection{cgal:rty-m3-15b +, author = "Pierre Alliez and Cl{\'e}ment Jamin and Laurent Rineau and St{\'e}phane Tayeb and Jane Tournois and Mariette Yvinec" +, title = "{3D} Mesh Generation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMesh_3Summary" +, year = 2015 +} + +@incollection{cgal:lty-pmp-15b +, author = "S{\'e}bastien Loriot and Jane Tournois and Ilker O. Yaz" +, title = "Polygon Mesh Processing" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPolygonMeshProcessingSummary" +, year = 2015 +} + +@incollection{cgal:s-ssm2-15b +, author = "Le-Jeng Andy Shiue" +, title = "{3D} Surface Subdivision Methods" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceSubdivisionMethods3Summary" +, year = 2015 +} + +@incollection{cgal:y-smsimpl-15b +, author = "Ilker O. Yaz and S{\'e}bastien Loriot" +, title = "Triangulated Surface Mesh Segmentation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceSegmentationSummary" +, year = 2015 +} + +@incollection{cgal:c-tsms-12-15b +, author = "Fernando Cacciola" +, title = "Triangulated Surface Mesh Simplification" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceMeshSimplificationSummary" +, year = 2015 +} + +@incollection{cgal:lsxy-tsmd-15b +, author = "S{\'e}bastien Loriot and Olga Sorkine-Hornung and Yin Xu and Ilker O. Yaz" +, title = "Triangulated Surface Mesh Deformation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceModelingSummary" +, year = 2015 +} + +@incollection{cgal:sal-pptsm2-15b +, author = "Laurent Saboret and Pierre Alliez and Bruno L{\'e}vy" +, title = "Planar Parameterization of Triangulated Surface Meshes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceParameterizationSummary" +, year = 2015 +} + +@incollection{cgal:klcdv-tsmsp-15b +, author = "Stephen Kiazyk and S{\'e}bastien Loriot and {\'E}ric Colin de Verdi{\`e}re" +, title = "Triangulated Surface Mesh Shortest Paths" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSurfaceMeshShortestPathSummary" +, year = 2015 +} + +@incollection{cgal:glt-tsms-15b +, author = "Xiang Gao and S{\'e}bastien Loriot and Andrea Tagliasacchi" +, title = "Triangulated Surface Mesh Skeletonization" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgMeanCurvatureSkeleton3Summary" +, year = 2015 +} + +@incollection{cgal:cp-arutsm-15b +, author = "Marc Pouget and Fr{\'e}d{\'e}ric Cazals" +, title = "Approximation of Ridges and Umbilics on Triangulated Surface Meshes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgRidges_3Summary" +, year = 2015 +} + +@incollection{cgal:pc-eldp-15b +, author = "Marc Pouget and Fr{\'e}d{\'e}ric Cazals" +, title = "Estimation of Local Differential Properties of Point-Sampled Surfaces" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgJet_fitting_3Summary" +, year = 2015 +} + +@incollection{cgal:ass-psp-15b +, author = "Pierre Alliez and Cl{\'e}ment Jamin and Quentin M{\'e}rigot and Jocelyn Meyron and Laurent Saboret and Nader Salman and Shihao Wu" +, title = "Point Set Processing" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPointSetProcessingSummary" +, year = 2015 +} + +@incollection{cgal:ovja-pssd-15b +, author = "Sven Oesau and Yannick Verdie and Cl{\'e}ment Jamin and Pierre Alliez" +, title = "Point Set Shape Detection" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPointSetShapeDetection3Summary" +, year = 2015 +} + +@incollection{cgal:m-ps-15b +, author = "Abdelkrim Mebarki" +, title = "{2D} Placement of Streamlines" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPlacementOfStreamlines2Summary" +, year = 2015 +} + +@incollection{cgal:b-ss2-15b +, author = "Matthias B{\"a}sken" +, title = "{2D} Range and Neighbor Search" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPointSet2Summary" +, year = 2015 +} + +@incollection{cgal:f-isl-15b +, author = "Andreas Fabri" +, title = "Interval Skip List" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgIntervalSkipListSummary" +, year = 2015 +} + +@incollection{cgal:tf-ssd-15b +, author = "Hans Tangelder and Andreas Fabri" +, title = "{dD} Spatial Searching" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSpatialSearchingDSummary" +, year = 2015 +} + +@incollection{cgal:n-rstd-15b +, author = "Gabriele Neyer" +, title = "{dD} Range and Segment Trees" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgRangeSegmentTreesDSummary" +, year = 2015 +} + +@incollection{cgal:kmz-isiobd-15b +, author = "Lutz Kettner and Andreas Meyer and Afra Zomorodian" +, title = "Intersecting Sequences of {dD} Iso-oriented Boxes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBoxIntersectionDSummary" +, year = 2015 +} + +@incollection{cgal:atw-aabb-15b +, author = "Pierre Alliez and St{\'e}phane Tayeb and Camille Wormser" +, title = "{3D} Fast Intersection and Distance Computation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgAABB_treeSummary" +, year = 2015 +} + +@incollection{cgal:dd-ss-15b +, author = "Christophe Delage and Olivier Devillers" +, title = "Spatial Sorting" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgSpatialSortingSummary" +, year = 2015 +} + +@incollection{cgal:fghhs-bv-15b +, author = "Kaspar Fischer and Bernd G{\"a}rtner and Thomas Herrmann and Michael Hoffmann and Sven Sch{\"o}nherr" +, title = "Bounding Volumes" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBoundingVolumesSummary" +, year = 2015 +} + +@incollection{cgal:hp-ia-15b +, author = "Michael Hoffmann and Eli Packer" +, title = "Inscribed Areas" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgInscribedAreasSummary" +, year = 2015 +} + +@incollection{cgal:fghhs-od-15b +, author = "Kaspar Fischer and Bernd G{\"a}rtner and Thomas Herrmann and Michael Hoffmann and Sven Sch{\"o}nherr" +, title = "Optimal Distances" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgOptimalDistancesSummary" +, year = 2015 +} + +@incollection{cgal:ap-pcad-15b +, author = "Pierre Alliez and Sylvain Pion and Ankit Gupta" +, title = "Principal Component Analysis" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgPrincipalComponentAnalysisDSummary" +, year = 2015 +} + +@incollection{cgal:f-i-15b +, author = "Julia Fl{\"o}totto" +, title = "{2D} and Surface Function Interpolation" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgInterpolation2Summary" +, year = 2015 +} + +@incollection{cgal:abha-gbc-15b +, author = "Dmitry Anisimov and David Bommes and Kai Hormann and Pierre Alliez" +, title = "{2D} Generalized Barycentric Coordinates" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBarycentric_coordinates_2Summary" +, year = 2015 +} + +@incollection{cgal:r-kds-15b +, author = "Daniel Russel" +, title = "Kinetic Data Structures" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgKdsSummary" +, year = 2015 +} + +@incollection{cgal:r-kdsf-15b +, author = "Daniel Russel" +, title = "Kinetic Framework" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgKdsFrameworkSummary" +, year = 2015 +} + +@incollection{cgal:hkpw-se-15b +, author = "Michael Hoffmann and Lutz Kettner and Sylvain Pion and Ron Wein" +, title = "STL Extensions for {CGAL}" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgStlExtensionSummary" +, year = 2015 +} + +@incollection{cgal:cfw-cbgl-15b +, author = "Andreas Fabri and Fernando Cacciola and Philipp Moeller and Ron Wein" +, title = "{CGAL} and the {Boost} Graph Library" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgBGLSummary" +, year = 2015 +} + +@incollection{cgal:fs-cbpm-15b +, author = "Andreas Fabri and Laurent Saboret" +, title = "{CGAL} and {Boost} Property Maps" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgProperty_mapSummary" +, year = 2015 +} + +@incollection{cgal:dksy-hc-15b +, author = "Olivier Devillers and Lutz Kettner and Sylvain Pion and Michael Seel and Mariette Yvinec" +, title = "Handles and Circulators" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgHandlesAndCirculatorsSummary" +, year = 2015 +} + +@incollection{cgal:dhhk-gog-15b +, author = "Pedro M. M. de Castro and Olivier Devillers and Susan Hert and Michael Hoffmann and Lutz Kettner and Sven Sch{\"o}nherr and Alexandru Tifrea" +, title = "Geometric Object Generators" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgGeneratorsSummary" +, year = 2015 +} + +@incollection{cgal:kps-pthum-15b +, author = "Lutz Kettner and Sylvain Pion and Michael Seel" +, title = "Profiling tools, Hash Map, Union-find, Modifiers" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgProfilingToolsSummary" +, year = 2015 +} + +@incollection{cgal:fgk-ios-12-15b +, author = "Andreas Fabri and Geert-Jan Giezeman and Lutz Kettner" +, title = "IO Streams" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgIOstreamsSummary" +, year = 2015 +} + +@incollection{cgal:fp-gv-15b +, author = "Andreas Fabri and Sylvain Pion" +, title = "Geomview" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgGeomviewSummary" +, year = 2015 +} + +@incollection{cgal:fr-cqgvf-15b +, author = "Andreas Fabri and Laurent Rineau" +, title = "{CGAL} and the {Qt} Graphics View Framework" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgGraphicsViewSummary" +, year = 2015 +} + +@incollection{cgal:lp-gi-15b +, author = "Olivier Devillers and S{\'e}bastien Loriot and Sylvain Pion" +, title = "{CGAL} Ipelets" +, publisher = "{CGAL Editorial Board}" +, edition = "{4.7}" +, booktitle = "{CGAL} User and Reference Manual" +, url = "http://doc.cgal.org/4.7/Manual/packages.html#PkgCGALIpeletsSummary" +, year = 2015 +} diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index d7c13da0..fa24e1b1 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -18,8 +18,6 @@ if(CGAL_FOUND) add_executable ( AlphaComplexUT Alpha_complex_unit_test.cpp ) target_link_libraries(AlphaComplexUT ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - add_executable ( cerr cerr.cpp ) - # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) diff --git a/src/GudhUI/alpha_complex_persistence.cpp b/src/GudhUI/alpha_complex_persistence.cpp deleted file mode 100644 index 4f85459a..00000000 --- a/src/GudhUI/alpha_complex_persistence.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - - -#include - -// to construct a Delaunay_triangulation from a OFF file -#include -#include -#include - -#include "utils/Bar_code_persistence.h" - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off " << // alpha_square_max_value[double] " << - "coeff_field_characteristic[integer > 0] min_persistence[double >= -1.0]" << std::endl; - std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0 2 0.02" << std::endl; - exit(-1); // ----- >> -} - -int main(int argc, char **argv) { - if (argc != 4) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - QApplication qtapp(argc, argv); - - std::string off_file_name(argv[1]); - // double alpha_square_max_value = atof(argv[2]); - double alpha_square_max_value = 1e20; - int coeff_field_characteristic = atoi(argv[2]); // argv[3] - double min_persistence = atof(argv[3]); // argv[4] - - // ---------------------------------------------------------------------------- - // Init of an alpha complex from an OFF file - // ---------------------------------------------------------------------------- - typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); - - // ---------------------------------------------------------------------------- - // Display information about the alpha complex - // ---------------------------------------------------------------------------- - std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << - " - " << alpha_complex_from_file.num_simplices() << " simplices - " << - alpha_complex_from_file.num_vertices() << " vertices." << std::endl; - - // Sort the simplices in the order of the filtration - alpha_complex_from_file.initialize_filtration(); - - std::cout << "Simplex_tree dim: " << alpha_complex_from_file.dimension() << std::endl; - // Compute the persistence diagram of the complex - Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::alphacomplex::Alpha_complex, - Gudhi::persistent_cohomology::Field_Zp > pcoh(alpha_complex_from_file); - - std::cout << "coeff_field_characteristic " << coeff_field_characteristic << - " - min_persistence " << min_persistence << std::endl; - - // initializes the coefficient field for homology - pcoh.init_coefficients(coeff_field_characteristic); - - pcoh.compute_persistent_cohomology(min_persistence); - - pcoh.output_diagram(); - - std::vector> persistence_vector; - pcoh.get_persistence(persistence_vector); - - Bar_code_persistence bc_persistence; - - for (auto persistence : persistence_vector) { - bc_persistence.insert(persistence.first, persistence.second); - } - - bc_persistence.show(); - - return qtapp.exec(); -} diff --git a/src/GudhUI/utils/Bar_code_persistence.h b/src/GudhUI/utils/Bar_code_persistence.h index a1a46ea8..a4cd8156 100644 --- a/src/GudhUI/utils/Bar_code_persistence.h +++ b/src/GudhUI/utils/Bar_code_persistence.h @@ -39,7 +39,7 @@ class Bar_code_persistence { max_death = death; } - void show() { + void show(const std::string& window_title) { // Create a view, put a scene in it QGraphicsView * view = new QGraphicsView(); QGraphicsScene * scene = new QGraphicsScene(); @@ -78,6 +78,7 @@ class Bar_code_persistence { QGraphicsTextItem* dimText = scene->addText(scale_value, QFont("Helvetica", 8)); dimText->setPos(scale - (3.0 * scale_value.size()), height + 9.0 * (modulo % 2)); } + view->setWindowTitle(window_title.c_str()); // Show the view view->show(); } diff --git a/src/GudhUI/utils/Persistence_compute.h b/src/GudhUI/utils/Persistence_compute.h index 0b9961d3..1f04cc6b 100644 --- a/src/GudhUI/utils/Persistence_compute.h +++ b/src/GudhUI/utils/Persistence_compute.h @@ -46,10 +46,6 @@ struct Persistence_params { * Show persistence into output stream */ template class Persistence_compute { - private: - SkBlComplex& complex_; - std::ostream& stream_; - public: typedef typename SkBlComplex::Vertex_handle Vertex_handle; typedef typename SkBlComplex::Edge_handle Edge_handle; @@ -61,9 +57,7 @@ template class Persistence_compute { * double threshold * int p for coefficient Z_p */ - Persistence_compute(SkBlComplex& complex, std::ostream& stream, const Persistence_params& params) : - // double threshold = 0.5,unsigned dim_max = 8): - complex_(complex), stream_(stream) { + Persistence_compute(SkBlComplex& complex, std::ostream& stream, const Persistence_params& params) { // for now everything is copied, todo boost adapt iterators to points of SkBlComplex instead of copying to an // initial vector typedef std::vector Point_t; @@ -87,10 +81,11 @@ template class Persistence_compute { pcoh.init_coefficients(params.p); // put params.min_pers pcoh.compute_persistent_cohomology(params.min_pers); - stream_ << "persistence: \n"; - stream_ << "p dimension birth death: \n"; + stream << "persistence: \n"; + stream << "p dimension birth death: \n"; - pcoh.output_diagram(stream_); + pcoh.output_diagram(stream); + } }; diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index eb4ee3e3..9e96adc0 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -22,63 +22,61 @@ add_executable(persistence_from_file persistence_from_file.cpp) target_link_libraries(persistence_from_file ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) add_test(persistence_from_file_3_2_0 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 2 -m 0) add_test(persistence_from_file_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) - -if(GMPXX_FOUND AND GMP_FOUND) - message("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}") - message("GMP_LIBRARIES = ${GMP_LIBRARIES}") - - add_executable(rips_multifield_persistence rips_multifield_persistence.cpp ) - target_link_libraries(rips_multifield_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) - add_test(rips_multifield_persistence_2_71 ${CMAKE_CURRENT_BINARY_DIR}/rips_multifield_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 71 -m 100) - - add_executable ( performance_rips_persistence performance_rips_persistence.cpp ) - target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) - - if(CGAL_FOUND) - add_executable(alpha_shapes_persistence alpha_shapes_persistence.cpp) - target_link_libraries(alpha_shapes_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) - add_test(alpha_shapes_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) - #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) - - - - if (NOT CGAL_VERSION VERSION_LESS 4.7.0) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - - include( ${CGAL_USE_FILE} ) - # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. - # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 - # A workaround is to add "-std=c++11" again. - # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html - # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html - # but it implies to use cmake version 3.1 at least. - if(NOT MSVC) - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) - if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +if(GMPXX_FOUND AND GMP_FOUND) + message("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}") + message("GMP_LIBRARIES = ${GMP_LIBRARIES}") + + add_executable(rips_multifield_persistence rips_multifield_persistence.cpp ) + target_link_libraries(rips_multifield_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) + add_test(rips_multifield_persistence_2_71 ${CMAKE_CURRENT_BINARY_DIR}/rips_multifield_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 71 -m 100) + + add_executable ( performance_rips_persistence performance_rips_persistence.cpp ) + target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) + + if(CGAL_FOUND) + add_executable(alpha_shapes_persistence alpha_shapes_persistence.cpp) + target_link_libraries(alpha_shapes_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) + add_test(alpha_shapes_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) + #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) + + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) + message(STATUS "CGAL version: ${CGAL_VERSION}.") + + include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() endif() - endif() - # - End of workaround + # - End of workaround - find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) - message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") - include( ${EIGEN3_USE_FILE} ) + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") + include( ${EIGEN3_USE_FILE} ) - add_executable (alphacomplexpersistence alpha_complex_persistence.cpp) - target_link_libraries(alphacomplexpersistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_executable (alpha_complex_persistence alpha_complex_persistence.cpp) + target_link_libraries(alpha_complex_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) + else() + message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") + endif() else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") - endif() + message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") + endif () else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") - endif () - - - - endif() + # message(WARNING "CGAL not found.") + endif() +else() + # message(WARNING "GMP not found.") endif() diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp index fbadf673..0dabdeac 100644 --- a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -1,34 +1,35 @@ #include #include +#include + // to construct a Delaunay_triangulation from a OFF file #include #include #include -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value[double] " << - "coeff_field_characteristic[integer > 0] min_persistence[double >= -1.0]" << std::endl; - std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0 2 0.02" << std::endl; - exit(-1); // ----- >> -} +void program_options(int argc, char * argv[] + , std::string & off_file_points + , std::string & output_file_diag + , Filtration_value & alpha_square_max_value + , int & coeff_field_characteristic + , Filtration_value & min_persistence); int main(int argc, char **argv) { - if (argc != 5) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } + std::string off_file_points; + std::string output_file_diag; + Filtration_value alpha_square_max_value; + int coeff_field_characteristic; + Filtration_value min_persistence; + + program_options(argc, argv, off_file_points, output_file_diag, alpha_square_max_value, coeff_field_characteristic, min_persistence); - std::string off_file_name(argv[1]); - double alpha_square_max_value = atof(argv[2]); - int coeff_field_characteristic = atoi(argv[3]); - double min_persistence = atof(argv[4]); // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); + Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_points, alpha_square_max_value); // ---------------------------------------------------------------------------- // Display information about the alpha complex @@ -49,7 +50,66 @@ int main(int argc, char **argv) { pcoh.compute_persistent_cohomology(min_persistence); - pcoh.output_diagram(); + // Output the diagram in filediag + if (output_file_diag.empty()) { + pcoh.output_diagram(); + } else { + std::cout << "Result in file: " << output_file_diag << std::endl; + std::ofstream out(output_file_diag); + pcoh.output_diagram(out); + out.close(); + } return 0; } + +void program_options(int argc, char * argv[] + , std::string & off_file_points + , std::string & output_file_diag + , Filtration_value & alpha_square_max_value + , int & coeff_field_characteristic + , Filtration_value & min_persistence) { + namespace po = boost::program_options; + po::options_description hidden("Hidden options"); + hidden.add_options() + ("input-file", po::value(&off_file_points), + "Name of file containing a point set. Format is one point per line: X1 ... Xd "); + + po::options_description visible("Allowed options", 100); + visible.add_options() + ("help,h", "produce help message") + ("output-file,o", po::value(&output_file_diag)->default_value(std::string()), + "Name of file in which the persistence diagram is written. Default print in std::cout") + ("max-alpha-square-value,r", po::value(&alpha_square_max_value)->default_value(std::numeric_limits::infinity()), + "Maximal alpha square value for the Alpha complex construction.") + ("field-charac,p", po::value(&coeff_field_characteristic)->default_value(11), + "Characteristic p of the coefficient field Z/pZ for computing homology.") + ("min-persistence,m", po::value(&min_persistence), + "Minimal lifetime of homology feature to be recorded. Default is 0. Enter a negative value to see zero length intervals"); + + po::positional_options_description pos; + pos.add("input-file", 1); + + po::options_description all; + all.add(visible).add(hidden); + + po::variables_map vm; + po::store(po::command_line_parser(argc, argv). + options(all).positional(pos).run(), vm); + po::notify(vm); + + if (vm.count("help") || !vm.count("input-file")) { + std::cout << std::endl; + std::cout << "Compute the persistent homology with coefficient field Z/pZ \n"; + std::cout << "of an Alpha complex defined on a set of input points.\n \n"; + std::cout << "The output diagram contains one bar per line, written with the convention: \n"; + std::cout << " p dim b d \n"; + std::cout << "where dim is the dimension of the homological feature,\n"; + std::cout << "b and d are respectively the birth and death of the feature and \n"; + std::cout << "p is the characteristic of the field Z/pZ used for homology coefficients." << std::endl << std::endl; + + std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl << std::endl; + std::cout << visible << std::endl; + std::abort(); + } +} diff --git a/src/Persistent_cohomology/example/rips_persistence.cpp b/src/Persistent_cohomology/example/rips_persistence.cpp index 9b1ef42f..fa0449a8 100644 --- a/src/Persistent_cohomology/example/rips_persistence.cpp +++ b/src/Persistent_cohomology/example/rips_persistence.cpp @@ -30,6 +30,7 @@ #include #include +#include // infinity using namespace Gudhi; using namespace Gudhi::persistent_cohomology; @@ -114,7 +115,7 @@ void program_options(int argc, char * argv[] ("help,h", "produce help message") ("output-file,o", po::value(&filediag)->default_value(std::string()), "Name of file in which the persistence diagram is written. Default print in std::cout") - ("max-edge-length,r", po::value(&threshold)->default_value(0), + ("max-edge-length,r", po::value(&threshold)->default_value(std::numeric_limits::infinity()), "Maximal length of an edge for the Rips complex construction.") ("cpx-dimension,d", po::value(&dim_max)->default_value(1), "Maximal dimension of the Rips complex we want to compute.") diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 4b04e75a..d4f9aeae 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1160,43 +1160,28 @@ std::cout << "prune_above_filtration - filtration=" << filtration << std::endl; threshold_ = filtration; // Initialize filtration_vect_ if required if (filtration_vect_.empty()) { -std::cout << "prune_above_filtration - initialize_filtration" << std::endl; initialize_filtration(); } - -std::cout << "prune_above_filtration - after initialize_filtration "; -for(auto sh : filtration_vect_) { -for (auto vertex : simplex_vertex_range(sh)) { -std::cout << (int) vertex << ", "; -} -std::cout << " - filtration=" << sh->second.filtration() << " - " << &(sh->second) << std::endl; -} - + std::vector> simplex_list_to_removed; // Loop in reverse mode until threshold is reached - auto f_simplex = filtration_vect_.rbegin(); - for (; (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > threshold_); f_simplex++) { - -std::cout << "prune_above_filtration - remove "; -for (auto vertex : simplex_vertex_range(*f_simplex)) { -std::cout << (int) vertex << ", "; -} -std::cout << " - " << &((*f_simplex)->second) << std::endl; - - remove_maximal_simplex(*f_simplex); + // Do not erase while looping, because removing is shifting data in a flat_map + for (auto f_simplex = filtration_vect_.rbegin(); + (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > threshold_); + f_simplex++) { + std::vector simplex_to_remove; + for (auto vertex : simplex_vertex_range(*f_simplex)) + simplex_to_remove.insert(simplex_to_remove.begin(), vertex); + simplex_list_to_removed.push_back(simplex_to_remove); } -std::cout << "prune_above_filtration - remove STOPPED ON "; -for (auto vertex : simplex_vertex_range(*f_simplex)) { -std::cout << (int) vertex << ", "; -} -std::cout << " - filtration=" << (*f_simplex)->second.filtration() << " - " << &(*f_simplex->second) << std::endl; - if (f_simplex != filtration_vect_.rbegin()) { - // Do not forget to update filtration_vect_ - resize is enough - std::size_t new_size = filtration_vect_.size() - (f_simplex - filtration_vect_.rbegin()); -std::cout << "prune_above_filtration - resize" << new_size << std::endl; - filtration_vect_.resize(new_size); + for (auto simplex_to_remove : simplex_list_to_removed) { + Simplex_handle sh = find_simplex(simplex_to_remove); + if (sh != null_simplex()) + remove_maximal_simplex(sh); } - + // Re-initialize filtration_vect_ if dta were removed, because removing is shifting data in a flat_map + if (simplex_list_to_removed.size() > 0) + initialize_filtration(); } } } @@ -1205,6 +1190,7 @@ std::cout << "prune_above_filtration - resize" << new_size << std::endl; * @param[in] sh Simplex handle on the maximal simplex to remove. * \pre Please check the simplex has no coface before removing it. * \warning In debug mode, the exception std::invalid_argument is thrown if sh has children. + * \warning Be aware that removing is shifting data in a flat_map (initialize_filtration to be done). */ void remove_maximal_simplex(Simplex_handle sh) { // Guarantee the simplex has no children @@ -1213,49 +1199,18 @@ std::cout << "prune_above_filtration - resize" << new_size << std::endl; // Simplex is a leaf, it means the child is the Siblings owning the leaf Siblings* child = sh->second.children(); + if ((child->size() > 1) || (child == root())) { // Not alone, just remove it from members // Special case when child is the root of the simplex tree, just remove it from members -std::cout << "remove_maximal_simplex - members removal" << std::endl; child->erase(sh->first); } else { // Sibling is emptied : must be deleted, and its parent must point on his own Sibling -std::cout << "remove_maximal_simplex - members is empty" << std::endl; child->oncles()->members().at(child->parent()).assign_children(child->oncles()); delete child; } } -/***************************************************************************************************************/ - public: - /** \brief Prints the simplex_tree hierarchically. - * Since it prints the vertices recursively, one can watch its tree shape. - */ - void print_tree() { - for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { - std::cout << sh->first << " "; - if (has_children(sh)) { - std::cout << "("; - rec_print(sh->second.children()); - std::cout << ")"; - } - std::cout << std::endl; - } - } - - /** \brief Recursively prints the simplex_tree, using depth first search. */ - private: - void rec_print(Siblings * sib) { - for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { - std::cout << " " << sh->first << " "; - if (has_children(sh)) { - std::cout << "("; - rec_print(sh->second.children()); - std::cout << ")"; - } - } - } -/*****************************************************************************************************************/ private: Vertex_handle null_vertex_; /** \brief Upper bound on the filtration values of the simplices.*/ diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index f6bd5411..0d73d347 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -351,7 +351,7 @@ BOOST_AUTO_TEST_CASE(simplex_tree_insertion) { // Display the Simplex_tree - Can not be done in the middle of 2 inserts std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; - std::cout << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; for (auto f_simplex : st.filtration_simplex_range()) { std::cout << " " << "[" << st.filtration(f_simplex) << "] "; for (auto vertex : st.simplex_vertex_range(f_simplex)) { @@ -549,7 +549,7 @@ BOOST_AUTO_TEST_CASE(NSimplexAndSubfaces_tree_insertion) { // Display the Simplex_tree - Can not be done in the middle of 2 inserts std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; - std::cout << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; for (auto f_simplex : st.filtration_simplex_range()) { std::cout << " " << "[" << st.filtration(f_simplex) << "] "; for (auto vertex : st.simplex_vertex_range(f_simplex)) { @@ -805,7 +805,7 @@ struct MyOptions : Simplex_tree_options_full_featured { }; typedef Simplex_tree miniST; -/*BOOST_AUTO_TEST_CASE(remove_maximal_simplex) { +BOOST_AUTO_TEST_CASE(remove_maximal_simplex) { std::cout << "********************************************************************" << std::endl; std::cout << "REMOVE MAXIMAL SIMPLEX" << std::endl; @@ -887,7 +887,7 @@ typedef Simplex_tree miniST; st.remove_maximal_simplex(st.find({7})); BOOST_CHECK(st == st_wo_seven); -}*/ +} BOOST_AUTO_TEST_CASE(prune_above_filtration) { std::cout << "********************************************************************" << std::endl; @@ -939,10 +939,10 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { st.prune_above_filtration(5.0); BOOST_CHECK(st == st_complete); - // Display the Simplex_tree - Can not be done in the middle of 2 inserts + // Display the Simplex_tree std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; - std::cout << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; for (auto f_simplex : st.filtration_simplex_range()) { std::cout << " " << "[" << st.filtration(f_simplex) << "] "; for (auto vertex : st.simplex_vertex_range(f_simplex)) { @@ -955,35 +955,45 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { // Set the st_pruned filtration for operator== st_pruned.set_filtration(2.5); st.prune_above_filtration(2.5); - /*BOOST_CHECK(st == st_pruned); + BOOST_CHECK(st == st_pruned); + + // Display the Simplex_tree + std::cout << "The complex pruned at 2.5 contains " << st.num_simplices() << " simplices" << std::endl; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + std::cout << " " << "[" << st.filtration(f_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; + } st_pruned.set_filtration(2.0); st.prune_above_filtration(2.0); BOOST_CHECK(st == st_pruned); -*/ -/* std::cout << "The complex contains " << st.num_simplices() << " simplices --------------------------" << std::endl; - std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; - st.print_tree(); - std::cout << "The pruned complex contains " << st_pruned.num_simplices() << " simplices --------------------------" << std::endl; - std::cout << " - dimension " << st_pruned.dimension() << " - filtration " << st_pruned.filtration() << std::endl; - st_pruned.print_tree(); - typeST st_empty; // FIXME st_empty.set_dimension(3); st.prune_above_filtration(0.0); - */ - /*BOOST_CHECK(st == st_empty); + + // Display the Simplex_tree + std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices" << std::endl; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + std::cout << " " << "[" << st.filtration(f_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << (int) vertex << " "; + } + std::cout << std::endl; + } + + BOOST_CHECK(st == st_empty); // Test case to the limit st.prune_above_filtration(-1.0); st_empty.set_filtration(-1.0); BOOST_CHECK(st == st_empty); -*/ } - -/*BOOST_AUTO_TEST_CASE(sanitizer) { - int a[2] = {1, 0}; - int b=a[2]; -}*/ diff --git a/src/common/include/gudhi/distance_functions.h b/src/common/include/gudhi/distance_functions.h index e5c79ded..cd518581 100644 --- a/src/common/include/gudhi/distance_functions.h +++ b/src/common/include/gudhi/distance_functions.h @@ -23,6 +23,8 @@ #ifndef DISTANCE_FUNCTIONS_H_ #define DISTANCE_FUNCTIONS_H_ +#include // for std::sqrt + /* Compute the Euclidean distance between two Points given * by a range of coordinates. The points are assumed to have * the same dimension. */ @@ -35,7 +37,7 @@ double euclidean_distance(Point &p1, Point &p2) { double tmp = *it1 - *it2; dist += tmp*tmp; } - return sqrt(dist); + return std::sqrt(dist); } #endif // DISTANCE_FUNCTIONS_H_ diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index e05714c7..da2c2c36 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -58,7 +58,9 @@ inline void read_points(std::string file_name, std::vector< std::vector< double while (iss >> x) { point.push_back(x); } - points.push_back(point); + // Check for empty lines + if (!point.empty()) + points.push_back(point); } in_file.close(); } -- cgit v1.2.3 From 178f37684b9f3bebf95534568b5ef54c15e11c63 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 12 Jan 2016 16:21:20 +0000 Subject: Remove test from gudhUI cmake git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@958 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1f77ce3d6bd85fceba2e0eeeacd559315d9c9d89 --- src/GudhUI/CMakeLists.txt | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index 75adba08..24cb0be1 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -78,40 +78,6 @@ if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND ) target_link_libraries( GudhUI ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} ) target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) -############################################################################### - if (NOT CGAL_VERSION VERSION_LESS 4.7.0) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - - include( ${CGAL_USE_FILE} ) - # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. - # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 - # A workaround is to add "-std=c++11" again. - # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html - # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html - # but it implies to use cmake version 3.1 at least. - if(NOT MSVC) - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) - if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - endif() - endif() - # - End of workaround - - find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) - message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") - include( ${EIGEN3_USE_FILE} ) - - add_executable (acp alpha_complex_persistence.cpp) - target_link_libraries(acp ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${QT_LIBRARIES}) - - else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") - endif() - else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Alpha shapes feature. Version 4.6.0 is required.") - endif () ############################################################################### else() -- cgit v1.2.3 From f443bbd06cac275284f75936d6803105eb99fec6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 15 Jan 2016 13:00:53 +0000 Subject: make_filtration_non_decreasing fix. Make it non decreasing for border and not only for parent. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@972 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: e71f40baa56de53e68b02603b64fb504b1f5d978 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 64 +++++++++++++++++++--- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 67 ++++++++++-------------- 2 files changed, 86 insertions(+), 45 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 3ba838a7..16485c89 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -47,6 +47,7 @@ #include #include // Inf #include +#include // for std::max namespace Gudhi { /** \defgroup simplex_tree Filtered Complexes @@ -128,6 +129,10 @@ class Simplex_tree { /* \brief Set of nodes sharing a same parent in the simplex tree. */ typedef Simplex_tree_siblings Siblings; + /** \brief Element of a flat_map. + * 'value_type' is Map_element. */ + typedef typename std::pair Map_element; + struct Key_simplex_base_real { Key_simplex_base_real() : key_(-1) {} void assign_key(Simplex_key k) { key_ = k; } @@ -221,7 +226,7 @@ class Simplex_tree { * * 'value_type' is Simplex_handle. */ typedef typename Filtration_simplex_range::const_iterator Filtration_simplex_iterator; - + /* @} */ // end name range and iterator types /** \name Range and iterator methods * @{ */ @@ -327,11 +332,10 @@ class Simplex_tree { Simplex_tree(const Simplex_tree& simplex_source) : null_vertex_(simplex_source.null_vertex_), threshold_(simplex_source.threshold_), + root_(nullptr, null_vertex_ , simplex_source.root_.members_), filtration_vect_(), dimension_(simplex_source.dimension_) { auto root_source = simplex_source.root_; - auto memb_source = root_source.members(); - root_ = Siblings(nullptr, null_vertex_, memb_source); rec_copy(&root_, &root_source); } @@ -343,7 +347,7 @@ class Simplex_tree { Siblings * newsib = new Siblings(sib, sh_source->first); newsib->members_.reserve(sh_source->second.children()->members().size()); for (auto & child : sh_source->second.children()->members()) - newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(sib, child.second.filtration())); + newsib->members_.emplace_hint(newsib->members_.end(), child.first, Node(newsib, child.second.filtration())); rec_copy(newsib, sh_source->second.children()); sh->second.assign_children(newsib); } @@ -1127,9 +1131,15 @@ class Simplex_tree { */ bool make_filtration_non_decreasing() { bool modified = false; + + // Find the maximum filtration value in the border + Simplex_handle max_border_value = std::max_element( std::begin(root_.members()), std::end(root_.members()), + [](const Map_element& sh1, const Map_element& sh2) { + return sh1.second.filtration() < sh2.second.filtration(); + }); for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children(), max_border_value->second.filtration()); } } return modified; @@ -1143,6 +1153,12 @@ class Simplex_tree { */ bool rec_make_filtration_non_decreasing(Siblings * sib, Filtration_value upper_filtration) { bool modified = false; + // Find the maximum filtration value in the border + Simplex_handle max_border_value = std::max_element( std::begin(sib->members()), std::end(sib->members()), + [](const Map_element& sh1, const Map_element& sh2) { + return sh1.second.filtration() < sh2.second.filtration(); + }); + for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { if (sh->second.filtration() < upper_filtration) { // Store the filtration modification information @@ -1150,7 +1166,7 @@ class Simplex_tree { sh->second.assign_filtration(upper_filtration); } if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children(), sh->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children(), max_border_value->second.filtration()); } } // Make the modified information to be traced by upper call @@ -1223,6 +1239,42 @@ std::cout << "prune_above_filtration - filtration=" << filtration << std::endl; delete child; } } +/***************************************************************************************************************/ + public: + /** \brief Prints the simplex_tree hierarchically. + * Since it prints the vertices recursively, one can watch its tree shape. + */ + void debug_tree() { + std::cout << "{" << &root_ << "} -------------------------------------------------------------------" << std::endl; + for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { + std::cout << sh->first << " [" << sh->second.filtration() << "] "; + if (has_children(sh)) { + rec_debug_tree(sh->second.children()); + } else { + std::cout << " {- " << sh->second.children() << "} "; + } + std::cout << std::endl; + } + std::cout << "--------------------------------------------------------------------------------------" << std::endl; + } + + + /** \brief Recursively prints the simplex_tree, using depth first search. */ + private: + void rec_debug_tree(Siblings * sib) { + std::cout << " {" << sib << "} ("; + for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { + std::cout << " " << sh->first << " [" << sh->second.filtration() << "] "; + if (has_children(sh)) { + rec_debug_tree(sh->second.children()); + } else { + std::cout << " {- " << sh->second.children() << "} "; + } + } + std::cout << ")"; + } + +/*****************************************************************************************************************/ private: Vertex_handle null_vertex_; diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 1a050a25..25ae5ed3 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -802,13 +802,18 @@ BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) { typedef Simplex_tree<> typeST; typeST st; - st.insert_simplex_and_subfaces({2, 1, 0}, 4.0); - st.insert_simplex_and_subfaces({3, 0}, 3.0); + st.insert_simplex_and_subfaces({2, 1, 0}, 2.0); + st.insert_simplex_and_subfaces({3, 0}, 2.0); st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); - // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 4.0 + + typeST st_bis = st; + // Check default insertion ensures the filtration values are non decreasing + BOOST_CHECK(!st.make_filtration_non_decreasing()); + + // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 2.0 // to 1.0 st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); - + /* Inserted simplex: */ /* 1 6 */ /* o---o */ @@ -817,45 +822,29 @@ BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) { /* 2 0 3\X/4 */ /* o */ /* 5 */ - - // FIXME - st.set_dimension(3); - - // Copy constructor - typeST st_copy = st; - - // Check default insertion ensures the filtration values are non decreasing - BOOST_CHECK(!st.make_filtration_non_decreasing()); - // Check the simplex tree is not modified by the function - BOOST_CHECK(st == st_copy); - - // Make { 0, 1 } decreasing - st.assign_filtration(st.find({0, 1}), 0.5); - // Make { 1, 6, 7 } decreasing - st.assign_filtration(st.find({1, 6, 7}), 0.4); - // Make { 3, 4 } decreasing - st.assign_filtration(st.find({3, 4}), 0.3); - // Make { 4, 5 } decreasing - st.assign_filtration(st.find({4, 5}), 0.1); - - // Check the filtration values were decreasing + BOOST_CHECK(st.make_filtration_non_decreasing()); - // Check the simplex tree has been modified by the function to retrieve the initial simplex tree - BOOST_CHECK(st == st_copy); + + // Check make_filtration_non_decreasing is just not modifying root values + st_bis.insert_simplex_and_subfaces({0, 1, 6, 7}, 2.0); + st_bis.assign_filtration(st_bis.find({0}), 1.0); + st_bis.assign_filtration(st_bis.find({1}), 1.0); + st_bis.assign_filtration(st_bis.find({6}), 1.0); + st_bis.assign_filtration(st_bis.find({7}), 1.0); + + BOOST_CHECK(st == st_bis); - // Change { 0, 3 }, but still non decreasing - st.assign_filtration(st.find({0, 3}), 1.01); - // Change { 0, 1, 6, 7 }, but still non decreasing - st.assign_filtration(st.find({0, 1, 6, 7}), 1.201); - // Change { 1, 2 }, but still non decreasing - st.assign_filtration(st.find({1, 2}), 1.05); - // Change { 4 }, but still non decreasing - st.assign_filtration(st.find({4}), 1.123); + // Check make_filtration_non_decreasing can modify non-root values (leaves and non-leaf) + st.assign_filtration(st.find({0, 1, 6, 7}), 1.99); + st.assign_filtration(st.find({3, 4}), 1.5); + st.assign_filtration(st.find({0, 3}), -1.0); + BOOST_CHECK(st.make_filtration_non_decreasing()); + BOOST_CHECK(st == st_bis); - // Check the filtration values are non decreasing + // Check make_filtration_non_decreasing is not modifying when increasing + st.assign_filtration(st.find({0, 1, 6, 7}), 4.5); + st.assign_filtration(st.find({3, 4, 5}), 15.0); BOOST_CHECK(!st.make_filtration_non_decreasing()); - // Check the simplex tree has been modified from the original - BOOST_CHECK(st != st_copy); } -- cgit v1.2.3 From 73e025369bd50511b67b4f8e290a2c3a533ded88 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 19 Jan 2016 10:28:37 +0000 Subject: make_filtration_non_decreasing fix Ut rewrite git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@974 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3326338b9454923b59d3e42add0f3530c6dbe16f --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 4 +- src/Simplex_tree/include/gudhi/Simplex_tree.h | 37 ++++------ src/Simplex_tree/test/simplex_tree_unit_test.cpp | 88 ++++++++++++++++-------- 3 files changed, 78 insertions(+), 51 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 9f931066..1ab6766c 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -308,7 +308,9 @@ class Alpha_complex : public Simplex_tree<> { // -------------------------------------------------------------------------------------------- // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension - make_filtration_non_decreasing(); + if (make_filtration_non_decreasing()) { + initialize_filtration(); + } // Remove all simplices that have a filtration value greater than max_alpha_square prune_above_filtration(max_alpha_square); // -------------------------------------------------------------------------------------------- diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 16485c89..dbef8517 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -129,10 +129,6 @@ class Simplex_tree { /* \brief Set of nodes sharing a same parent in the simplex tree. */ typedef Simplex_tree_siblings Siblings; - /** \brief Element of a flat_map. - * 'value_type' is Map_element. */ - typedef typename std::pair Map_element; - struct Key_simplex_base_real { Key_simplex_base_real() : key_(-1) {} void assign_key(Simplex_key k) { key_ = k; } @@ -1131,15 +1127,10 @@ class Simplex_tree { */ bool make_filtration_non_decreasing() { bool modified = false; - - // Find the maximum filtration value in the border - Simplex_handle max_border_value = std::max_element( std::begin(root_.members()), std::end(root_.members()), - [](const Map_element& sh1, const Map_element& sh2) { - return sh1.second.filtration() < sh2.second.filtration(); - }); - for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { + // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree + for (auto sh = (root_.members().end() - 1); sh >= root_.members().begin(); --sh) { if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children(), max_border_value->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children()); } } return modified; @@ -1148,25 +1139,27 @@ class Simplex_tree { private: /** \brief Recursively Browse the simplex tree to ensure the filtration is not decreasing. * @param[in] sib Siblings to be parsed. - * @param[in] upper_filtration Upper level filtration value in the simplex tree. * @return The filtration modification information in order to trigger initialize_filtration. */ - bool rec_make_filtration_non_decreasing(Siblings * sib, Filtration_value upper_filtration) { + bool rec_make_filtration_non_decreasing(Siblings * sib) { bool modified = false; - // Find the maximum filtration value in the border - Simplex_handle max_border_value = std::max_element( std::begin(sib->members()), std::end(sib->members()), - [](const Map_element& sh1, const Map_element& sh2) { - return sh1.second.filtration() < sh2.second.filtration(); - }); for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { - if (sh->second.filtration() < upper_filtration) { + // Find the maximum filtration value in the border + Boundary_simplex_range boundary = boundary_simplex_range(sh); + Boundary_simplex_iterator max_border = std::max_element( std::begin(boundary), std::end(boundary), + [](Simplex_handle sh1, Simplex_handle sh2) { + return filtration(sh1) < filtration(sh2); + } ); + + Filtration_value max_filt_border_value = filtration(*max_border); + if (sh->second.filtration() < max_filt_border_value) { // Store the filtration modification information modified = true; - sh->second.assign_filtration(upper_filtration); + sh->second.assign_filtration(max_filt_border_value); } if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children(), max_border_value->second.filtration()); + modified |= rec_make_filtration_non_decreasing(sh->second.children()); } } // Make the modified information to be traced by upper call diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 25ae5ed3..cd6746a6 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -806,46 +806,78 @@ BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) { st.insert_simplex_and_subfaces({3, 0}, 2.0); st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); - typeST st_bis = st; - // Check default insertion ensures the filtration values are non decreasing + // Inserted simplex: + // 1 + // o + // /X\ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 + + std::cout << "Check default insertion ensures the filtration values are non decreasing" << std::endl; BOOST_CHECK(!st.make_filtration_non_decreasing()); // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 2.0 // to 1.0 st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); - /* Inserted simplex: */ - /* 1 6 */ - /* o---o */ - /* /X\7/ */ - /* o---o---o---o */ - /* 2 0 3\X/4 */ - /* o */ - /* 5 */ - - BOOST_CHECK(st.make_filtration_non_decreasing()); + // Inserted simplex: + // 1 6 + // o---o + // /X\7/ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 - // Check make_filtration_non_decreasing is just not modifying root values - st_bis.insert_simplex_and_subfaces({0, 1, 6, 7}, 2.0); - st_bis.assign_filtration(st_bis.find({0}), 1.0); - st_bis.assign_filtration(st_bis.find({1}), 1.0); - st_bis.assign_filtration(st_bis.find({6}), 1.0); - st_bis.assign_filtration(st_bis.find({7}), 1.0); + std::cout << "Check default second insertion ensures the filtration values are non decreasing" << std::endl; + BOOST_CHECK(!st.make_filtration_non_decreasing()); - BOOST_CHECK(st == st_bis); + // Copy original simplex tree + typeST st_copy = st; - // Check make_filtration_non_decreasing can modify non-root values (leaves and non-leaf) - st.assign_filtration(st.find({0, 1, 6, 7}), 1.99); - st.assign_filtration(st.find({3, 4}), 1.5); - st.assign_filtration(st.find({0, 3}), -1.0); + // Modify specific values for st to become like st_copy thanks to make_filtration_non_decreasing + st.assign_filtration(st.find({0,1,6,7}), 0.8); + st.assign_filtration(st.find({0,1,6}), 0.9); + st.assign_filtration(st.find({0,6}), 0.6); + st.assign_filtration(st.find({3,4,5}), 1.2); + st.assign_filtration(st.find({3,4}), 1.1); + st.assign_filtration(st.find({4,5}), 1.99); + + std::cout << "Check the simplex_tree is rolled back in case of decreasing filtration values" << std::endl; BOOST_CHECK(st.make_filtration_non_decreasing()); - BOOST_CHECK(st == st_bis); + BOOST_CHECK(st == st_copy); - // Check make_filtration_non_decreasing is not modifying when increasing - st.assign_filtration(st.find({0, 1, 6, 7}), 4.5); - st.assign_filtration(st.find({3, 4, 5}), 15.0); + // Other simplex tree + typeST st_other; + st_other.insert_simplex_and_subfaces({2, 1, 0}, 3.0); // This one is different from st + st_other.insert_simplex_and_subfaces({3, 0}, 2.0); + st_other.insert_simplex_and_subfaces({3, 4, 5}, 2.0); + st_other.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); + + // Modify specific values for st to become like st_other thanks to make_filtration_non_decreasing + st.assign_filtration(st.find({2}), 3.0); + // By modifying just the simplex {2} + // {0,1,2}, {1,2} and {0,2} will be modified + + std::cout << "Check the simplex_tree is repaired in case of decreasing filtration values" << std::endl; + BOOST_CHECK(st.make_filtration_non_decreasing()); + BOOST_CHECK(st == st_other); + + // Modify specific values for st still to be non-decreasing + st.assign_filtration(st.find({0,1,2}), 10.0); + st.assign_filtration(st.find({0,2}), 9.0); + st.assign_filtration(st.find({0,1,6,7}), 50.0); + st.assign_filtration(st.find({0,1,6}), 49.0); + st.assign_filtration(st.find({0,1,7}), 48.0); + // Other copy simplex tree + typeST st_other_copy = st; + + std::cout << "Check the simplex_tree is not modified in case of non-decreasing filtration values" << std::endl; BOOST_CHECK(!st.make_filtration_non_decreasing()); - + BOOST_CHECK(st == st_other_copy); + } struct MyOptions : Simplex_tree_options_full_featured { -- cgit v1.2.3 From 57eb57ed2092beaceb978e31aebb500450b9599b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Feb 2016 09:07:16 +0000 Subject: rename alpha_shapes_persistence test with alpha_complex_3d_persistence git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@991 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 455ee94450098bbcc000fb2ab2c4d39a326dea2c --- src/Persistent_cohomology/example/CMakeLists.txt | 39 ++- .../example/alpha_complex_3d_persistence.cpp | 294 +++++++++++++++++++++ .../example/alpha_shapes_persistence.cpp | 294 --------------------- 3 files changed, 313 insertions(+), 314 deletions(-) create mode 100644 src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp delete mode 100644 src/Persistent_cohomology/example/alpha_shapes_persistence.cpp diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index 5fec8ad4..779a9e89 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -40,30 +40,29 @@ if(GMPXX_FOUND AND GMP_FOUND) target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) if(CGAL_FOUND) - add_executable(alpha_shapes_persistence alpha_shapes_persistence.cpp) - target_link_libraries(alpha_shapes_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) - add_test(alpha_shapes_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) - #add_test(alpha_shapes_persistence_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/alpha_shapes_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.st -p 3 -m 100) + include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround + + add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp) + target_link_libraries(alpha_complex_3d_persistence ${Boost_SYSTEM_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES} ${CGAL_LIBRARY}) + add_test(alpha_complex_3d_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_complex_3d_persistence ${CMAKE_SOURCE_DIR}/data/points/bunny_5000 2 0.5) if (NOT CGAL_VERSION VERSION_LESS 4.7.0) message(STATUS "CGAL version: ${CGAL_VERSION}.") - include( ${CGAL_USE_FILE} ) - # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. - # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 - # A workaround is to add "-std=c++11" again. - # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html - # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html - # but it implies to use cmake version 3.1 at least. - if(NOT MSVC) - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) - if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - endif() - endif() - # - End of workaround - find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") diff --git a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp new file mode 100644 index 00000000..ac208957 --- /dev/null +++ b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp @@ -0,0 +1,294 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2014 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Gudhi; +using namespace Gudhi::persistent_cohomology; + +// Alpha_shape_3 templates type definitions +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef CGAL::Alpha_shape_vertex_base_3 Vb; +typedef CGAL::Alpha_shape_cell_base_3 Fb; +typedef CGAL::Triangulation_data_structure_3 Tds; +typedef CGAL::Delaunay_triangulation_3 Triangulation_3; +typedef CGAL::Alpha_shape_3 Alpha_shape_3; + +// From file type definition +typedef Kernel::Point_3 Point_3; + +// filtration with alpha values needed type definition +typedef Alpha_shape_3::FT Alpha_value_type; +typedef CGAL::Object Object; +typedef CGAL::Dispatch_output_iterator< +CGAL::cpp11::tuple, +CGAL::cpp11::tuple >, + std::back_insert_iterator< std::vector > > > Dispatch; +typedef Alpha_shape_3::Cell_handle Cell_handle; +typedef Alpha_shape_3::Facet Facet; +typedef Alpha_shape_3::Edge Edge_3; +typedef std::list Vertex_list; + +// gudhi type definition +typedef Simplex_tree ST; +typedef ST::Vertex_handle Simplex_tree_vertex; +typedef std::map Alpha_shape_simplex_tree_map; +typedef std::pair Alpha_shape_simplex_tree_pair; +typedef std::vector< Simplex_tree_vertex > Simplex_tree_vector_vertex; + +Vertex_list from(const Cell_handle& ch) { + Vertex_list the_list; + for (auto i = 0; i < 4; i++) { +#ifdef DEBUG_TRACES + std::cout << "from cell[" << i << "]=" << ch->vertex(i)->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(ch->vertex(i)); + } + return the_list; +} + +Vertex_list from(const Facet& fct) { + Vertex_list the_list; + for (auto i = 0; i < 4; i++) { + if (fct.second != i) { +#ifdef DEBUG_TRACES + std::cout << "from facet=[" << i << "]" << fct.first->vertex(i)->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(fct.first->vertex(i)); + } + } + return the_list; +} + +Vertex_list from(const Edge_3& edg) { + Vertex_list the_list; + for (auto i = 0; i < 4; i++) { + if ((edg.second == i) || (edg.third == i)) { +#ifdef DEBUG_TRACES + std::cout << "from edge[" << i << "]=" << edg.first->vertex(i)->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(edg.first->vertex(i)); + } + } + return the_list; +} + +Vertex_list from(const Alpha_shape_3::Vertex_handle& vh) { + Vertex_list the_list; +#ifdef DEBUG_TRACES + std::cout << "from vertex=" << vh->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(vh); + return the_list; +} + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << + " path_to_file_graph coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n"; + exit(-1); +} + +int main(int argc, char * const argv[]) { + // program args management + if (argc != 4) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; + usage(argv[0]); + } + + int coeff_field_characteristic = 0; + int returnedScanValue = sscanf(argv[2], "%d", &coeff_field_characteristic); + if ((returnedScanValue == EOF) || (coeff_field_characteristic <= 0)) { + std::cerr << "Error: " << argv[2] << " is not correct\n"; + usage(argv[0]); + } + + Filtration_value min_persistence = 0.0; + returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); + if ((returnedScanValue == EOF) || (min_persistence < -1.0)) { + std::cerr << "Error: " << argv[3] << " is not correct\n"; + usage(argv[0]); + } + + // Read points from file + std::string filegraph = argv[1]; + std::list lp; + std::ifstream is(filegraph.c_str()); + int n; + is >> n; +#ifdef DEBUG_TRACES + std::cout << "Reading " << n << " points " << std::endl; +#endif // DEBUG_TRACES + Point_3 p; + for (; n > 0; n--) { + is >> p; + lp.push_back(p); + } + + // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. + Alpha_shape_3 as(lp.begin(), lp.end(), 0, Alpha_shape_3::GENERAL); +#ifdef DEBUG_TRACES + std::cout << "Alpha shape computed in GENERAL mode" << std::endl; +#endif // DEBUG_TRACES + + // filtration with alpha values from alpha shape + std::vector the_objects; + std::vector the_alpha_values; + + Dispatch disp = CGAL::dispatch_output(std::back_inserter(the_objects), + std::back_inserter(the_alpha_values)); + + as.filtration_with_alpha_values(disp); +#ifdef DEBUG_TRACES + std::cout << "filtration_with_alpha_values returns : " << the_objects.size() << " objects" << std::endl; +#endif // DEBUG_TRACES + + Alpha_shape_3::size_type count_vertices = 0; + Alpha_shape_3::size_type count_edges = 0; + Alpha_shape_3::size_type count_facets = 0; + Alpha_shape_3::size_type count_cells = 0; + + // Loop on objects vector + Vertex_list vertex_list; + ST simplex_tree; + Alpha_shape_simplex_tree_map map_cgal_simplex_tree; + std::vector::iterator the_alpha_value_iterator = the_alpha_values.begin(); + int dim_max = 0; + Filtration_value filtration_max = 0.0; + for (auto object_iterator : the_objects) { + // Retrieve Alpha shape vertex list from object + if (const Cell_handle * cell = CGAL::object_cast(&object_iterator)) { + vertex_list = from(*cell); + count_cells++; + if (dim_max < 3) { + // Cell is of dim 3 + dim_max = 3; + } + } else if (const Facet * facet = CGAL::object_cast(&object_iterator)) { + vertex_list = from(*facet); + count_facets++; + if (dim_max < 2) { + // Facet is of dim 2 + dim_max = 2; + } + } else if (const Edge_3 * edge = CGAL::object_cast(&object_iterator)) { + vertex_list = from(*edge); + count_edges++; + if (dim_max < 1) { + // Edge_3 is of dim 1 + dim_max = 1; + } + } else if (const Alpha_shape_3::Vertex_handle * vertex = + CGAL::object_cast(&object_iterator)) { + count_vertices++; + vertex_list = from(*vertex); + } + // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex + Simplex_tree_vector_vertex the_simplex_tree; + for (auto the_alpha_shape_vertex : vertex_list) { + Alpha_shape_simplex_tree_map::iterator the_map_iterator = map_cgal_simplex_tree.find(the_alpha_shape_vertex); + if (the_map_iterator == map_cgal_simplex_tree.end()) { + // alpha shape not found + Simplex_tree_vertex vertex = map_cgal_simplex_tree.size(); +#ifdef DEBUG_TRACES + std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] not found - insert " << vertex << std::endl; +#endif // DEBUG_TRACES + the_simplex_tree.push_back(vertex); + map_cgal_simplex_tree.insert(Alpha_shape_simplex_tree_pair(the_alpha_shape_vertex, vertex)); + } else { + // alpha shape found + Simplex_tree_vertex vertex = the_map_iterator->second; +#ifdef DEBUG_TRACES + std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] found in " << vertex << std::endl; +#endif // DEBUG_TRACES + the_simplex_tree.push_back(vertex); + } + } + // Construction of the simplex_tree + Filtration_value filtr = /*std::sqrt*/(*the_alpha_value_iterator); +#ifdef DEBUG_TRACES + std::cout << "filtration = " << filtr << std::endl; +#endif // DEBUG_TRACES + if (filtr > filtration_max) { + filtration_max = filtr; + } + simplex_tree.insert_simplex(the_simplex_tree, filtr); + if (the_alpha_value_iterator != the_alpha_values.end()) + ++the_alpha_value_iterator; + else + std::cout << "This shall not happen" << std::endl; + } + simplex_tree.set_filtration(filtration_max); + simplex_tree.set_dimension(dim_max); + +#ifdef DEBUG_TRACES + std::cout << "vertices \t\t" << count_vertices << std::endl; + std::cout << "edges \t\t" << count_edges << std::endl; + std::cout << "facets \t\t" << count_facets << std::endl; + std::cout << "cells \t\t" << count_cells << std::endl; + + + std::cout << "Information of the Simplex Tree: " << std::endl; + std::cout << " Number of vertices = " << simplex_tree.num_vertices() << " "; + std::cout << " Number of simplices = " << simplex_tree.num_simplices() << std::endl << std::endl; + std::cout << " Dimension = " << simplex_tree.dimension() << " "; + std::cout << " filtration = " << simplex_tree.filtration() << std::endl << std::endl; +#endif // DEBUG_TRACES + +#ifdef DEBUG_TRACES + std::cout << "Iterator on vertices: " << std::endl; + for (auto vertex : simplex_tree.complex_vertex_range()) { + std::cout << vertex << " "; + } +#endif // DEBUG_TRACES + + // Sort the simplices in the order of the filtration + simplex_tree.initialize_filtration(); + + std::cout << "Simplex_tree dim: " << simplex_tree.dimension() << std::endl; + // Compute the persistence diagram of the complex + Persistent_cohomology< ST, Field_Zp > pcoh(simplex_tree); + // initializes the coefficient field for homology + pcoh.init_coefficients(coeff_field_characteristic); + + pcoh.compute_persistent_cohomology(min_persistence); + + pcoh.output_diagram(); + + return 0; +} diff --git a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp b/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp deleted file mode 100644 index ac208957..00000000 --- a/src/Persistent_cohomology/example/alpha_shapes_persistence.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2014 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; - -// Alpha_shape_3 templates type definitions -typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; -typedef CGAL::Alpha_shape_vertex_base_3 Vb; -typedef CGAL::Alpha_shape_cell_base_3 Fb; -typedef CGAL::Triangulation_data_structure_3 Tds; -typedef CGAL::Delaunay_triangulation_3 Triangulation_3; -typedef CGAL::Alpha_shape_3 Alpha_shape_3; - -// From file type definition -typedef Kernel::Point_3 Point_3; - -// filtration with alpha values needed type definition -typedef Alpha_shape_3::FT Alpha_value_type; -typedef CGAL::Object Object; -typedef CGAL::Dispatch_output_iterator< -CGAL::cpp11::tuple, -CGAL::cpp11::tuple >, - std::back_insert_iterator< std::vector > > > Dispatch; -typedef Alpha_shape_3::Cell_handle Cell_handle; -typedef Alpha_shape_3::Facet Facet; -typedef Alpha_shape_3::Edge Edge_3; -typedef std::list Vertex_list; - -// gudhi type definition -typedef Simplex_tree ST; -typedef ST::Vertex_handle Simplex_tree_vertex; -typedef std::map Alpha_shape_simplex_tree_map; -typedef std::pair Alpha_shape_simplex_tree_pair; -typedef std::vector< Simplex_tree_vertex > Simplex_tree_vector_vertex; - -Vertex_list from(const Cell_handle& ch) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { -#ifdef DEBUG_TRACES - std::cout << "from cell[" << i << "]=" << ch->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(ch->vertex(i)); - } - return the_list; -} - -Vertex_list from(const Facet& fct) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { - if (fct.second != i) { -#ifdef DEBUG_TRACES - std::cout << "from facet=[" << i << "]" << fct.first->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(fct.first->vertex(i)); - } - } - return the_list; -} - -Vertex_list from(const Edge_3& edg) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { - if ((edg.second == i) || (edg.third == i)) { -#ifdef DEBUG_TRACES - std::cout << "from edge[" << i << "]=" << edg.first->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(edg.first->vertex(i)); - } - } - return the_list; -} - -Vertex_list from(const Alpha_shape_3::Vertex_handle& vh) { - Vertex_list the_list; -#ifdef DEBUG_TRACES - std::cout << "from vertex=" << vh->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(vh); - return the_list; -} - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << - " path_to_file_graph coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n"; - exit(-1); -} - -int main(int argc, char * const argv[]) { - // program args management - if (argc != 4) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; - usage(argv[0]); - } - - int coeff_field_characteristic = 0; - int returnedScanValue = sscanf(argv[2], "%d", &coeff_field_characteristic); - if ((returnedScanValue == EOF) || (coeff_field_characteristic <= 0)) { - std::cerr << "Error: " << argv[2] << " is not correct\n"; - usage(argv[0]); - } - - Filtration_value min_persistence = 0.0; - returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); - if ((returnedScanValue == EOF) || (min_persistence < -1.0)) { - std::cerr << "Error: " << argv[3] << " is not correct\n"; - usage(argv[0]); - } - - // Read points from file - std::string filegraph = argv[1]; - std::list lp; - std::ifstream is(filegraph.c_str()); - int n; - is >> n; -#ifdef DEBUG_TRACES - std::cout << "Reading " << n << " points " << std::endl; -#endif // DEBUG_TRACES - Point_3 p; - for (; n > 0; n--) { - is >> p; - lp.push_back(p); - } - - // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. - Alpha_shape_3 as(lp.begin(), lp.end(), 0, Alpha_shape_3::GENERAL); -#ifdef DEBUG_TRACES - std::cout << "Alpha shape computed in GENERAL mode" << std::endl; -#endif // DEBUG_TRACES - - // filtration with alpha values from alpha shape - std::vector the_objects; - std::vector the_alpha_values; - - Dispatch disp = CGAL::dispatch_output(std::back_inserter(the_objects), - std::back_inserter(the_alpha_values)); - - as.filtration_with_alpha_values(disp); -#ifdef DEBUG_TRACES - std::cout << "filtration_with_alpha_values returns : " << the_objects.size() << " objects" << std::endl; -#endif // DEBUG_TRACES - - Alpha_shape_3::size_type count_vertices = 0; - Alpha_shape_3::size_type count_edges = 0; - Alpha_shape_3::size_type count_facets = 0; - Alpha_shape_3::size_type count_cells = 0; - - // Loop on objects vector - Vertex_list vertex_list; - ST simplex_tree; - Alpha_shape_simplex_tree_map map_cgal_simplex_tree; - std::vector::iterator the_alpha_value_iterator = the_alpha_values.begin(); - int dim_max = 0; - Filtration_value filtration_max = 0.0; - for (auto object_iterator : the_objects) { - // Retrieve Alpha shape vertex list from object - if (const Cell_handle * cell = CGAL::object_cast(&object_iterator)) { - vertex_list = from(*cell); - count_cells++; - if (dim_max < 3) { - // Cell is of dim 3 - dim_max = 3; - } - } else if (const Facet * facet = CGAL::object_cast(&object_iterator)) { - vertex_list = from(*facet); - count_facets++; - if (dim_max < 2) { - // Facet is of dim 2 - dim_max = 2; - } - } else if (const Edge_3 * edge = CGAL::object_cast(&object_iterator)) { - vertex_list = from(*edge); - count_edges++; - if (dim_max < 1) { - // Edge_3 is of dim 1 - dim_max = 1; - } - } else if (const Alpha_shape_3::Vertex_handle * vertex = - CGAL::object_cast(&object_iterator)) { - count_vertices++; - vertex_list = from(*vertex); - } - // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex - Simplex_tree_vector_vertex the_simplex_tree; - for (auto the_alpha_shape_vertex : vertex_list) { - Alpha_shape_simplex_tree_map::iterator the_map_iterator = map_cgal_simplex_tree.find(the_alpha_shape_vertex); - if (the_map_iterator == map_cgal_simplex_tree.end()) { - // alpha shape not found - Simplex_tree_vertex vertex = map_cgal_simplex_tree.size(); -#ifdef DEBUG_TRACES - std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] not found - insert " << vertex << std::endl; -#endif // DEBUG_TRACES - the_simplex_tree.push_back(vertex); - map_cgal_simplex_tree.insert(Alpha_shape_simplex_tree_pair(the_alpha_shape_vertex, vertex)); - } else { - // alpha shape found - Simplex_tree_vertex vertex = the_map_iterator->second; -#ifdef DEBUG_TRACES - std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] found in " << vertex << std::endl; -#endif // DEBUG_TRACES - the_simplex_tree.push_back(vertex); - } - } - // Construction of the simplex_tree - Filtration_value filtr = /*std::sqrt*/(*the_alpha_value_iterator); -#ifdef DEBUG_TRACES - std::cout << "filtration = " << filtr << std::endl; -#endif // DEBUG_TRACES - if (filtr > filtration_max) { - filtration_max = filtr; - } - simplex_tree.insert_simplex(the_simplex_tree, filtr); - if (the_alpha_value_iterator != the_alpha_values.end()) - ++the_alpha_value_iterator; - else - std::cout << "This shall not happen" << std::endl; - } - simplex_tree.set_filtration(filtration_max); - simplex_tree.set_dimension(dim_max); - -#ifdef DEBUG_TRACES - std::cout << "vertices \t\t" << count_vertices << std::endl; - std::cout << "edges \t\t" << count_edges << std::endl; - std::cout << "facets \t\t" << count_facets << std::endl; - std::cout << "cells \t\t" << count_cells << std::endl; - - - std::cout << "Information of the Simplex Tree: " << std::endl; - std::cout << " Number of vertices = " << simplex_tree.num_vertices() << " "; - std::cout << " Number of simplices = " << simplex_tree.num_simplices() << std::endl << std::endl; - std::cout << " Dimension = " << simplex_tree.dimension() << " "; - std::cout << " filtration = " << simplex_tree.filtration() << std::endl << std::endl; -#endif // DEBUG_TRACES - -#ifdef DEBUG_TRACES - std::cout << "Iterator on vertices: " << std::endl; - for (auto vertex : simplex_tree.complex_vertex_range()) { - std::cout << vertex << " "; - } -#endif // DEBUG_TRACES - - // Sort the simplices in the order of the filtration - simplex_tree.initialize_filtration(); - - std::cout << "Simplex_tree dim: " << simplex_tree.dimension() << std::endl; - // Compute the persistence diagram of the complex - Persistent_cohomology< ST, Field_Zp > pcoh(simplex_tree); - // initializes the coefficient field for homology - pcoh.init_coefficients(coeff_field_characteristic); - - pcoh.compute_persistent_cohomology(min_persistence); - - pcoh.output_diagram(); - - return 0; -} -- cgit v1.2.3 From cbf1f4c98c9e6d7ba3b7c552e43c7c98ed349954 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Feb 2016 10:03:48 +0000 Subject: Make example for doc shorter. Include strategy reviewal git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@992 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 23d3e71d7d0fb4d649f73e53959626c5cbb0acd8 --- src/Alpha_complex/example/Alpha_complex_from_off.cpp | 9 +++++---- .../example/Alpha_complex_from_points.cpp | 18 ++---------------- src/Alpha_complex/include/gudhi/Alpha_complex.h | 1 - .../example/alpha_complex_persistence.cpp | 17 ++++++++++------- 4 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 4f381892..780f904b 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -1,12 +1,13 @@ +#include +#include + #include #include -#include - void usage(char * const progName) { std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value" << std::endl; std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0" << std::endl; - exit(-1); // ----- >> + exit(-1); // ----- >> } int main(int argc, char **argv) { @@ -23,7 +24,7 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); - + // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 00e988a6..dab161c9 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -1,31 +1,17 @@ -#include -#include #include +#include #include #include #include -#include - typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel; typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " alpha_square_max_value" << std::endl; - std::cerr << " i.e.: " << progName << " 32.0" << std::endl; - exit(-1); // ----- >> -} - int main(int argc, char **argv) { - if (argc != 2) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } + double alpha_square_max_value = 32.0; - double alpha_square_max_value = atof(argv[1]); - // ---------------------------------------------------------------------------- // Init of a list of points // ---------------------------------------------------------------------------- diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 1ab6766c..962ed8dc 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -34,7 +34,6 @@ #include // isnan, fmax #include -#include #include #include diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp index 0dabdeac..d2f9a4a2 100644 --- a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -1,13 +1,15 @@ -#include -#include - #include +#include // to construct a Delaunay_triangulation from a OFF file #include #include #include +#include +#include +#include // for numeric_limits + void program_options(int argc, char * argv[] , std::string & off_file_points , std::string & output_file_diag @@ -21,10 +23,10 @@ int main(int argc, char **argv) { Filtration_value alpha_square_max_value; int coeff_field_characteristic; Filtration_value min_persistence; - - program_options(argc, argv, off_file_points, output_file_diag, alpha_square_max_value, coeff_field_characteristic, min_persistence); - + program_options(argc, argv, off_file_points, output_file_diag, alpha_square_max_value, + coeff_field_characteristic, min_persistence); + // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- @@ -80,7 +82,8 @@ void program_options(int argc, char * argv[] ("help,h", "produce help message") ("output-file,o", po::value(&output_file_diag)->default_value(std::string()), "Name of file in which the persistence diagram is written. Default print in std::cout") - ("max-alpha-square-value,r", po::value(&alpha_square_max_value)->default_value(std::numeric_limits::infinity()), + ("max-alpha-square-value,r", + po::value(&alpha_square_max_value)->default_value(std::numeric_limits::infinity()), "Maximal alpha square value for the Alpha complex construction.") ("field-charac,p", po::value(&coeff_field_characteristic)->default_value(11), "Characteristic p of the coefficient field Z/pZ for computing homology.") -- cgit v1.2.3 From 74dcaacda1c887b008ea8c95b28962de1c02a2d0 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 2 Feb 2016 15:24:51 +0000 Subject: alpha off reader test strategy modification git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@995 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: aa4ba97eecefb03e01a53ae1e2b50248a0857043 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 2 +- .../example/Alpha_complex_from_off.cpp | 33 +++++++++++++++------- .../example/Alpha_complex_from_points.cpp | 2 +- src/Alpha_complex/example/CMakeLists.txt | 19 +++++++++++-- .../example/alphaoffreader_for_doc_32.txt | 26 ++++++++--------- src/Alpha_complex/test/CMakeLists.txt | 14 +++++++++ src/Simplex_tree/include/gudhi/Simplex_tree.h | 15 ++++++---- 7 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 12d62ac0..8eea6ba7 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -67,7 +67,7 @@ namespace alphacomplex { * * When launching: * - * \code $> ./alphapoints 60.0 + * \code $> ./alphapoints * \endcode * * the program output is: diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 780f904b..80445a22 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -5,14 +5,14 @@ #include void usage(char * const progName) { - std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value" << std::endl; - std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0" << std::endl; + std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value [ouput_file.txt]\n"; + std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0\n"; exit(-1); // ----- >> } int main(int argc, char **argv) { - if (argc != 3) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + if ((argc != 3) && (argc != 4)) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; usage(argv[0]); } @@ -25,21 +25,34 @@ int main(int argc, char **argv) { typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, alpha_square_max_value); + std::streambuf* streambufffer; + std::ofstream ouput_file_stream; + + if (argc == 4) { + ouput_file_stream.open(std::string(argv[3])); + streambufffer = ouput_file_stream.rdbuf(); + } else { + streambufffer = std::cout.rdbuf(); + } + + std::ostream output_stream(streambufffer); + // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- - std::cout << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << + output_stream << "Alpha complex is of dimension " << alpha_complex_from_file.dimension() << " - " << alpha_complex_from_file.num_simplices() << " simplices - " << alpha_complex_from_file.num_vertices() << " vertices." << std::endl; - std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + output_stream << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : alpha_complex_from_file.filtration_simplex_range()) { - std::cout << " ( "; + output_stream << " ( "; for (auto vertex : alpha_complex_from_file.simplex_vertex_range(f_simplex)) { - std::cout << vertex << " "; + output_stream << vertex << " "; } - std::cout << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; - std::cout << std::endl; + output_stream << ") -> " << "[" << alpha_complex_from_file.filtration(f_simplex) << "] "; + output_stream << std::endl; } + ouput_file_stream.close(); return 0; } diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index dab161c9..815e40d7 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -10,7 +10,7 @@ typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; int main(int argc, char **argv) { - double alpha_square_max_value = 32.0; + double alpha_square_max_value = 60.0; // ---------------------------------------------------------------------------- // Init of a list of points diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 33ff6805..d93dd436 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -27,12 +27,25 @@ if(CGAL_FOUND) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - - add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) - target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_executable ( alphapoints Alpha_complex_from_points.cpp ) target_link_libraries(alphapoints ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(alphapoints ${CMAKE_CURRENT_BINARY_DIR}/alphapoints) + + # Do not forget to copy test files in current binary dir + file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + # Do not forget to copy test results files in current binary dir + file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + file(COPY "alphaoffreader_for_doc_60.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + + add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) + target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(alphaoffreader_doc_60 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader alphacomplexdoc.off 60.0 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt) + add_test(alphaoffreader_doc_32 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader alphacomplexdoc.off 32.0 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt) + if (DIFF_PATH) + add_test(alphaoffreader_doc_60_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_60.txt) + add_test(alphaoffreader_doc_32_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt) + endif() else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt index 553431a9..13183e86 100644 --- a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt @@ -7,16 +7,16 @@ Iterator on alpha complex simplices in the filtration order, with [filtration va ( 4 ) -> [0] ( 5 ) -> [0] ( 6 ) -> [0] - ( 5 4 ) -> [6.25] - ( 4 1 ) -> [20] - ( 4 2 ) -> [8.5] - ( 6 2 ) -> [9.25] - ( 6 5 ) -> [10] - ( 6 4 ) -> [11.25] - ( 6 5 4 ) -> [12.5] - ( 6 4 2 ) -> [12.9959] - ( 3 0 ) -> [13.25] - ( 4 1 ) -> [20] - ( 1 0 ) -> [22.7367] - ( 3 1 0 ) -> [22.7367] - ( 5 0 ) -> [30.25] + ( 3 2 ) -> [6.25] + ( 5 4 ) -> [7.25] + ( 2 0 ) -> [8.5] + ( 1 0 ) -> [9.25] + ( 3 1 ) -> [10] + ( 2 1 ) -> [11.25] + ( 3 2 1 ) -> [12.5] + ( 2 1 0 ) -> [12.9959] + ( 6 5 ) -> [13.25] + ( 4 2 ) -> [20] + ( 6 4 ) -> [22.7367] + ( 6 5 4 ) -> [22.7367] + ( 6 3 ) -> [30.25] diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index fa24e1b1..52ec0a78 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -8,6 +8,20 @@ if(CGAL_FOUND) message(STATUS "CGAL version: ${CGAL_VERSION}.") include( ${CGAL_USE_FILE} ) + # In CMakeLists.txt, when include(${CGAL_USE_FILE}), CXX_FLAGS are overwritten. + # cf. http://doc.cgal.org/latest/Manual/installation.html#title40 + # A workaround is to add "-std=c++11" again. + # A fix would be to use https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html + # or even better https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html + # but it implies to use cmake version 3.1 at least. + if(NOT MSVC) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + # - End of workaround find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index dbef8517..3911f497 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -307,7 +307,8 @@ class Simplex_tree { * of the simplex. * * @param[in] sh Simplex for which the boundary is computed. */ - Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) { + template + Boundary_simplex_range boundary_simplex_range(DictionaryIterator sh) { return Boundary_simplex_range(Boundary_simplex_iterator(this, sh), Boundary_simplex_iterator(this)); } @@ -528,7 +529,11 @@ class Simplex_tree { /** \brief Returns true if the node in the simplex tree pointed by * sh has children.*/ - bool has_children(Simplex_handle sh) const { + /*bool has_children(Simplex_handle sh) const { + return (sh->second.children()->parent() == sh->first); + }*/ + template + bool has_children(DictionaryIterator sh) const { return (sh->second.children()->parent() == sh->first); } @@ -1128,7 +1133,7 @@ class Simplex_tree { bool make_filtration_non_decreasing() { bool modified = false; // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree - for (auto sh = (root_.members().end() - 1); sh >= root_.members().begin(); --sh) { + for (auto sh = root_.members().rbegin(); sh != root_.members().rend(); ++sh) { if (has_children(sh)) { modified |= rec_make_filtration_non_decreasing(sh->second.children()); } @@ -1144,10 +1149,11 @@ class Simplex_tree { bool rec_make_filtration_non_decreasing(Siblings * sib) { bool modified = false; + // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { // Find the maximum filtration value in the border Boundary_simplex_range boundary = boundary_simplex_range(sh); - Boundary_simplex_iterator max_border = std::max_element( std::begin(boundary), std::end(boundary), + Boundary_simplex_iterator max_border = std::max_element(std::begin(boundary), std::end(boundary), [](Simplex_handle sh1, Simplex_handle sh2) { return filtration(sh1) < filtration(sh2); } ); @@ -1175,7 +1181,6 @@ class Simplex_tree { * call `initialize_filtration()` to recompute it. */ void prune_above_filtration(Filtration_value filtration) { -std::cout << "prune_above_filtration - filtration=" << filtration << std::endl; // No action if filtration is not stored if (Options::store_filtration) { if (filtration < threshold_) { -- cgit v1.2.3 From 8cb0b53a28b9d4cf6b97abcffbb527b51e322a22 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 3 Feb 2016 10:15:31 +0000 Subject: make_filtration_non_decreasing and rec_make_filtration_non_decreasing must go through the tree in reverse mode (starting from the right part) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@997 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0c8f8aeabd7dcba26971381c425ef7b0b417138c --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 33 +++++++++++----------- .../gudhi/Simplex_tree/Simplex_tree_iterators.h | 3 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 3911f497..0d12e9b7 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef GUDHI_USE_TBB #include @@ -307,8 +308,8 @@ class Simplex_tree { * of the simplex. * * @param[in] sh Simplex for which the boundary is computed. */ - template - Boundary_simplex_range boundary_simplex_range(DictionaryIterator sh) { + template + Boundary_simplex_range boundary_simplex_range(SimplexHandle sh) { return Boundary_simplex_range(Boundary_simplex_iterator(this, sh), Boundary_simplex_iterator(this)); } @@ -529,11 +530,8 @@ class Simplex_tree { /** \brief Returns true if the node in the simplex tree pointed by * sh has children.*/ - /*bool has_children(Simplex_handle sh) const { - return (sh->second.children()->parent() == sh->first); - }*/ - template - bool has_children(DictionaryIterator sh) const { + template + bool has_children(SimplexHandle sh) const { return (sh->second.children()->parent() == sh->first); } @@ -765,7 +763,8 @@ class Simplex_tree { } /** Returns the Siblings containing a simplex.*/ - Siblings * self_siblings(Simplex_handle sh) { + template + Siblings* self_siblings(SimplexHandle sh) { if (sh->second.children()->parent() == sh->first) return sh->second.children()->oncles(); else @@ -1133,9 +1132,9 @@ class Simplex_tree { bool make_filtration_non_decreasing() { bool modified = false; // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree - for (auto sh = root_.members().rbegin(); sh != root_.members().rend(); ++sh) { - if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children()); + for (auto& sh : boost::adaptors::reverse(root_.members())) { + if (has_children(&sh)) { + modified |= rec_make_filtration_non_decreasing(sh.second.children()); } } return modified; @@ -1150,22 +1149,22 @@ class Simplex_tree { bool modified = false; // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree - for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { + for (auto& sh : boost::adaptors::reverse(sib->members())) { // Find the maximum filtration value in the border - Boundary_simplex_range boundary = boundary_simplex_range(sh); + Boundary_simplex_range boundary = boundary_simplex_range(&sh); Boundary_simplex_iterator max_border = std::max_element(std::begin(boundary), std::end(boundary), [](Simplex_handle sh1, Simplex_handle sh2) { return filtration(sh1) < filtration(sh2); } ); Filtration_value max_filt_border_value = filtration(*max_border); - if (sh->second.filtration() < max_filt_border_value) { + if (sh.second.filtration() < max_filt_border_value) { // Store the filtration modification information modified = true; - sh->second.assign_filtration(max_filt_border_value); + sh.second.assign_filtration(max_filt_border_value); } - if (has_children(sh)) { - modified |= rec_make_filtration_non_decreasing(sh->second.children()); + if (has_children(&sh)) { + modified |= rec_make_filtration_non_decreasing(sh.second.children()); } } // Make the modified information to be traced by upper call diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h index 936b7a1f..7e0a454d 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h @@ -104,7 +104,8 @@ class Simplex_tree_boundary_simplex_iterator : public boost::iterator_facade< st_(st) { } - Simplex_tree_boundary_simplex_iterator(SimplexTree * st, Simplex_handle sh) + template + Simplex_tree_boundary_simplex_iterator(SimplexTree * st, SimplexHandle sh) : last_(sh->first), sib_(nullptr), st_(st) { -- cgit v1.2.3 From 26bed354555e0f0fc18c6adc6a4b0fe27379a4a6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 3 Feb 2016 11:37:33 +0000 Subject: Mentionning Delaunay complex in Alpha complex documentation (user and reference) Specifying Alpha complex Kernel must be an Epick_d dD kernel (user and reference) git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@998 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b1a7a0cadd236bbfa6c529f2979ad2096414e207 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 4 +++- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 8eea6ba7..b109956d 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -52,10 +52,12 @@ namespace alphacomplex { * \cite cgal:hdj-t-15b from CGAL (the Computational Geometry * Algorithms Library \cite cgal:eb-15b). * - * The complex is a template class requiring a dD Geometry Kernel * \cite cgal:s-gkd-15b from CGAL as template. * + * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. + * * \section pointsexample Example from points * * This example builds the Delaunay triangulation from the given points in a 2D static kernel, and initializes the diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 962ed8dc..0898c6cd 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -57,6 +57,12 @@ namespace alphacomplex { * * Please refer to \ref alpha_complex for examples. * + * The complex is a template class requiring an Epick_d dD Geometry Kernel + * \cite cgal:s-gkd-15b from CGAL as template. + * + * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. + * */ template class Alpha_complex : public Simplex_tree<> { -- cgit v1.2.3 From 9781709e1c8ba405140345ba2e7d3e521e533e16 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 3 Feb 2016 11:52:24 +0000 Subject: it is a simplex and not a simplex handle git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@999 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4bfc8fe6051480854acbd68fdb5c6f09624aa3da --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 0d12e9b7..3569b323 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1132,9 +1132,9 @@ class Simplex_tree { bool make_filtration_non_decreasing() { bool modified = false; // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree - for (auto& sh : boost::adaptors::reverse(root_.members())) { - if (has_children(&sh)) { - modified |= rec_make_filtration_non_decreasing(sh.second.children()); + for (auto& simplex : boost::adaptors::reverse(root_.members())) { + if (has_children(&simplex)) { + modified |= rec_make_filtration_non_decreasing(simplex.second.children()); } } return modified; @@ -1149,22 +1149,22 @@ class Simplex_tree { bool modified = false; // Loop must be from the end to the beginning, as higher dimension simplex are always on the left part of the tree - for (auto& sh : boost::adaptors::reverse(sib->members())) { + for (auto& simplex : boost::adaptors::reverse(sib->members())) { // Find the maximum filtration value in the border - Boundary_simplex_range boundary = boundary_simplex_range(&sh); + Boundary_simplex_range boundary = boundary_simplex_range(&simplex); Boundary_simplex_iterator max_border = std::max_element(std::begin(boundary), std::end(boundary), [](Simplex_handle sh1, Simplex_handle sh2) { return filtration(sh1) < filtration(sh2); } ); Filtration_value max_filt_border_value = filtration(*max_border); - if (sh.second.filtration() < max_filt_border_value) { + if (simplex.second.filtration() < max_filt_border_value) { // Store the filtration modification information modified = true; - sh.second.assign_filtration(max_filt_border_value); + simplex.second.assign_filtration(max_filt_border_value); } - if (has_children(&sh)) { - modified |= rec_make_filtration_non_decreasing(sh.second.children()); + if (has_children(&simplex)) { + modified |= rec_make_filtration_non_decreasing(simplex.second.children()); } } // Make the modified information to be traced by upper call -- cgit v1.2.3 From 4d68901d74817ce356b701b38b083059954d7493 Mon Sep 17 00:00:00 2001 From: glisse Date: Sat, 20 Feb 2016 10:57:52 +0000 Subject: Details in the doc of alpha-complex. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1033 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7cc1b51ef8e93ee987710a8ea2ed4ac98638f099 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index b109956d..0987e0e7 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -39,13 +39,13 @@ namespace alphacomplex { * Alpha_complex is a simplicial complex * constructed from the finite cells of a Delaunay Triangulation. * - * The filtration value of each simplex is computed from the circumradius of the simplex if it is Gabriel or - * from the alpha value of the simplex cofaces that make it not Gabriel. + * The filtration value of each simplex is computed as the square of the circumradius of the simplex if the circumsphere is empty (the simplex is then said to be Gabriel), and as the minimum of the filtration + * values of the codimension 1 cofaces that make it not Gabriel otherwise. * - * All simplices that have a filtration value strictly greater than a given alpha square value are not inserted into - * the simplex. + * All simplices that have a filtration value strictly greater than a given alpha squared value are not inserted into + * the complex. * - * \image html "alpha_complex_representation.png" "Alpha simplicial complex representation" + * \image html "alpha_complex_representation.png" "Alpha-complex representation" * * Alpha_complex is constructing a `Simplex_tree` using Delaunay Triangulation @@ -54,7 +54,7 @@ namespace alphacomplex { * * The complex is a template class requiring an Epick_d dD Geometry Kernel - * \cite cgal:s-gkd-15b from CGAL as template. + * \cite cgal:s-gkd-15b from CGAL as template parameter. * * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. * @@ -129,14 +129,13 @@ namespace alphacomplex { * * \subsubsection nondecreasing Non decreasing filtration values * - * As Alpha square value computed from CGAL is an approximation, we have to make filtration non decreasing while - * increasing the dimension for our simplicial complex to be valid (cf. - * `Simplex_tree::make_filtration_non_decreasing()`). + * As the squared radii computed by CGAL are an approximation, it might happen that these alpha squared values do not quite define a proper filtration (i.e. non-decreasing with respect to inclusion). + * We fix that up by calling `Simplex_tree::make_filtration_non_decreasing()`. * * \subsubsection pruneabove Prune above given filtration value * - * The simplex tree is pruned from the given maximum alpha square value (cf. `Simplex_tree::prune_above_filtration()`). - * In this example, the value is given by the user as argument of the program. + * The simplex tree is pruned from the given maximum alpha squared value (cf. `Simplex_tree::prune_above_filtration()`). + * In the following example, the value is given by the user as argument of the program. * * * \section offexample Example from OFF file -- cgit v1.2.3 From 1f7bd529827a5da3fdae315935a682c4337ca7cd Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 10:28:31 +0000 Subject: Alpha complex documentation generated had no scrolling menu for alpha complexes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1039 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 91b8bc91510c4605956682db729f80c03f9b982f --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 0898c6cd..5183828f 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -49,7 +49,9 @@ namespace alphacomplex { /** * \brief Alpha complex data structure. - * + * + * \ingroup alpha_complex + * * \details * The data structure can be constructed from a CGAL Delaunay triangulation (for more informations on CGAL Delaunay * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) or from -- cgit v1.2.3 From df8cf1a75bceb3411e98281585045fb0f5609939 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 10:29:38 +0000 Subject: Boost flat_map erase on an iterator is most efficient git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1040 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1b20d31e129b9aa7f2d884aa935a53959a288650 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 2 +- src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 3569b323..1c4587c0 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1229,7 +1229,7 @@ class Simplex_tree { if ((child->size() > 1) || (child == root())) { // Not alone, just remove it from members // Special case when child is the root of the simplex tree, just remove it from members - child->erase(sh->first); + child->erase(sh); } else { // Sibling is emptied : must be deleted, and its parent must point on his own Sibling child->oncles()->members().at(child->parent()).assign_children(child->oncles()); diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h index 8942d92c..1eca7f6f 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_siblings.h @@ -116,8 +116,8 @@ class Simplex_tree_siblings { return members_.size(); } - void erase(const Vertex_handle vh) { - members_.erase(vh); + void erase(const Dictionary_it iterator) { + members_.erase(iterator); } Simplex_tree_siblings * oncles_; -- cgit v1.2.3 From 558d908404cdc2e1f5111fd9ee236cd55ab7790a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 11:00:11 +0000 Subject: Use GUDHI_CHECK on null_simplex instead of "if" git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1041 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 783218b56e34ef53fbca5bb52e8a467504c0eddc --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 1c4587c0..813e7924 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -451,12 +451,12 @@ class Simplex_tree { } /** \brief Sets the filtration value of a simplex. - * - * No action if called on the null_simplex*/ + * \warning In debug mode, the exception std::invalid_argument is thrown if sh is a null_simplex. + */ void assign_filtration(Simplex_handle sh, Filtration_value fv) { - if (sh != null_simplex()) { - sh->second.assign_filtration(fv); - } + GUDHI_CHECK(sh == null_simplex(), + std::invalid_argument ("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex")); + sh->second.assign_filtration(fv); } /** \brief Returns an upper bound of the filtration values of the simplices. */ -- cgit v1.2.3 From 07fe71e2301f95fd0008bfc91e72f07b4f0d9bb6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 13:42:22 +0000 Subject: No more use of threshold_ for prune_above_filtration because threshold may be not up to date git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1043 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b17d8ef63bc173b4c4b6b0bde31f97d85672a754 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 48 +++++++++++------------- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 35 +++++------------ 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 813e7924..92f4576d 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1174,7 +1174,6 @@ class Simplex_tree { public: /** \brief Prune above filtration value given as parameter. * @param[in] filtration Maximum threshold value. - * \warning threshold_ is set from filtration given as parameter. * \warning The filtration must be valid. If the filtration has not been initialized yet, the method initializes it * (i.e. order the simplices). If the complex has changed since the last time the filtration was initialized, please * call `initialize_filtration()` to recompute it. @@ -1182,33 +1181,30 @@ class Simplex_tree { void prune_above_filtration(Filtration_value filtration) { // No action if filtration is not stored if (Options::store_filtration) { - if (filtration < threshold_) { - threshold_ = filtration; - // Initialize filtration_vect_ if required - if (filtration_vect_.empty()) { - initialize_filtration(); - } + // Initialize filtration_vect_ if required + if (filtration_vect_.empty()) { + initialize_filtration(); + } - std::vector> simplex_list_to_removed; - // Loop in reverse mode until threshold is reached - // Do not erase while looping, because removing is shifting data in a flat_map - for (auto f_simplex = filtration_vect_.rbegin(); - (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > threshold_); - f_simplex++) { - std::vector simplex_to_remove; - for (auto vertex : simplex_vertex_range(*f_simplex)) - simplex_to_remove.insert(simplex_to_remove.begin(), vertex); - simplex_list_to_removed.push_back(simplex_to_remove); - } - for (auto simplex_to_remove : simplex_list_to_removed) { - Simplex_handle sh = find_simplex(simplex_to_remove); - if (sh != null_simplex()) - remove_maximal_simplex(sh); - } - // Re-initialize filtration_vect_ if dta were removed, because removing is shifting data in a flat_map - if (simplex_list_to_removed.size() > 0) - initialize_filtration(); + std::vector> simplex_list_to_removed; + // Loop in reverse mode until threshold is reached + // Do not erase while looping, because removing is shifting data in a flat_map + for (auto f_simplex = filtration_vect_.rbegin(); + (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > filtration); + f_simplex++) { + std::vector simplex_to_remove; + for (auto vertex : simplex_vertex_range(*f_simplex)) + simplex_to_remove.insert(simplex_to_remove.begin(), vertex); + simplex_list_to_removed.push_back(simplex_to_remove); + } + for (auto simplex_to_remove : simplex_list_to_removed) { + Simplex_handle sh = find_simplex(simplex_to_remove); + if (sh != null_simplex()) + remove_maximal_simplex(sh); } + // Re-initialize filtration_vect_ if dta were removed, because removing is shifting data in a flat_map + if (simplex_list_to_removed.size() > 0) + initialize_filtration(); } } diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index cd6746a6..ff8993b3 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -989,7 +989,7 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { // Constructs a copy at this state for further test purpose typeST st_pruned = st; - st_pruned.initialize_filtration(); // reset + st_pruned.initialize_filtration(); // reset st.insert_simplex_and_subfaces({3, 0}, 3.0); st.insert_simplex_and_subfaces({2, 1, 0}, 4.0); @@ -1021,12 +1021,11 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { st.prune_above_filtration(6.0); BOOST_CHECK(st == st_complete); // lower than initial filtration value, but still greater than the maximum filtration value - st_complete.set_filtration(5.0); st.prune_above_filtration(5.0); BOOST_CHECK(st == st_complete); // Display the Simplex_tree - std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; + std::cout << "The complex contains " << st.num_simplices() << " simplices"; std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; for (auto f_simplex : st.filtration_simplex_range()) { @@ -1039,47 +1038,33 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { // Check the pruned cases // Set the st_pruned filtration for operator== - st_pruned.set_filtration(2.5); st.prune_above_filtration(2.5); BOOST_CHECK(st == st_pruned); // Display the Simplex_tree - std::cout << "The complex pruned at 2.5 contains " << st.num_simplices() << " simplices" << std::endl; + std::cout << "The complex pruned at 2.5 contains " << st.num_simplices() << " simplices"; std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; - std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; - for (auto f_simplex : st.filtration_simplex_range()) { - std::cout << " " << "[" << st.filtration(f_simplex) << "] "; - for (auto vertex : st.simplex_vertex_range(f_simplex)) { - std::cout << (int) vertex << " "; - } - std::cout << std::endl; - } - st_pruned.set_filtration(2.0); st.prune_above_filtration(2.0); + + std::cout << "The complex pruned at 2.0 contains " << st.num_simplices() << " simplices"; + std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + BOOST_CHECK(st == st_pruned); typeST st_empty; + st_empty.set_filtration(6.0); // For equality reason // FIXME st_empty.set_dimension(3); st.prune_above_filtration(0.0); - // Display the Simplex_tree - std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices" << std::endl; + // Display the Simplex_tree + std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices"; std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; - std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; - for (auto f_simplex : st.filtration_simplex_range()) { - std::cout << " " << "[" << st.filtration(f_simplex) << "] "; - for (auto vertex : st.simplex_vertex_range(f_simplex)) { - std::cout << (int) vertex << " "; - } - std::cout << std::endl; - } BOOST_CHECK(st == st_empty); // Test case to the limit st.prune_above_filtration(-1.0); - st_empty.set_filtration(-1.0); BOOST_CHECK(st == st_empty); } -- cgit v1.2.3 From 77243b4c6ad09f1f60122191414fc5fb2e2cc865 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 15:08:30 +0000 Subject: Remove Options::store_filtration check is true in prune_above_filtration function in order to let the user empty the tree To empty the tree, call initialize_filtration() and prune_above_filtration(-1) Add a UT to test this case git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1044 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: bb4a916fb547c6312f2138d355903ef87525e9c4 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 49 +++++++++++------------- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 40 ++++++++++++++++++- 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 92f4576d..ac5fbe79 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1179,33 +1179,30 @@ class Simplex_tree { * call `initialize_filtration()` to recompute it. */ void prune_above_filtration(Filtration_value filtration) { - // No action if filtration is not stored - if (Options::store_filtration) { - // Initialize filtration_vect_ if required - if (filtration_vect_.empty()) { - initialize_filtration(); - } - - std::vector> simplex_list_to_removed; - // Loop in reverse mode until threshold is reached - // Do not erase while looping, because removing is shifting data in a flat_map - for (auto f_simplex = filtration_vect_.rbegin(); - (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > filtration); - f_simplex++) { - std::vector simplex_to_remove; - for (auto vertex : simplex_vertex_range(*f_simplex)) - simplex_to_remove.insert(simplex_to_remove.begin(), vertex); - simplex_list_to_removed.push_back(simplex_to_remove); - } - for (auto simplex_to_remove : simplex_list_to_removed) { - Simplex_handle sh = find_simplex(simplex_to_remove); - if (sh != null_simplex()) - remove_maximal_simplex(sh); - } - // Re-initialize filtration_vect_ if dta were removed, because removing is shifting data in a flat_map - if (simplex_list_to_removed.size() > 0) - initialize_filtration(); + // Initialize filtration_vect_ if required + if (filtration_vect_.empty()) { + initialize_filtration(); + } + + std::vector> simplex_list_to_removed; + // Loop in reverse mode until threshold is reached + // Do not erase while looping, because removing is shifting data in a flat_map + for (auto f_simplex = filtration_vect_.rbegin(); + (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > filtration); + f_simplex++) { + std::vector simplex_to_remove; + for (auto vertex : simplex_vertex_range(*f_simplex)) + simplex_to_remove.insert(simplex_to_remove.begin(), vertex); + simplex_list_to_removed.push_back(simplex_to_remove); } + for (auto simplex_to_remove : simplex_list_to_removed) { + Simplex_handle sh = find_simplex(simplex_to_remove); + if (sh != null_simplex()) + remove_maximal_simplex(sh); + } + // Re-initialize filtration_vect_ if dta were removed, because removing is shifting data in a flat_map + if (simplex_list_to_removed.size() > 0) + initialize_filtration(); } /** \brief Remove a maximal simplex. diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index ff8993b3..b8c1cc35 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -985,7 +985,6 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0); st.insert_simplex_and_subfaces({3, 4, 5}, 2.0); - st.set_filtration(6.0); // Constructs a copy at this state for further test purpose typeST st_pruned = st; @@ -1053,7 +1052,6 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { BOOST_CHECK(st == st_pruned); typeST st_empty; - st_empty.set_filtration(6.0); // For equality reason // FIXME st_empty.set_dimension(3); st.prune_above_filtration(0.0); @@ -1068,3 +1066,41 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { st.prune_above_filtration(-1.0); BOOST_CHECK(st == st_empty); } + +BOOST_AUTO_TEST_CASE(mini_prune_above_filtration) { + std::cout << "********************************************************************" << std::endl; + std::cout << "MINI PRUNE ABOVE FILTRATION" << std::endl; + typedef Simplex_tree typeST; + typeST st; + + // FIXME + st.set_dimension(3); + + st.insert_simplex_and_subfaces({0, 1, 6, 7}); + st.insert_simplex_and_subfaces({3, 4, 5}); + st.insert_simplex_and_subfaces({3, 0}); + st.insert_simplex_and_subfaces({2, 1, 0}); + + // st: + // 1 6 + // o---o + // /X\7/ + // o---o---o---o + // 2 0 3\X/4 + // o + // 5 + + st.initialize_filtration(); + + // Display the Simplex_tree + std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; + BOOST_CHECK(st.num_simplices() == 27); + + // Test case to the limit + st.prune_above_filtration(-1.0); + + // Display the Simplex_tree + std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; + BOOST_CHECK(st.num_simplices() == 0); + +} \ No newline at end of file -- cgit v1.2.3 From 50d0b9006eaefa4aa41eba336206afd5ad700324 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 14 Mar 2016 15:20:59 +0000 Subject: Remove temporary get_persistence function git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1045 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c7503904a243d5f642b9efcbc65df856590e11fc --- src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index 19417ace..643b810c 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -722,14 +722,6 @@ class Persistent_cohomology { } } - void get_persistence(std::vector>& persistence) { - cmp_intervals_by_length cmp(cpx_); - std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp); - for (auto pair : persistent_pairs_) { - persistence.push_back(std::make_pair(cpx_->filtration(get<0>(pair)), cpx_->filtration(get<1>(pair)))); - } - } - void write_output_diagram(std::string diagram_name) { std::ofstream diagram_out(diagram_name.c_str()); cmp_intervals_by_length cmp(cpx_); -- cgit v1.2.3 From a28d3c6ba5ab9687626992cc0402c4399c76ecaf Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 15 Mar 2016 14:23:19 +0000 Subject: In Delaunay_triangulation_off_io.h, constructing the Triangulation from a vector of Points is a more efficient way (instead of inserting points on the fly). As consequence, the documentation needs to be rewritten as the points index are changed. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1046 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: bdb0196b61418a983cfaf7f6781a3a2906e8b136 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 8 +- src/Alpha_complex/doc/alpha_complex_doc.ipe | 371 ++++++++++----- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 49973 -> 25150 bytes src/Alpha_complex/doc/alpha_complex_doc_135.ipe | 514 --------------------- src/Alpha_complex/doc/alpha_complex_doc_135.png | Bin 80794 -> 0 bytes src/Alpha_complex/doc/alpha_complex_doc_421.ipe | 514 +++++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc_421.png | Bin 0 -> 100798 bytes .../doc/alpha_complex_representation.ipe | 14 +- .../doc/alpha_complex_representation.png | Bin 16737 -> 14628 bytes src/Alpha_complex/example/CMakeLists.txt | 8 +- .../example/alphaoffreader_for_doc_32.txt | 26 +- .../example/alphaoffreader_for_doc_60.txt | 36 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 1 + src/common/example/CMakeLists.txt | 6 + .../example/dtoffrw_alphashapedoc_result.off | 18 +- .../include/gudhi/Delaunay_triangulation_off_io.h | 26 +- src/common/test/CMakeLists.txt | 4 +- src/common/test/dtoffrw_alphashapedoc_result.off | 18 +- 18 files changed, 851 insertions(+), 713 deletions(-) delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.ipe delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_135.png create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_421.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_421.png diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 0987e0e7..deecf93f 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -112,19 +112,19 @@ namespace alphacomplex { * * \subsubsection dimension2 Dimension 2 * - * From the example above, it means the algorithm looks into each triangle ([1,2,3], [2,3,4], [1,3,5], ...), + * From the example above, it means the algorithm looks into each triangle ([4,2,1], [2,4,6], [4,5,6], ...), * computes the filtration value of the triangle, and then propagates the filtration value as described * here : - * \image html "alpha_complex_doc_135.png" "Filtration value propagation example" + * \image html "alpha_complex_doc_421.png" "Filtration value propagation example" * * \subsubsection dimension1 Dimension 1 * - * Then, the algorithm looks into each edge ([1,2], [2,3], [1,3], ...), + * Then, the algorithm looks into each edge ([1,2], [4,2], [4,1], ...), * computes the filtration value of the edge (in this case, propagation will have no effect). * * \subsubsection dimension0 Dimension 0 * - * Finally, the algorithm looks into each vertex ([1], [2], [3], [4], [5], [6] and [7]) and + * Finally, the algorithm looks into each vertex ([0], [1], [2], [3], [4], [5] and [6]) and * sets the filtration value (0 in case of a vertex - propagation will have no effect). * * \subsubsection nondecreasing Non decreasing filtration values diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe index e74f9bc4..99bd05af 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -1,7 +1,7 @@ - + @@ -253,13 +253,13 @@ h 320 580 l Delaunay triangulation -0 -1 -2 -3 -4 -5 -6 +2 +6 +4 +5 +1 +3 +0 280 660 m 300 710 l @@ -278,161 +278,282 @@ h 320 580 l 280 660 l -0 -1 -2 -2 -1 -2 -2 -3 -3 -3 -3 -4 -4 -4 -4 -6 -6 -6 -6 -6 -6 -5 -6 -5 - + 4 0 0 4 320 704 e - + 322.919 706.788 m 317.189 701.058 l 317.189 701.203 l - + 317.551 706.934 m 322.629 701.058 l - -230 680 m -240 670 l + +240 620 m +220 600 l - -230 680 m -240 670 l + +240 620 m +220 640 l - -230 680 m -240 670 l +Simplex tree structure + +280 630 m +170 630 l - -230 680 m -240 670 l + +280 610 m +170 610 l - -230 680 m -220 670 l + + + + + + + +3 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -230 680 m -230 670 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -220 660 m -220 650 l +4 +3 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -230 660 m -230 650 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -260 680 m -260 670 l +4 +1 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -260 660 m -260 650 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -300 680 m -300 670 l +5 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -300 680 m -290 670 l +5 +3 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -290 660 m -290 650 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -300 660 m -300 650 l +4 +2 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -330 680 m -330 670 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -350 680 m -350 670 l +4 +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -350 660 m -350 650 l +4 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -240 690 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -270 690 l +6 +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -310 690 l +5 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -330 690 l + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -350 690 l +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h - -320 700 m -380 690 l +6 + +292 716 m +292 728 l +316 728 l +316 716 l +h - -320 700 m -400 690 l + +316 716 m +316 728 l +340 728 l +340 716 l +h - -240 620 m -220 600 l + +340 716 m +340 728 l +364 728 l +364 716 l +h - -240 620 m -220 640 l + +364 716 m +364 728 l +388 728 l +388 716 l +h + + +388 716 m +388 728 l +412 728 l +412 716 l +h + + +412 716 m +412 728 l +436 728 l +436 716 l +h + + +436 716 m +436 728 l +460 728 l +460 716 l +h + +0 +1 +2 +3 +4 +5 +6 + +436 708 m +436 716 l + + +364 708 m +364 716 l + + +364 688 m +364 696 l + + +320 688 m +320 696 l + + +296 708 m +308 716 l +308 716 l + + +264 688 m +268 696 l + + +292 688 m +292 696 l + + +388 736 m +388 728 l -Simplex tree structure -280 630 m -170 630 l +372 612 m +376 620 l -280 610 m -170 610 l +448 612 m +448 620 l - - - - - - - diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index c9eab275..cfe3ede6 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc.png and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe b/src/Alpha_complex/doc/alpha_complex_doc_135.ipe deleted file mode 100644 index 5d1d29d4..00000000 --- a/src/Alpha_complex/doc/alpha_complex_doc_135.ipe +++ /dev/null @@ -1,514 +0,0 @@ - - - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - -0.6 0 0 0.6 0 0 e - - - - - -0.5 0 0 0.5 0 0 e - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h - - - - - --0.5 -0.5 m -0.5 -0.5 l -0.5 0.5 l --0.5 0.5 l -h - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - - - --0.43 -0.57 m -0.57 0.43 l -0.43 0.57 l --0.57 -0.43 l -h - - --0.43 0.57 m -0.57 -0.43 l -0.43 -0.57 l --0.57 0.43 l -h - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - --1 0.333 m -0 0 l --1 -0.333 l - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -Cell [4,2,0] -0 -1 -2 -3 -4 -5 -6 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - - -77.2727 0 0 77.2727 243.636 591.818 e - - -243.428 591.569 m -186.061 643.28 l - -$\alpha_{420}$ - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -[2,0] is Gabriel $\rightarrow$ $\alpha_{20}$ is not$\\$ -modified (NaN) - -0 -2 -3 -4 -5 -6 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{20}$ - -290 530 m -320 580 l - - -29.1548 0 0 29.1548 305 555 e - - -304.883 555.015 m -334.509 555.015 l - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -[0,4] is not Gabriel $\rightarrow$ $\alpha_{40} = \alpha_{420}$ -0 -3 -5 -6 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{40}$ - -290 530 m -280 660 l - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -0 -1 -2 -3 -5 -6 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{42}$ -4 - -406.093 497.775 m -446.094 418.092 l - - -44.5799 0 0 44.5799 425.934 457.774 e - - -425.854 457.774 m -470.795 457.774 l - -[2,4] is Gabriel $\rightarrow$ $\alpha_{42}$ is not modified (NaN) - - -205.028 596.091 m -110.946 544.02 l - - -280.768 588.99 m -280.768 547.57 l - - -341.123 594.316 m -413.904 554.079 l - -For all faces of [4,2,0] -N.B. : is Gabriel on a single point has no sense. -Dimension =2 - $\sigma$ = [4,2,0] - -247.333 430.892 m -311.764 430.892 l - - - - - - - - - - - - - - -1 - - - - - -4 - - -1 - - -2 - -65.192 0 0 65.192 285 595 e - - - - - - - - - - - - - diff --git a/src/Alpha_complex/doc/alpha_complex_doc_135.png b/src/Alpha_complex/doc/alpha_complex_doc_135.png deleted file mode 100644 index ef7187f7..00000000 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_135.png and /dev/null differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_421.ipe b/src/Alpha_complex/doc/alpha_complex_doc_421.ipe new file mode 100644 index 00000000..727816c5 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc_421.ipe @@ -0,0 +1,514 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +Cell [4,2,1] +2 +6 +4 +5 +1 +3 +0 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + + +77.2727 0 0 77.2727 243.636 591.818 e + + +243.428 591.569 m +186.061 643.28 l + +$\alpha_{421}$ + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[4,2] is Gabriel $\rightarrow$ $\alpha_{42}$ is not$\\$ +modified (NaN) + +2 +4 +5 +1 +3 +0 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{42}$ + +290 530 m +320 580 l + + +29.1548 0 0 29.1548 305 555 e + + +304.883 555.015 m +334.509 555.015 l + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[2,1] is not Gabriel $\rightarrow$ $\alpha_{21} = \alpha_{421}$ +2 +5 +3 +0 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{12}$ + +290 530 m +280 660 l + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +2 +6 +4 +5 +3 +0 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{41}$ +1 + +406.093 497.775 m +446.094 418.092 l + + +44.5799 0 0 44.5799 425.934 457.774 e + + +425.854 457.774 m +470.795 457.774 l + +[4,1] is Gabriel $\rightarrow$ $\alpha_{41}$ is not modified (NaN) + + +205.028 596.091 m +110.946 544.02 l + + +280.768 588.99 m +280.768 547.57 l + + +341.123 594.316 m +413.904 554.079 l + +For all faces of [4,2,1] +N.B. : is Gabriel on a single point has no sense. +Dimension =2 - $\sigma$ = [4,2,1] + +247.333 430.892 m +311.764 430.892 l + + + + + + + + + + + + + + +6 + + + + + +1 + + +6 + + +4 + +65.192 0 0 65.192 285 595 e + + + + + + + + + + + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_421.png b/src/Alpha_complex/doc/alpha_complex_doc_421.png new file mode 100644 index 00000000..1cce4402 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc_421.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_representation.ipe b/src/Alpha_complex/doc/alpha_complex_representation.ipe index 8687d694..fead1661 100644 --- a/src/Alpha_complex/doc/alpha_complex_representation.ipe +++ b/src/Alpha_complex/doc/alpha_complex_representation.ipe @@ -251,13 +251,13 @@ h h Alpha complex -0 -1 -2 -3 -4 -5 -6 +2 +6 +4 +5 +1 +3 +0 58.1341 0 0 58.1341 218.925 692.601 e diff --git a/src/Alpha_complex/doc/alpha_complex_representation.png b/src/Alpha_complex/doc/alpha_complex_representation.png index 06e54c06..9833bff3 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_representation.png and b/src/Alpha_complex/doc/alpha_complex_representation.png differ diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index e904133b..debb440d 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -18,15 +18,15 @@ if(CGAL_FOUND) # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - # Do not forget to copy test results files in current binary dir - file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - file(COPY "alphaoffreader_for_doc_60.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - add_executable ( alphaoffreader Alpha_complex_from_off.cpp ) target_link_libraries(alphaoffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(alphaoffreader_doc_60 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader alphacomplexdoc.off 60.0 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt) add_test(alphaoffreader_doc_32 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader alphacomplexdoc.off 32.0 ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt) if (DIFF_PATH) + # Do not forget to copy test results files in current binary dir + file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + file(COPY "alphaoffreader_for_doc_60.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + add_test(alphaoffreader_doc_60_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_60.txt) add_test(alphaoffreader_doc_32_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt) endif() diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt index 13183e86..5869fdff 100644 --- a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt @@ -7,16 +7,16 @@ Iterator on alpha complex simplices in the filtration order, with [filtration va ( 4 ) -> [0] ( 5 ) -> [0] ( 6 ) -> [0] - ( 3 2 ) -> [6.25] - ( 5 4 ) -> [7.25] - ( 2 0 ) -> [8.5] - ( 1 0 ) -> [9.25] - ( 3 1 ) -> [10] - ( 2 1 ) -> [11.25] - ( 3 2 1 ) -> [12.5] - ( 2 1 0 ) -> [12.9959] - ( 6 5 ) -> [13.25] - ( 4 2 ) -> [20] - ( 6 4 ) -> [22.7367] - ( 6 5 4 ) -> [22.7367] - ( 6 3 ) -> [30.25] + ( 5 4 ) -> [6.25] + ( 3 1 ) -> [7.25] + ( 4 2 ) -> [8.5] + ( 6 2 ) -> [9.25] + ( 6 5 ) -> [10] + ( 6 4 ) -> [11.25] + ( 6 5 4 ) -> [12.5] + ( 6 4 2 ) -> [12.9959] + ( 3 0 ) -> [13.25] + ( 4 1 ) -> [20] + ( 1 0 ) -> [22.7367] + ( 3 1 0 ) -> [22.7367] + ( 5 0 ) -> [30.25] diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt index 71f29a00..1d17a58a 100644 --- a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt @@ -7,21 +7,21 @@ Iterator on alpha complex simplices in the filtration order, with [filtration va ( 4 ) -> [0] ( 5 ) -> [0] ( 6 ) -> [0] - ( 3 2 ) -> [6.25] - ( 5 4 ) -> [7.25] - ( 2 0 ) -> [8.5] - ( 1 0 ) -> [9.25] - ( 3 1 ) -> [10] - ( 2 1 ) -> [11.25] - ( 3 2 1 ) -> [12.5] - ( 2 1 0 ) -> [12.9959] - ( 6 5 ) -> [13.25] - ( 4 2 ) -> [20] - ( 6 4 ) -> [22.7367] - ( 6 5 4 ) -> [22.7367] - ( 6 3 ) -> [30.25] - ( 6 2 ) -> [36.5] - ( 6 3 2 ) -> [36.5] - ( 6 4 2 ) -> [37.2449] - ( 4 0 ) -> [59.7107] - ( 4 2 0 ) -> [59.7107] + ( 5 4 ) -> [6.25] + ( 3 1 ) -> [7.25] + ( 4 2 ) -> [8.5] + ( 6 2 ) -> [9.25] + ( 6 5 ) -> [10] + ( 6 4 ) -> [11.25] + ( 6 5 4 ) -> [12.5] + ( 6 4 2 ) -> [12.9959] + ( 3 0 ) -> [13.25] + ( 4 1 ) -> [20] + ( 1 0 ) -> [22.7367] + ( 3 1 0 ) -> [22.7367] + ( 5 0 ) -> [30.25] + ( 4 0 ) -> [36.5] + ( 5 4 0 ) -> [36.5] + ( 4 1 0 ) -> [37.2449] + ( 2 1 ) -> [59.7107] + ( 4 2 1 ) -> [59.7107] diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 5183828f..a69afb51 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -48,6 +48,7 @@ namespace Gudhi { namespace alphacomplex { /** + * \class Alpha_complex Alpha_complex.h gudhi/Alpha_complex.h * \brief Alpha complex data structure. * * \ingroup alpha_complex diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index 6c2e7669..91e78ea2 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -13,6 +13,12 @@ if(CGAL_FOUND) target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) add_test(dtoffrw ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) + if (DIFF_PATH) + # Do not forget to copy test results files in current binary dir + file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + add_test(dtoffrw_result_off_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) + endif() + else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") endif() diff --git a/src/common/example/dtoffrw_alphashapedoc_result.off b/src/common/example/dtoffrw_alphashapedoc_result.off index 03b7ca75..d1839a43 100644 --- a/src/common/example/dtoffrw_alphashapedoc_result.off +++ b/src/common/example/dtoffrw_alphashapedoc_result.off @@ -1,15 +1,15 @@ nOFF 2 7 6 0 +9 17 +0 14 1 1 -7 0 +2 19 4 6 9 6 -0 14 -2 19 -9 17 -3 0 1 2 -3 3 2 1 -3 4 0 2 -3 4 2 6 -3 6 2 3 +7 0 +3 5 0 4 +3 0 1 4 +3 3 1 0 +3 4 1 2 3 5 4 6 +3 6 4 2 diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index b3f4a299..529774f0 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -31,7 +31,9 @@ namespace Gudhi { -/** \brief OFF file visitor implementation according to Off_reader in order to construct a CGAL Delaunay triangulation. +/** + * \class Delaunay_triangulation_off_visitor_reader Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h + * \brief OFF file visitor implementation according to Off_reader in order to construct a CGAL Delaunay triangulation. * * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page * http://doc.cgal.org/latest/Triangulation/ @@ -41,7 +43,7 @@ class Delaunay_triangulation_off_visitor_reader { private: Complex* complex_; typedef typename Complex::Point Point; - + std::vector point_cloud; public: // TODO(VR) : Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. @@ -95,7 +97,9 @@ class Delaunay_triangulation_off_visitor_reader { } std::cout << std::endl; #endif // DEBUG_TRACES - complex_->insert(Point(point.size(), point.begin(), point.end())); + // Fill the point cloud + // VR: complex_->insert(Point(point.size(), point.begin(), point.end())); + point_cloud.push_back(Point(point.size(), point.begin(), point.end())); } // Off_reader visitor maximal_face implementation - not used @@ -103,9 +107,11 @@ class Delaunay_triangulation_off_visitor_reader { // For Delaunay Triangulation, only points are read } - // Off_reader visitor done implementation - not used + // Off_reader visitor done implementation void done() { - // Nothing to be done on end of OFF file read + // It is advised to insert all the points at a time in a Delaunay Triangulation because points are sorted at the + // beginning of the insertion + complex_->insert(point_cloud.begin(), point_cloud.end()); } /** \brief Returns the constructed Delaunay triangulation. @@ -119,7 +125,9 @@ class Delaunay_triangulation_off_visitor_reader { } }; -/** \brief OFF file reader implementation in order to construct a Delaunay triangulation. +/** + * \class Delaunay_triangulation_off_reader Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h + * \brief OFF file reader implementation in order to construct a Delaunay triangulation. * * This class is using the Delaunay_triangulation_off_visitor_reader to visit the OFF file according to Off_reader. * @@ -135,7 +143,7 @@ class Delaunay_triangulation_off_visitor_reader { * * When launching: * - * \code $> ./dtoffrw ../../data/points/alphacomplexdoc triangulated.off + * \code $> ./dtoffrw ../../data/points/alphacomplexdoc.off triangulated.off * \endcode * * the program output is: @@ -203,7 +211,9 @@ class Delaunay_triangulation_off_reader { Complex* complex_; }; -/** \brief OFF file writer from a Delaunay triangulation. +/** + * \class Delaunay_triangulation_off_writer Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h + * \brief OFF file writer from a Delaunay triangulation. * * This class constructs the OFF file header according to http://www.geomview.org/docs/html/OFF.html * diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 50655a93..12eecda8 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -21,8 +21,6 @@ if(CGAL_FOUND) add_executable ( dtoffrw_UT dtoffrw_unit_test.cpp ) target_link_libraries(dtoffrw_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - # Do not forget to copy test files in current binary dir - file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) @@ -32,6 +30,8 @@ if(CGAL_FOUND) --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/dtoffrw_UT.xml --log_level=test_suite --report_level=no) if (DIFF_PATH) + # Do not forget to copy test result files in current binary dir + file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) add_test(dtoffrw_diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) endif() diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off index 03b7ca75..d1839a43 100644 --- a/src/common/test/dtoffrw_alphashapedoc_result.off +++ b/src/common/test/dtoffrw_alphashapedoc_result.off @@ -1,15 +1,15 @@ nOFF 2 7 6 0 +9 17 +0 14 1 1 -7 0 +2 19 4 6 9 6 -0 14 -2 19 -9 17 -3 0 1 2 -3 3 2 1 -3 4 0 2 -3 4 2 6 -3 6 2 3 +7 0 +3 5 0 4 +3 0 1 4 +3 3 1 0 +3 4 1 2 3 5 4 6 +3 6 4 2 -- cgit v1.2.3 From 298c080b45250f2b8f16a0c31ace9bb6fc666c93 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 16 Mar 2016 08:33:04 +0000 Subject: CppCheck and CppLint fixes for alpha complexes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1047 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a9b42ad2f8751384b5227fa3da8f380cda9b3696 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 4 ++-- .../example/Alpha_complex_from_off.cpp | 2 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 21 ++++++++++----------- src/GudhUI/model/Model.h | 2 +- src/GudhUI/utils/Bar_code_persistence.h | 11 ++++++++--- src/GudhUI/utils/Persistence_compute.h | 1 - src/GudhUI/view/FirstCoordProjector.h | 1 - .../example/alpha_complex_3d_persistence.cpp | 15 ++++----------- .../example/Delaunay_triangulation_off_rw.cpp | 14 +++++++------- .../include/gudhi/Delaunay_triangulation_off_io.h | 10 +++------- src/common/include/gudhi/Off_reader.h | 2 +- 11 files changed, 37 insertions(+), 46 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index deecf93f..f55d7029 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -161,8 +161,8 @@ namespace alphacomplex { */ /** @} */ // end defgroup alpha_complex -} // namespace alphacomplex +} // namespace alphacomplex -} // namespace Gudhi +} // namespace Gudhi #endif // INTRO_ALPHA_COMPLEX_H_ diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 80445a22..18a1a20d 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -27,7 +27,7 @@ int main(int argc, char **argv) { std::streambuf* streambufffer; std::ofstream ouput_file_stream; - + if (argc == 4) { ouput_file_stream.open(std::string(argv[3])); streambufffer = ouput_file_stream.rdbuf(); diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index a69afb51..eab66384 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef ALPHA_COMPLEX_H_ -#define ALPHA_COMPLEX_H_ +#ifndef DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ +#define DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ // to construct a simplex_tree from Delaunay_triangulation #include @@ -97,7 +97,6 @@ class Alpha_complex : public Simplex_tree<> { // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; - //typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Map_vertex_handle_to_iterator; typedef typename std::vector< CGAL_vertex_iterator > Vector_vertex_iterator; private: @@ -141,7 +140,7 @@ class Alpha_complex : public Simplex_tree<> { Alpha_complex(Delaunay_triangulation* triangulation_ptr, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(triangulation_ptr) { - init(max_alpha_square); + init(max_alpha_square); } /** \brief Alpha_complex constructor from a list of points. @@ -160,17 +159,17 @@ class Alpha_complex : public Simplex_tree<> { : triangulation_(nullptr) { auto first = std::begin(points); auto last = std::end(points); - + GUDHI_CHECK((first == last), - std::invalid_argument ("Alpha_complex::Alpha_complex(InputPointRange) - Empty input point range")); - + std::invalid_argument("Alpha_complex::Alpha_complex(InputPointRange) - Empty input point range")); + if (first != last) { // point_dimension function initialization Point_Dimension point_dimension = kernel_.point_dimension_d_object(); // Delaunay triangulation is point dimension minus one. triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); - + size_type inserted = triangulation_->insert(first, last); if (inserted != (last -first)) { std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << "\n"; @@ -227,7 +226,7 @@ class Alpha_complex : public Simplex_tree<> { } set_dimension(triangulation_->maximal_dimension()); - // set_filtration to +inf for prune_above_filtration to be done (if necessary) + // set_filtration to +inf for prune_above_filtration to be done (if necessary) set_filtration(std::numeric_limits::infinity()); // -------------------------------------------------------------------------------------------- @@ -247,7 +246,7 @@ class Alpha_complex : public Simplex_tree<> { } } // -------------------------------------------------------------------------------------------- - + // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { @@ -393,4 +392,4 @@ class Alpha_complex : public Simplex_tree<> { } // namespace Gudhi -#endif // ALPHA_COMPLEX_H_ +#endif // DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ diff --git a/src/GudhUI/model/Model.h b/src/GudhUI/model/Model.h index 99a82eba..1c39c0d7 100644 --- a/src/GudhUI/model/Model.h +++ b/src/GudhUI/model/Model.h @@ -71,7 +71,7 @@ class CGAL_geometric_flag_complex_wrapper { void maximal_face(std::vector vertices) { if (!load_only_points_) { - //std::cout << "size:" << vertices.size() << std::endl; + // std::cout << "size:" << vertices.size() << std::endl; for (int i = 0; i < vertices.size(); ++i) for (int j = i + 1; j < vertices.size(); ++j) complex_.add_edge(Vertex_handle(vertices[i]), Vertex_handle(vertices[j])); diff --git a/src/GudhUI/utils/Bar_code_persistence.h b/src/GudhUI/utils/Bar_code_persistence.h index a4cd8156..b527d684 100644 --- a/src/GudhUI/utils/Bar_code_persistence.h +++ b/src/GudhUI/utils/Bar_code_persistence.h @@ -12,6 +12,10 @@ #include #include // NaN, infinity #include // for pair +#include + +#ifndef UTILS_BAR_CODE_PERSISTENCE_H_ +#define UTILS_BAR_CODE_PERSISTENCE_H_ class Bar_code_persistence { private: @@ -21,7 +25,6 @@ class Bar_code_persistence { double max_death; public: - Bar_code_persistence() : min_birth(std::numeric_limits::quiet_NaN()), max_death(std::numeric_limits::quiet_NaN()) { } @@ -45,13 +48,13 @@ class Bar_code_persistence { QGraphicsScene * scene = new QGraphicsScene(); view->setScene(scene); double ratio = 600.0 / (max_death - min_birth); - //std::cout << "min_birth=" << min_birth << " - max_death=" << max_death << " - ratio=" << ratio << std::endl; + // std::cout << "min_birth=" << min_birth << " - max_death=" << max_death << " - ratio=" << ratio << std::endl; double height = 0.0, birth = 0.0, death = 0.0; int pers_num = 1; for (auto& persistence : persistence_vector) { height = 5.0 * pers_num; - //std::cout << "[" << pers_num << "] birth=" << persistence.first << " - death=" << persistence.second << std::endl; + // std::cout << "[" << pers_num << "] birth=" << persistence.first << " - death=" << persistence.second << std::endl; if (std::isfinite(persistence.first)) birth = ((persistence.first - min_birth) * ratio) + 50.0; else @@ -83,3 +86,5 @@ class Bar_code_persistence { view->show(); } }; + +#endif // UTILS_BAR_CODE_PERSISTENCE_H_ diff --git a/src/GudhUI/utils/Persistence_compute.h b/src/GudhUI/utils/Persistence_compute.h index 1f04cc6b..97165490 100644 --- a/src/GudhUI/utils/Persistence_compute.h +++ b/src/GudhUI/utils/Persistence_compute.h @@ -85,7 +85,6 @@ template class Persistence_compute { stream << "p dimension birth death: \n"; pcoh.output_diagram(stream); - } }; diff --git a/src/GudhUI/view/FirstCoordProjector.h b/src/GudhUI/view/FirstCoordProjector.h index 3ceda3f5..a4027b7f 100644 --- a/src/GudhUI/view/FirstCoordProjector.h +++ b/src/GudhUI/view/FirstCoordProjector.h @@ -36,7 +36,6 @@ class FirstCoordProjector3D : public Projector3D { return Point_3(p.x(), p.y(), p.z()); else if (p.dimension() >= 2) return Point_3(p.x(), p.y(), 0.0); - } }; diff --git a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp index ac208957..f81951ce 100644 --- a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp @@ -39,9 +39,6 @@ #include #include -using namespace Gudhi; -using namespace Gudhi::persistent_cohomology; - // Alpha_shape_3 templates type definitions typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Alpha_shape_vertex_base_3 Vb; @@ -66,11 +63,12 @@ typedef Alpha_shape_3::Edge Edge_3; typedef std::list Vertex_list; // gudhi type definition -typedef Simplex_tree ST; +typedef Gudhi::Simplex_tree ST; typedef ST::Vertex_handle Simplex_tree_vertex; typedef std::map Alpha_shape_simplex_tree_map; typedef std::pair Alpha_shape_simplex_tree_pair; typedef std::vector< Simplex_tree_vertex > Simplex_tree_vector_vertex; +typedef Gudhi::persistent_cohomology::Persistent_cohomology< ST, Gudhi::persistent_cohomology::Field_Zp > PCOH; Vertex_list from(const Cell_handle& ch) { Vertex_list the_list; @@ -131,12 +129,7 @@ int main(int argc, char * const argv[]) { usage(argv[0]); } - int coeff_field_characteristic = 0; - int returnedScanValue = sscanf(argv[2], "%d", &coeff_field_characteristic); - if ((returnedScanValue == EOF) || (coeff_field_characteristic <= 0)) { - std::cerr << "Error: " << argv[2] << " is not correct\n"; - usage(argv[0]); - } + int coeff_field_characteristic = atoi(argv[2]); Filtration_value min_persistence = 0.0; returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); @@ -282,7 +275,7 @@ int main(int argc, char * const argv[]) { std::cout << "Simplex_tree dim: " << simplex_tree.dimension() << std::endl; // Compute the persistence diagram of the complex - Persistent_cohomology< ST, Field_Zp > pcoh(simplex_tree); + PCOH pcoh(simplex_tree); // initializes the coefficient field for homology pcoh.init_coefficients(coeff_field_characteristic); diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp index 75e4fafb..4c7a9aaf 100644 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ b/src/common/example/Delaunay_triangulation_off_rw.cpp @@ -10,12 +10,12 @@ // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instantiation of the +// The triangulation uses the default instantiation of the // TriangulationDataStructure template parameter void usage(char * const progName) { std::cerr << "Usage: " << progName << " inputFile.off outputFile.off" << std::endl; - exit(-1); // ----- >> + exit(-1); } int main(int argc, char **argv) { @@ -30,9 +30,9 @@ int main(int argc, char **argv) { // Check the read operation was correct if (!off_reader.is_valid()) { std::cerr << "Unable to read file " << offInputFile << std::endl; - exit(-1); // ----- >> + exit(-1); } - + // Retrieve the triangulation T* triangulation = off_reader.get_complex(); // Operations on triangulation @@ -47,8 +47,8 @@ int main(int argc, char **argv) { // Check the write operation was correct if (!off_writer.is_valid()) { std::cerr << "Unable to write file " << offOutputFile << std::endl; - exit(-1); // ----- >> + exit(-1); } - + return 0; -} \ No newline at end of file +} diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 529774f0..e623cf7b 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -44,8 +44,8 @@ class Delaunay_triangulation_off_visitor_reader { Complex* complex_; typedef typename Complex::Point Point; std::vector point_cloud; - public: + public: // TODO(VR) : Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. /** \brief Delaunay_triangulation_off_visitor_reader constructor @@ -153,7 +153,6 @@ class Delaunay_triangulation_off_visitor_reader { template class Delaunay_triangulation_off_reader { public: - /** \brief Reads the OFF file and constructs the Delaunay triangulation from the points * that are in the OFF file. * @@ -180,7 +179,6 @@ class Delaunay_triangulation_off_reader { std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << name_file << "\n"; } - } /** \brief Returns if the OFF file read operation was successful or not. @@ -201,7 +199,6 @@ class Delaunay_triangulation_off_reader { if (valid_) return complex_; return nullptr; - } private: @@ -285,7 +282,6 @@ class Delaunay_triangulation_off_writer { } for (auto cit = complex_ptr->finite_full_cells_begin(); cit != complex_ptr->finite_full_cells_end(); ++cit) { - std::vector vertexVector; stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { stream << points_to_vh[(*vit)->point()] - 1 << " "; @@ -299,7 +295,7 @@ class Delaunay_triangulation_off_writer { name_file << "\n"; } } - + /** \brief Returns if the OFF write operation was successful or not. * * @return OFF file write status. @@ -313,6 +309,6 @@ class Delaunay_triangulation_off_writer { bool valid_; }; -} // namespace Gudhi +} // namespace Gudhi #endif // DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index e45a7600..2420ae72 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -160,7 +160,7 @@ class Off_reader { iss >> num_face_vertices; std::vector face; face.assign(std::istream_iterator(iss), std::istream_iterator()); - //if (face.size() != (off_info_.dim + 1)) return false; + // if (face.size() != (off_info_.dim + 1)) return false; visitor.maximal_face(face); } return true; -- cgit v1.2.3 From 6996f2a16a1fdaa0d0faee1c559855fbea25b6c1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 16 Mar 2016 08:49:20 +0000 Subject: Compil issue git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1048 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4fcfc1498408eb98a12ed5d48e620dc38d4c442d --- src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp index f81951ce..01497c7c 100644 --- a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp @@ -132,7 +132,7 @@ int main(int argc, char * const argv[]) { int coeff_field_characteristic = atoi(argv[2]); Filtration_value min_persistence = 0.0; - returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); + int returnedScanValue = sscanf(argv[3], "%lf", &min_persistence); if ((returnedScanValue == EOF) || (min_persistence < -1.0)) { std::cerr << "Error: " << argv[3] << " is not correct\n"; usage(argv[0]); -- cgit v1.2.3 From 79e0db96e6cf4def4df5cad902c44abcaa179ff8 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 17 Mar 2016 10:13:28 +0000 Subject: Add in a comment an alternative version of prune_above_filtration Fix some cpplint/cppcheck defaults git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1051 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 9cfd8c7f7f9c82998a4c9d2d00f105ed16690208 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 46 ++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index ac5fbe79..b7b4b8b2 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -41,7 +41,6 @@ #include #endif -#include #include #include #include // for greater<> @@ -223,7 +222,7 @@ class Simplex_tree { * * 'value_type' is Simplex_handle. */ typedef typename Filtration_simplex_range::const_iterator Filtration_simplex_iterator; - + /* @} */ // end name range and iterator types /** \name Range and iterator methods * @{ */ @@ -455,7 +454,7 @@ class Simplex_tree { */ void assign_filtration(Simplex_handle sh, Filtration_value fv) { GUDHI_CHECK(sh == null_simplex(), - std::invalid_argument ("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex")); + std::invalid_argument("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex")); sh->second.assign_filtration(fv); } @@ -1119,7 +1118,7 @@ class Simplex_tree { os << filtration(sh) << " \n"; } } - + public: /** \brief Browse the simplex tree to ensure the filtration is not decreasing. * The simplex tree is browsed starting from the root until the leaf, and the filtration values are set with their @@ -1139,7 +1138,7 @@ class Simplex_tree { } return modified; } - + private: /** \brief Recursively Browse the simplex tree to ensure the filtration is not decreasing. * @param[in] sib Siblings to be parsed. @@ -1183,7 +1182,7 @@ class Simplex_tree { if (filtration_vect_.empty()) { initialize_filtration(); } - + std::vector> simplex_list_to_removed; // Loop in reverse mode until threshold is reached // Do not erase while looping, because removing is shifting data in a flat_map @@ -1205,6 +1204,37 @@ class Simplex_tree { initialize_filtration(); } + /* + // Another alternative for prune_above_filtration + // Seg fault in this state + void prune_above_filtration(Filtration_value filt) { + if (!Options::store_filtration || filt >= filtration()) return; + rec_prune_above_filtration(root(), filt); + set_filtration(filt); + } + + private: + void rec_prune_above_filtration(Siblings* sib, Filtration_value filt) { + auto&& list=sib->members(); + auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) { + if (simplex.second.filtration()<=filt) return false; + if (has_children(&simplex)) rec_delete(simplex.second.children()); + return true; + }); + + if (last == list.begin() && sib != root()) { + // Removing the whole siblings, parent becomes a leaf. + sib->oncles()->members()[sib->parent()].assign_children(sib->oncles()); + delete sib; + } else { + // Keeping some elements of siblings. Remove the others, and recurse in the remaining ones. + list.erase(last, list.end()); + for(auto&& simplex : list) + if(has_children(&simplex)) + rec_prune_above_filtration(simplex.second.children(), filt); + } + }*/ + /** \brief Remove a maximal simplex. * @param[in] sh Simplex handle on the maximal simplex to remove. * \pre Please check the simplex has no coface before removing it. @@ -1214,8 +1244,8 @@ class Simplex_tree { void remove_maximal_simplex(Simplex_handle sh) { // Guarantee the simplex has no children GUDHI_CHECK(has_children(sh), - std::invalid_argument ("Simplex_tree::remove_maximal_simplex - argument has children")); - + std::invalid_argument("Simplex_tree::remove_maximal_simplex - argument has children")); + // Simplex is a leaf, it means the child is the Siblings owning the leaf Siblings* child = sh->second.children(); -- cgit v1.2.3 From fa4810bea8d480f09d4cba5beba51805522cfdfe Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 17 Mar 2016 10:13:47 +0000 Subject: Fix cpplint/cppcheck git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1052 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d598999dec360fb4a80ca3e228128d889bfed3c7 --- src/Alpha_complex/doc/Intro_alpha_complex.h | 6 +++--- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index f55d7029..0dea2b16 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef INTRO_ALPHA_COMPLEX_H_ -#define INTRO_ALPHA_COMPLEX_H_ +#ifndef DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ +#define DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ // needs namespace for Doxygen to link on classes namespace Gudhi { @@ -165,4 +165,4 @@ namespace alphacomplex { } // namespace Gudhi -#endif // INTRO_ALPHA_COMPLEX_H_ +#endif // DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index eab66384..415aa032 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ -#define DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ +#ifndef ALPHA_COMPLEX_H_ +#define ALPHA_COMPLEX_H_ // to construct a simplex_tree from Delaunay_triangulation #include @@ -392,4 +392,4 @@ class Alpha_complex : public Simplex_tree<> { } // namespace Gudhi -#endif // DOC_ALPHA_COMPLEX_INTRO_ALPHA_COMPLEX_H_ +#endif // ALPHA_COMPLEX_H_ -- cgit v1.2.3 From 26e05a189a31846cd1aa97e055ff3595d9dddca1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 17 Mar 2016 13:44:28 +0000 Subject: Use post and exception doxygen tag instead of warnings everywhere. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1053 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 5e263835e662d66ef068c73d3efe71f72f90de10 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 5 +- src/Simplex_tree/include/gudhi/Simplex_tree.h | 79 ++++++++-------------- .../include/gudhi/Delaunay_triangulation_off_io.h | 19 ++---- 3 files changed, 37 insertions(+), 66 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 415aa032..2d2d77a5 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -150,8 +150,7 @@ class Alpha_complex : public Simplex_tree<> { * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. - * \warning In debug mode, the exception std::invalid_argument is thrown if an empty input point range is passed as - * argument. + * \exception std::invalid_argument In debug mode, if an empty input point range is passed as argument. */ template Alpha_complex(const InputPointRange& points, @@ -191,7 +190,7 @@ class Alpha_complex : public Simplex_tree<> { * * @param[in] vertex Vertex handle of the point to retrieve. * @return The point found. - * @warning Exception std::out_of_range is thrown in case vertex is not found. + * @exception std::out_of_range In case vertex is not found (cf. std::vector::at). */ Point_d get_point(Vertex_handle vertex) const { return vertex_handle_to_iterator_.at(vertex)->point(); diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index b7b4b8b2..7b55df11 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -47,7 +47,7 @@ #include #include // Inf #include -#include // for std::max +#include // for std::max namespace Gudhi { /** \defgroup simplex_tree Filtered Complexes @@ -141,7 +141,8 @@ class Simplex_tree { void assign_key(Simplex_key) { } Simplex_key key() const { assert(false); return -1; } }; - typedef typename std::conditional::type Key_simplex_base; + typedef typename std::conditional::type + Key_simplex_base; struct Filtration_simplex_base_real { Filtration_simplex_base_real() : filt_(0) {} @@ -450,7 +451,7 @@ class Simplex_tree { } /** \brief Sets the filtration value of a simplex. - * \warning In debug mode, the exception std::invalid_argument is thrown if sh is a null_simplex. + * \exception std::invalid_argument In debug mode, if sh is a null_simplex. */ void assign_filtration(Simplex_handle sh, Filtration_value fv) { GUDHI_CHECK(sh == null_simplex(), @@ -596,7 +597,19 @@ class Simplex_tree { private: /** \brief Inserts a simplex represented by a vector of vertex. - \warning the vector must be sorted by increasing vertex handle order */ + * @param[in] simplex vector of Vertex_handles, representing the vertices of the new simplex. The vector must be + * sorted by increasing vertex handle order. + * @param[in] filtration the filtration value assigned to the new simplex. + * @return If the new simplex is inserted successfully (i.e. it was not in the + * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned + * to the new simplex. + * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion + * fails and the simplex already in the complex has a filtration value strictly bigger than 'filtration', + * we assign this simplex with the new value 'filtration', and set the Simplex_handle field of the + * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to + * null_simplex. + * + */ std::pair insert_vertex_vector(const std::vector& simplex, Filtration_value filtration) { Siblings * curr_sib = &root_; @@ -629,7 +642,7 @@ class Simplex_tree { * * @param[in] simplex range of Vertex_handles, representing the vertices of the new simplex * @param[in] filtration the filtration value assigned to the new simplex. - * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the + * @return If the new simplex is inserted successfully (i.e. it was not in the * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned * to the new simplex. * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion @@ -668,7 +681,7 @@ class Simplex_tree { * * @param[in] Nsimplex range of Vertex_handles, representing the vertices of the new N-simplex * @param[in] filtration the filtration value assigned to the new N-simplex. - * The return type is a pair. If the new simplex is inserted successfully (i.e. it was not in the + * @return If the new simplex is inserted successfully (i.e. it was not in the * simplicial complex yet) the bool is set to true and the Simplex_handle is the handle assigned * to the new simplex. * If the insertion fails (the simplex is already there), the bool is set to false. If the insertion @@ -677,7 +690,7 @@ class Simplex_tree { * output pair to the Simplex_handle of the simplex. Otherwise, we set the Simplex_handle part to * null_simplex. */ - template> + template> std::pair insert_simplex_and_subfaces(const InputVertexRange& Nsimplex, Filtration_value filtration = 0) { auto first = std::begin(Nsimplex); @@ -1124,7 +1137,7 @@ class Simplex_tree { * The simplex tree is browsed starting from the root until the leaf, and the filtration values are set with their * parent value (increased), in case the values are decreasing. * @return The filtration modification information. - * \warning Some simplex tree functions require the filtration to be valid. `make_filtration_non_decreasing()` + * \post Some simplex tree functions require the filtration to be valid. `make_filtration_non_decreasing()` * function is not launching `initialize_filtration()` but returns the filtration modification information. If the * complex has changed , please call `initialize_filtration()` to recompute it. */ @@ -1154,7 +1167,7 @@ class Simplex_tree { Boundary_simplex_iterator max_border = std::max_element(std::begin(boundary), std::end(boundary), [](Simplex_handle sh1, Simplex_handle sh2) { return filtration(sh1) < filtration(sh2); - } ); + }); Filtration_value max_filt_border_value = filtration(*max_border); if (simplex.second.filtration() < max_filt_border_value) { @@ -1173,7 +1186,7 @@ class Simplex_tree { public: /** \brief Prune above filtration value given as parameter. * @param[in] filtration Maximum threshold value. - * \warning The filtration must be valid. If the filtration has not been initialized yet, the method initializes it + * \post The filtration must be valid. If the filtration has not been initialized yet, the method initializes it * (i.e. order the simplices). If the complex has changed since the last time the filtration was initialized, please * call `initialize_filtration()` to recompute it. */ @@ -1182,7 +1195,7 @@ class Simplex_tree { if (filtration_vect_.empty()) { initialize_filtration(); } - + std::vector> simplex_list_to_removed; // Loop in reverse mode until threshold is reached // Do not erase while looping, because removing is shifting data in a flat_map @@ -1234,18 +1247,18 @@ class Simplex_tree { rec_prune_above_filtration(simplex.second.children(), filt); } }*/ - + /** \brief Remove a maximal simplex. * @param[in] sh Simplex handle on the maximal simplex to remove. * \pre Please check the simplex has no coface before removing it. - * \warning In debug mode, the exception std::invalid_argument is thrown if sh has children. - * \warning Be aware that removing is shifting data in a flat_map (initialize_filtration to be done). + * \exception std::invalid_argument In debug mode, if sh has children. + * \post Be aware that removing is shifting data in a flat_map (initialize_filtration to be done). */ void remove_maximal_simplex(Simplex_handle sh) { // Guarantee the simplex has no children GUDHI_CHECK(has_children(sh), std::invalid_argument("Simplex_tree::remove_maximal_simplex - argument has children")); - + // Simplex is a leaf, it means the child is the Siblings owning the leaf Siblings* child = sh->second.children(); @@ -1259,42 +1272,6 @@ class Simplex_tree { delete child; } } -/***************************************************************************************************************/ - public: - /** \brief Prints the simplex_tree hierarchically. - * Since it prints the vertices recursively, one can watch its tree shape. - */ - void debug_tree() { - std::cout << "{" << &root_ << "} -------------------------------------------------------------------" << std::endl; - for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) { - std::cout << sh->first << " [" << sh->second.filtration() << "] "; - if (has_children(sh)) { - rec_debug_tree(sh->second.children()); - } else { - std::cout << " {- " << sh->second.children() << "} "; - } - std::cout << std::endl; - } - std::cout << "--------------------------------------------------------------------------------------" << std::endl; - } - - - /** \brief Recursively prints the simplex_tree, using depth first search. */ - private: - void rec_debug_tree(Siblings * sib) { - std::cout << " {" << sib << "} ("; - for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { - std::cout << " " << sh->first << " [" << sh->second.filtration() << "] "; - if (has_children(sh)) { - rec_debug_tree(sh->second.children()); - } else { - std::cout << " {- " << sh->second.children() << "} "; - } - } - std::cout << ")"; - } - -/*****************************************************************************************************************/ private: Vertex_handle null_vertex_; diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index e623cf7b..7bf5569e 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -98,7 +98,6 @@ class Delaunay_triangulation_off_visitor_reader { std::cout << std::endl; #endif // DEBUG_TRACES // Fill the point cloud - // VR: complex_->insert(Point(point.size(), point.begin(), point.end())); point_cloud.push_back(Point(point.size(), point.begin(), point.end())); } @@ -116,9 +115,7 @@ class Delaunay_triangulation_off_visitor_reader { /** \brief Returns the constructed Delaunay triangulation. * - * @return A pointer on the Delaunay triangulation. - * - * @warning The returned pointer can be nullptr. + * @return A pointer on the Delaunay triangulation. Default value is nullptr. */ Complex* get_complex() const { return complex_; @@ -157,8 +154,8 @@ class Delaunay_triangulation_off_reader { * that are in the OFF file. * * @param[in] name_file OFF file to read. - * - * @warning Check with is_valid() function to see if read operation was successful. + * + * \post Check with is_valid() function to see if read operation was successful. */ Delaunay_triangulation_off_reader(const std::string & name_file) : valid_(false) { @@ -191,9 +188,7 @@ class Delaunay_triangulation_off_reader { /** \brief Returns the constructed Delaunay triangulation. * - * @return A pointer on the Delaunay triangulation. - * - * @warning The returned pointer can be nullptr. + * @return A pointer on the Delaunay triangulation. Default value is nullptr. */ Complex* get_complex() const { if (valid_) @@ -242,12 +237,12 @@ class Delaunay_triangulation_off_writer { public: typedef typename Complex::Point Point; - /** \brief Writes the OFF file from the Delaunay triangulation + /** \brief Writes the OFF file from the Delaunay triangulation. * * @param[in] name_file OFF file to write. * @param[in] complex_ptr pointer on a Delaunay triangulation. - * - * @warning Check with is_valid() function to see if write operation was successful. + * + * \post Check with is_valid() function to see if write operation was successful. */ Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) : valid_(false) { -- cgit v1.2.3 From 071c0495ae1ed556f17120ca7c249106f5e34f9b Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 22 Mar 2016 09:32:32 +0000 Subject: Delaunay triangulation is point dimension. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1066 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 672164328b3b1ac104811fb2fd79a3771c92d60e --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 2d2d77a5..0b6875af 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -166,8 +166,8 @@ class Alpha_complex : public Simplex_tree<> { // point_dimension function initialization Point_Dimension point_dimension = kernel_.point_dimension_d_object(); - // Delaunay triangulation is point dimension minus one. - triangulation_ = new Delaunay_triangulation(point_dimension(*first) - 1); + // Delaunay triangulation is point dimension. + triangulation_ = new Delaunay_triangulation(point_dimension(*first)); size_type inserted = triangulation_->insert(first, last); if (inserted != (last -first)) { -- cgit v1.2.3 From ce097f4fd26faf1b52d7a50769f809feeab60c3d Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 22 Mar 2016 12:55:19 +0000 Subject: Add a comment to say Alpha complex takes the ownership of the pointer on the Delaunay Triangulation. Add public typedef Delaunay_triangulation, Point_d and Geom_traits git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1067 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1137a9912ebac38a14d680921e62cd36e0068153 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 0b6875af..7c64b53e 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -34,6 +34,7 @@ #include // isnan, fmax #include +#include #include #include @@ -62,13 +63,24 @@ namespace alphacomplex { * * The complex is a template class requiring an Epick_d dD Geometry Kernel - * \cite cgal:s-gkd-15b from CGAL as template. + * \cite cgal:s-gkd-15b from CGAL as template, default value is CGAL::Epick_d + * < + * CGAL::Dynamic_dimension_tag > * * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex. * */ -template +template> class Alpha_complex : public Simplex_tree<> { + public: + /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ + typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; + /** \brief A point in Euclidean space.*/ + typedef typename Kernel::Point_d Point_d; + /** \brief Geometric traits class that provides the geometric types and predicates needed by Delaunay + * triangulations.*/ + typedef Kernel Geom_traits; private: // From Simplex_tree // Type required to insert into a simplex_tree (with or without subfaces). @@ -77,15 +89,10 @@ class Alpha_complex : public Simplex_tree<> { // Simplex_result is the type returned from simplex_tree insert function. typedef typename std::pair Simplex_result; - // Delaunay_triangulation type required to create an alpha-complex. - typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; - typedef typename Kernel::Compute_squared_radius_d Squared_Radius; typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; typedef typename Kernel::Point_dimension_d Point_Dimension; - typedef typename Kernel::Point_d Point_d; - // Type required to compute squared radius, or side of bounded sphere on a vector of points. typedef typename std::vector Vector_of_CGAL_points; @@ -135,6 +142,8 @@ class Alpha_complex : public Simplex_tree<> { * @param[in] triangulation_ptr Pointer on a * CGAL::Delaunay_triangulation \cite cgal:hdj-t-15b. + * Alpha_complex takes ownership of the Delaunay_triangulation object, which must have been allocated using operator + * new. * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. */ Alpha_complex(Delaunay_triangulation* triangulation_ptr, -- cgit v1.2.3 From 5276b0a9e344ed0bb4fdb8b079f2ce86649d12a4 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 22 Mar 2016 16:07:08 +0000 Subject: GUDHI_CHECK was not intuitive. Reverse GUDHI_CHECK calls. No exception when no point is given in contrction. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1070 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: bf6a08d48b5b29a5b24bf5107116e399dfc0a6bc --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 4 ---- src/Simplex_tree/include/gudhi/Simplex_tree.h | 4 ++-- src/common/include/gudhi/Debug_utils.h | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 7c64b53e..330b3b34 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -159,7 +159,6 @@ class Alpha_complex : public Simplex_tree<> { * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. - * \exception std::invalid_argument In debug mode, if an empty input point range is passed as argument. */ template Alpha_complex(const InputPointRange& points, @@ -168,9 +167,6 @@ class Alpha_complex : public Simplex_tree<> { auto first = std::begin(points); auto last = std::end(points); - GUDHI_CHECK((first == last), - std::invalid_argument("Alpha_complex::Alpha_complex(InputPointRange) - Empty input point range")); - if (first != last) { // point_dimension function initialization Point_Dimension point_dimension = kernel_.point_dimension_d_object(); diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 7b55df11..aa8f059e 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -454,7 +454,7 @@ class Simplex_tree { * \exception std::invalid_argument In debug mode, if sh is a null_simplex. */ void assign_filtration(Simplex_handle sh, Filtration_value fv) { - GUDHI_CHECK(sh == null_simplex(), + GUDHI_CHECK(sh != null_simplex(), std::invalid_argument("Simplex_tree::assign_filtration - cannot assign filtration on null_simplex")); sh->second.assign_filtration(fv); } @@ -1256,7 +1256,7 @@ class Simplex_tree { */ void remove_maximal_simplex(Simplex_handle sh) { // Guarantee the simplex has no children - GUDHI_CHECK(has_children(sh), + GUDHI_CHECK(!has_children(sh), std::invalid_argument("Simplex_tree::remove_maximal_simplex - argument has children")); // Simplex is a leaf, it means the child is the Siblings owning the leaf diff --git a/src/common/include/gudhi/Debug_utils.h b/src/common/include/gudhi/Debug_utils.h index 48d61fef..7573a9db 100644 --- a/src/common/include/gudhi/Debug_utils.h +++ b/src/common/include/gudhi/Debug_utils.h @@ -29,12 +29,12 @@ #define GUDHI_DEBUG #endif -// GUDHI_CHECK throw an exception on condition in debug mode, but does nothing in release mode +// GUDHI_CHECK throw an exception if expression is false in debug mode, but does nothing in release mode // Could assert in release mode, but cmake sets NDEBUG (for "NO DEBUG") in this mode, means assert does nothing. #ifdef GUDHI_DEBUG - #define GUDHI_CHECK(cond, excpt) if (cond) throw excpt + #define GUDHI_CHECK(expression, excpt) if ((expression) == 0) throw excpt #else - #define GUDHI_CHECK(cond, excpt) (void) 0 + #define GUDHI_CHECK(expression, excpt) (void) 0 #endif #define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl -- cgit v1.2.3 From bbf22c32a893c9875f6ea0e217d0bf6cf77c3257 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 23 Mar 2016 08:09:39 +0000 Subject: prune_above_filtration returns filtration vector modification information instead of calling initialize_filtration() git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1071 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6fdc1797ac6e7b452abe150643f0ec9578c3bbab --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 10 ++- src/Simplex_tree/include/gudhi/Simplex_tree.h | 16 ++--- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 71 +++++++++++++++++----- 4 files changed, 77 insertions(+), 26 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 330b3b34..33830175 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -230,8 +230,6 @@ class Alpha_complex : public Simplex_tree<> { } set_dimension(triangulation_->maximal_dimension()); - // set_filtration to +inf for prune_above_filtration to be done (if necessary) - set_filtration(std::numeric_limits::infinity()); // -------------------------------------------------------------------------------------------- // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa @@ -323,7 +321,9 @@ class Alpha_complex : public Simplex_tree<> { initialize_filtration(); } // Remove all simplices that have a filtration value greater than max_alpha_square - prune_above_filtration(max_alpha_square); + if (prune_above_filtration(max_alpha_square)) { + initialize_filtration(); + } // -------------------------------------------------------------------------------------------- } diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 2912019d..315582d1 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -78,7 +78,8 @@ BOOST_AUTO_TEST_CASE(ALPHA_DOC_OFF_file_filtered) { std::cout << "========== OFF FILE NAME = " << off_file_name << " - alpha²=" << max_alpha_square_value << "==========" << std::endl; - Gudhi::alphacomplex::Alpha_complex alpha_complex_from_file(off_file_name, max_alpha_square_value); + // Use of the default dynamic kernel + Gudhi::alphacomplex::Alpha_complex<> alpha_complex_from_file(off_file_name, max_alpha_square_value); const int DIMENSION = 2; std::cout << "alpha_complex_from_file.dimension()=" << alpha_complex_from_file.dimension() << std::endl; @@ -200,7 +201,12 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { BOOST_CHECK_THROW (alpha_complex_from_points.get_point(1234), std::out_of_range); // Test after prune_above_filtration - alpha_complex_from_points.prune_above_filtration(0.6); + bool modified = alpha_complex_from_points.prune_above_filtration(0.6); + if (modified) { + alpha_complex_from_points.initialize_filtration(); + } + BOOST_CHECK(modified); + // Another way to check num_simplices std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; num_simplices = 0; diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index aa8f059e..af298f33 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1186,11 +1186,14 @@ class Simplex_tree { public: /** \brief Prune above filtration value given as parameter. * @param[in] filtration Maximum threshold value. - * \post The filtration must be valid. If the filtration has not been initialized yet, the method initializes it - * (i.e. order the simplices). If the complex has changed since the last time the filtration was initialized, please - * call `initialize_filtration()` to recompute it. + * @return The filtration modification information. + * \pre The filtration must be valid. If the filtration has not been initialized yet, the method initializes it + * (i.e. order the simplices). + * \post Some simplex tree functions require the filtration to be valid. `prune_above_filtration()` + * function is not launching `initialize_filtration()` but returns the filtration modification information. If the + * complex has changed , please call `initialize_filtration()` to recompute it. */ - void prune_above_filtration(Filtration_value filtration) { + bool prune_above_filtration(Filtration_value filtration) { // Initialize filtration_vect_ if required if (filtration_vect_.empty()) { initialize_filtration(); @@ -1213,13 +1216,12 @@ class Simplex_tree { remove_maximal_simplex(sh); } // Re-initialize filtration_vect_ if dta were removed, because removing is shifting data in a flat_map - if (simplex_list_to_removed.size() > 0) - initialize_filtration(); + return (simplex_list_to_removed.size() > 0); } /* // Another alternative for prune_above_filtration - // Seg fault in this state + // initialize_filtration is not called. UT are not passed. void prune_above_filtration(Filtration_value filt) { if (!Options::store_filtration || filt >= filtration()) return; rec_prune_above_filtration(root(), filt); diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index b8c1cc35..b1bb23b1 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -1012,20 +1012,30 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { // o // 5 + bool simplex_is_changed = false; // Check the no action cases // greater than initial filtration value - st.prune_above_filtration(10.0); + simplex_is_changed = st.prune_above_filtration(10.0); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_complete); + BOOST_CHECK(!simplex_is_changed); // equal to initial filtration value - st.prune_above_filtration(6.0); + simplex_is_changed = st.prune_above_filtration(6.0); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_complete); + BOOST_CHECK(!simplex_is_changed); // lower than initial filtration value, but still greater than the maximum filtration value - st.prune_above_filtration(5.0); + simplex_is_changed = st.prune_above_filtration(5.0); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_complete); + BOOST_CHECK(!simplex_is_changed); // Display the Simplex_tree std::cout << "The complex contains " << st.num_simplices() << " simplices"; - std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << " - dimension " << st.dimension() << std::endl; std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; for (auto f_simplex : st.filtration_simplex_range()) { std::cout << " " << "[" << st.filtration(f_simplex) << "] "; @@ -1036,35 +1046,46 @@ BOOST_AUTO_TEST_CASE(prune_above_filtration) { } // Check the pruned cases - // Set the st_pruned filtration for operator== - st.prune_above_filtration(2.5); + simplex_is_changed = st.prune_above_filtration(2.5); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_pruned); + BOOST_CHECK(simplex_is_changed); // Display the Simplex_tree std::cout << "The complex pruned at 2.5 contains " << st.num_simplices() << " simplices"; - std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << " - dimension " << st.dimension() << std::endl; - st.prune_above_filtration(2.0); + simplex_is_changed = st.prune_above_filtration(2.0); + if (simplex_is_changed) + st.initialize_filtration(); std::cout << "The complex pruned at 2.0 contains " << st.num_simplices() << " simplices"; - std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << " - dimension " << st.dimension() << std::endl; BOOST_CHECK(st == st_pruned); + BOOST_CHECK(!simplex_is_changed); typeST st_empty; // FIXME st_empty.set_dimension(3); - st.prune_above_filtration(0.0); + simplex_is_changed = st.prune_above_filtration(0.0); + if (simplex_is_changed) + st.initialize_filtration(); // Display the Simplex_tree std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices"; - std::cout << " - dimension " << st.dimension() << " - filtration " << st.filtration() << std::endl; + std::cout << " - dimension " << st.dimension() << std::endl; BOOST_CHECK(st == st_empty); + BOOST_CHECK(simplex_is_changed); // Test case to the limit - st.prune_above_filtration(-1.0); + simplex_is_changed = st.prune_above_filtration(-1.0); + if (simplex_is_changed) + st.initialize_filtration(); BOOST_CHECK(st == st_empty); + BOOST_CHECK(!simplex_is_changed); } BOOST_AUTO_TEST_CASE(mini_prune_above_filtration) { @@ -1096,11 +1117,33 @@ BOOST_AUTO_TEST_CASE(mini_prune_above_filtration) { std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; BOOST_CHECK(st.num_simplices() == 27); + // Test case to the limit - With these options, there is no filtration, which means filtration is 0 + bool simplex_is_changed = st.prune_above_filtration(1.0); + if (simplex_is_changed) + st.initialize_filtration(); + // Display the Simplex_tree + std::cout << "The complex pruned at 1.0 contains " << st.num_simplices() << " simplices" << std::endl; + BOOST_CHECK(!simplex_is_changed); + BOOST_CHECK(st.num_simplices() == 27); + + simplex_is_changed = st.prune_above_filtration(0.0); + if (simplex_is_changed) + st.initialize_filtration(); + // Display the Simplex_tree + std::cout << "The complex pruned at 0.0 contains " << st.num_simplices() << " simplices" << std::endl; + BOOST_CHECK(!simplex_is_changed); + BOOST_CHECK(st.num_simplices() == 27); + // Test case to the limit - st.prune_above_filtration(-1.0); + simplex_is_changed = st.prune_above_filtration(-1.0); + if (simplex_is_changed) + st.initialize_filtration(); + // Display the Simplex_tree + std::cout << "The complex pruned at -1.0 contains " << st.num_simplices() << " simplices" << std::endl; + BOOST_CHECK(simplex_is_changed); + BOOST_CHECK(st.num_simplices() == 0); // Display the Simplex_tree std::cout << "The complex contains " << st.num_simplices() << " simplices" << std::endl; - BOOST_CHECK(st.num_simplices() == 0); } \ No newline at end of file -- cgit v1.2.3 From 73d8be19b7834f500e38f7304fd01e0e641ef018 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 23 Mar 2016 23:04:43 +0000 Subject: An alternative to prune_above_filtration in comment. Fix UT for alternative git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1072 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1958a5ee06c339d8cd8cdaae92358d2fff445a7a --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index af298f33..1bad8d7d 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1219,37 +1219,39 @@ class Simplex_tree { return (simplex_list_to_removed.size() > 0); } - /* + // Another alternative for prune_above_filtration - // initialize_filtration is not called. UT are not passed. - void prune_above_filtration(Filtration_value filt) { - if (!Options::store_filtration || filt >= filtration()) return; - rec_prune_above_filtration(root(), filt); - set_filtration(filt); + // UT are passed and performance are similar. + /*bool prune_above_filtration(Filtration_value filt) { + return rec_prune_above_filtration(root(), filt); } private: - void rec_prune_above_filtration(Siblings* sib, Filtration_value filt) { + bool rec_prune_above_filtration(Siblings* sib, Filtration_value filt) { auto&& list=sib->members(); auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) { - if (simplex.second.filtration()<=filt) return false; - if (has_children(&simplex)) rec_delete(simplex.second.children()); - return true; + if (simplex.second.filtration()<=filt) return false; + if (has_children(&simplex)) rec_delete(simplex.second.children()); + return true; }); - + + bool modified = (last != list.end()); if (last == list.begin() && sib != root()) { // Removing the whole siblings, parent becomes a leaf. sib->oncles()->members()[sib->parent()].assign_children(sib->oncles()); delete sib; + return true; } else { // Keeping some elements of siblings. Remove the others, and recurse in the remaining ones. list.erase(last, list.end()); for(auto&& simplex : list) if(has_children(&simplex)) - rec_prune_above_filtration(simplex.second.children(), filt); + modified |= rec_prune_above_filtration(simplex.second.children(), filt); } + return modified; }*/ + public: /** \brief Remove a maximal simplex. * @param[in] sh Simplex handle on the maximal simplex to remove. * \pre Please check the simplex has no coface before removing it. -- cgit v1.2.3 From eefb9628f71cd74127cfc9ffa4f8db0803d82ad9 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 24 Mar 2016 12:40:15 +0000 Subject: prune_above_filtration version that is no more using filtration vector. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1073 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 95dca83fa459abd902624bf2a5f631925e4cf9b0 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 8 +++--- src/Simplex_tree/include/gudhi/Simplex_tree.h | 35 ++----------------------- 2 files changed, 6 insertions(+), 37 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 33830175..2b27a459 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -317,11 +317,11 @@ class Alpha_complex : public Simplex_tree<> { // -------------------------------------------------------------------------------------------- // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension - if (make_filtration_non_decreasing()) { - initialize_filtration(); - } + bool modified_filt = make_filtration_non_decreasing(); // Remove all simplices that have a filtration value greater than max_alpha_square - if (prune_above_filtration(max_alpha_square)) { + // Remark: prune_above_filtration does not require initialize_filtration to be done before. + modified_filt |= prune_above_filtration(max_alpha_square); + if (modified_filt) { initialize_filtration(); } // -------------------------------------------------------------------------------------------- diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 1bad8d7d..f5bc0a11 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1187,42 +1187,11 @@ class Simplex_tree { /** \brief Prune above filtration value given as parameter. * @param[in] filtration Maximum threshold value. * @return The filtration modification information. - * \pre The filtration must be valid. If the filtration has not been initialized yet, the method initializes it - * (i.e. order the simplices). * \post Some simplex tree functions require the filtration to be valid. `prune_above_filtration()` * function is not launching `initialize_filtration()` but returns the filtration modification information. If the * complex has changed , please call `initialize_filtration()` to recompute it. */ - bool prune_above_filtration(Filtration_value filtration) { - // Initialize filtration_vect_ if required - if (filtration_vect_.empty()) { - initialize_filtration(); - } - - std::vector> simplex_list_to_removed; - // Loop in reverse mode until threshold is reached - // Do not erase while looping, because removing is shifting data in a flat_map - for (auto f_simplex = filtration_vect_.rbegin(); - (f_simplex != filtration_vect_.rend()) && ((*f_simplex)->second.filtration() > filtration); - f_simplex++) { - std::vector simplex_to_remove; - for (auto vertex : simplex_vertex_range(*f_simplex)) - simplex_to_remove.insert(simplex_to_remove.begin(), vertex); - simplex_list_to_removed.push_back(simplex_to_remove); - } - for (auto simplex_to_remove : simplex_list_to_removed) { - Simplex_handle sh = find_simplex(simplex_to_remove); - if (sh != null_simplex()) - remove_maximal_simplex(sh); - } - // Re-initialize filtration_vect_ if dta were removed, because removing is shifting data in a flat_map - return (simplex_list_to_removed.size() > 0); - } - - - // Another alternative for prune_above_filtration - // UT are passed and performance are similar. - /*bool prune_above_filtration(Filtration_value filt) { + bool prune_above_filtration(Filtration_value filt) { return rec_prune_above_filtration(root(), filt); } @@ -1249,7 +1218,7 @@ class Simplex_tree { modified |= rec_prune_above_filtration(simplex.second.children(), filt); } return modified; - }*/ + } public: /** \brief Remove a maximal simplex. -- cgit v1.2.3 From fde42a187d4a1a7abb4eaa3239cd884f8731b08a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Fri, 1 Apr 2016 08:50:48 +0000 Subject: cpplint/cppcheck fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1091 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 1c274cd8c8a3c76fe35f96c7186bcbf3d8bee3e8 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 14 +++++++------- src/common/include/gudhi/reader_utils.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index f5bc0a11..afc7d613 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -955,7 +955,7 @@ class Simplex_tree { bool operator()(const Simplex_handle sh1, const Simplex_handle sh2) const { // Not using st_->filtration(sh1) because it uselessly tests for null_simplex. if (sh1->second.filtration() != sh2->second.filtration()) { - return sh1->second.filtration() < sh2->second.filtration(); + return sh1->second.filtration() < sh2->second.filtration(); } // is sh1 a proper subface of sh2 return st_->reverse_lexicographic_order(sh1, sh2); @@ -1194,16 +1194,16 @@ class Simplex_tree { bool prune_above_filtration(Filtration_value filt) { return rec_prune_above_filtration(root(), filt); } - + private: bool rec_prune_above_filtration(Siblings* sib, Filtration_value filt) { - auto&& list=sib->members(); + auto&& list = sib->members(); auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) { - if (simplex.second.filtration()<=filt) return false; + if (simplex.second.filtration() <= filt) return false; if (has_children(&simplex)) rec_delete(simplex.second.children()); return true; }); - + bool modified = (last != list.end()); if (last == list.begin() && sib != root()) { // Removing the whole siblings, parent becomes a leaf. @@ -1213,8 +1213,8 @@ class Simplex_tree { } else { // Keeping some elements of siblings. Remove the others, and recurse in the remaining ones. list.erase(last, list.end()); - for(auto&& simplex : list) - if(has_children(&simplex)) + for (auto&& simplex : list) + if (has_children(&simplex)) modified |= rec_prune_above_filtration(simplex.second.children(), filt); } return modified; diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index da2c2c36..899f9df6 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -161,7 +161,7 @@ bool read_simplex(std::istream & in_, std::vector< Vertex_handle > & simplex, Fi simplex.push_back(v); } in_ >> fil; - in_.ignore((std::numeric_limits::max)(), '\n'); // ignore until the carriage return + in_.ignore((std::numeric_limits::max)(), '\n'); // ignore until the carriage return return true; } -- cgit v1.2.3 From 3d592b82f837219ee9ecd8e33120563edb4e76ab Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 06:19:05 +0000 Subject: Last modif git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1097 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: d02c8b6bf27616ef515464a35e48b7871a69f9a8 --- .../include/gudhi/Delaunay_triangulation_off_io.h | 47 ++++++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h index 7bf5569e..50be9a59 100644 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ b/src/common/include/gudhi/Delaunay_triangulation_off_io.h @@ -27,6 +27,10 @@ #include #include +#include + +#include + #include "gudhi/Off_reader.h" namespace Gudhi { @@ -42,8 +46,9 @@ template class Delaunay_triangulation_off_visitor_reader { private: Complex* complex_; - typedef typename Complex::Point Point; - std::vector point_cloud; + typedef typename Complex::Point_d Point_d; + typedef typename Complex::size_type size_type; + std::vector point_cloud; public: // TODO(VR) : Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. @@ -98,7 +103,7 @@ class Delaunay_triangulation_off_visitor_reader { std::cout << std::endl; #endif // DEBUG_TRACES // Fill the point cloud - point_cloud.push_back(Point(point.size(), point.begin(), point.end())); + point_cloud.push_back(Point_d(point.size(), point.begin(), point.end())); } // Off_reader visitor maximal_face implementation - not used @@ -110,7 +115,11 @@ class Delaunay_triangulation_off_visitor_reader { void done() { // It is advised to insert all the points at a time in a Delaunay Triangulation because points are sorted at the // beginning of the insertion - complex_->insert(point_cloud.begin(), point_cloud.end()); + size_type inserted = complex_->insert(point_cloud.begin(), point_cloud.end()); + if (inserted != (point_cloud.end() -point_cloud.begin())) { + std::cerr << "Delaunay_triangulation_off_visitor_reader::done - insertion failed " << inserted << " != " << + (point_cloud.end() -point_cloud.begin()) << "\n"; + } } /** \brief Returns the constructed Delaunay triangulation. @@ -120,6 +129,36 @@ class Delaunay_triangulation_off_visitor_reader { Complex* get_complex() const { return complex_; } + + private: + template + size_type insert_with_index(const PointRangeIterator& first, const PointRangeIterator& last) { + size_type vertices_before_insertion = complex_->number_of_vertices(); + std::vector points(first, last); + + std::vector indices; + indices.reserve(points.size()); + + // Creates a vector {0, 1, ..., N-1} + std::copy(boost::counting_iterator(0), boost::counting_iterator(points.size()), + std::back_inserter(indices)); + + // Sort indices considering CGAL spatial sort + typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; + spatial_sort(indices.begin(),indices.end(),Search_traits_d(&(points[0]))); + + typename Delaunay_triangulation::Full_cell_handle hint; + for (typename std::vector::const_iterator it = indices.begin(), end = indices.end(); + it != end; ++it) { + typename Delaunay_triangulation::Vertex_handle pos = complex_->insert(points[*it], hint); + // Save index value as data to retrieve it after insertion + pos->data() = *it; + hint = pos->full_cell(); + } + + return (complex_->number_of_vertices() - vertices_before_insertion); + } + }; /** -- cgit v1.2.3 From fb22bc9ca84f5b3c55a598bf0c903a73c117e783 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 11:08:33 +0000 Subject: Replace Delaunay_triangulation_off_io.h and Delaunay_triangulation_off_rw.cpp with Points_off_io.h and CGAL_points_off_reader.cpp Adapt UT and examples for this Adapt Alpha complex for it Alpha complex is now inserting points in a faster way (after a spatial_sort). Remove Alpha complex construction from a pointer on Delaunay triangulation (no more needed). Adapt documentation to all these modifications Forbid copy/move constructor/assignment operator on Alpha complex git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1098 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 08a673b66451b5cb03fbdf482d696d93b35d220f --- src/Alpha_complex/doc/Intro_alpha_complex.h | 6 +- src/Alpha_complex/doc/alpha_complex_doc.ipe | 136 ++++-- src/Alpha_complex/doc/alpha_complex_doc.png | Bin 25150 -> 25554 bytes src/Alpha_complex/doc/alpha_complex_doc_420.ipe | 514 +++++++++++++++++++++ src/Alpha_complex/doc/alpha_complex_doc_420.png | Bin 0 -> 80794 bytes src/Alpha_complex/doc/alpha_complex_doc_421.ipe | 514 --------------------- src/Alpha_complex/doc/alpha_complex_doc_421.png | Bin 100798 -> 0 bytes .../doc/alpha_complex_representation.ipe | 16 +- .../doc/alpha_complex_representation.png | Bin 14628 -> 14606 bytes .../example/Alpha_complex_from_off.cpp | 8 +- .../example/Alpha_complex_from_points.cpp | 15 +- .../example/alphaoffreader_for_doc_32.txt | 26 +- .../example/alphaoffreader_for_doc_60.txt | 36 +- src/Alpha_complex/include/gudhi/Alpha_complex.h | 109 +++-- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 2 - .../example/alpha_complex_persistence.cpp | 3 +- src/common/example/CGAL_points_off_reader.cpp | 43 ++ src/common/example/CMakeLists.txt | 12 +- .../example/Delaunay_triangulation_off_rw.cpp | 54 --- src/common/example/cgaloffreader_result.txt | 7 + .../example/dtoffrw_alphashapedoc_result.off | 15 - .../example/dtoffrw_alphashapedoc_result.txt | 2 - .../include/gudhi/Delaunay_triangulation_off_io.h | 348 -------------- src/common/include/gudhi/Points_off_io.h | 178 +++++++ src/common/test/CMakeLists.txt | 14 +- src/common/test/dtoffrw_alphashapedoc_result.off | 22 +- src/common/test/dtoffrw_unit_test.cpp | 90 ---- src/common/test/points_off_reader_unit_test.cpp | 78 ++++ 28 files changed, 1044 insertions(+), 1204 deletions(-) create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_420.ipe create mode 100644 src/Alpha_complex/doc/alpha_complex_doc_420.png delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_421.ipe delete mode 100644 src/Alpha_complex/doc/alpha_complex_doc_421.png create mode 100644 src/common/example/CGAL_points_off_reader.cpp delete mode 100644 src/common/example/Delaunay_triangulation_off_rw.cpp create mode 100644 src/common/example/cgaloffreader_result.txt delete mode 100644 src/common/example/dtoffrw_alphashapedoc_result.off delete mode 100644 src/common/example/dtoffrw_alphashapedoc_result.txt delete mode 100644 src/common/include/gudhi/Delaunay_triangulation_off_io.h create mode 100644 src/common/include/gudhi/Points_off_io.h delete mode 100644 src/common/test/dtoffrw_unit_test.cpp create mode 100644 src/common/test/points_off_reader_unit_test.cpp diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 0dea2b16..9d0dcefa 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -112,14 +112,14 @@ namespace alphacomplex { * * \subsubsection dimension2 Dimension 2 * - * From the example above, it means the algorithm looks into each triangle ([4,2,1], [2,4,6], [4,5,6], ...), + * From the example above, it means the algorithm looks into each triangle ([0,1,2], [0,2,4], [1,2,3], ...), * computes the filtration value of the triangle, and then propagates the filtration value as described * here : - * \image html "alpha_complex_doc_421.png" "Filtration value propagation example" + * \image html "alpha_complex_doc_420.png" "Filtration value propagation example" * * \subsubsection dimension1 Dimension 1 * - * Then, the algorithm looks into each edge ([1,2], [4,2], [4,1], ...), + * Then, the algorithm looks into each edge ([0,1], [0,2], [1,2], ...), * computes the filtration value of the edge (in this case, propagation will have no effect). * * \subsubsection dimension0 Dimension 0 diff --git a/src/Alpha_complex/doc/alpha_complex_doc.ipe b/src/Alpha_complex/doc/alpha_complex_doc.ipe index 99bd05af..baf0d26a 100644 --- a/src/Alpha_complex/doc/alpha_complex_doc.ipe +++ b/src/Alpha_complex/doc/alpha_complex_doc.ipe @@ -1,7 +1,7 @@ - + @@ -253,13 +253,13 @@ h 320 580 l Delaunay triangulation -2 -6 -4 -5 -1 -3 -0 +0 +1 +2 +3 +4 +5 +6 280 660 m 300 710 l @@ -314,7 +314,7 @@ h -3 +2 300 688 m 300 676 l @@ -322,15 +322,14 @@ h 312 688 l h - +2 + 300 688 m 300 676 l 312 676 l 312 688 l h -4 -3 300 688 m 300 676 l @@ -338,6 +337,8 @@ h 312 688 l h +4 +1 300 688 m 300 676 l @@ -345,39 +346,15 @@ h 312 688 l h -4 -1 - -300 688 m -300 676 l -312 676 l -312 688 l -h - - -300 688 m -300 676 l -312 676 l -312 688 l -h - -5 - + 300 688 m 300 676 l 312 676 l 312 688 l h -5 +4 3 - -300 688 m -300 676 l -312 676 l -312 688 l -h - 300 688 m 300 676 l @@ -385,7 +362,6 @@ h 312 688 l h -4 2 300 688 m @@ -401,7 +377,7 @@ h 312 688 l h -4 +3 6 300 688 m @@ -418,14 +394,14 @@ h 312 688 l h - + 300 688 m 300 676 l 312 676 l 312 688 l h -6 +6 6 300 688 m @@ -442,22 +418,22 @@ h 312 688 l h - + 300 688 m 300 676 l 312 676 l 312 688 l h -6 - +6 + 300 688 m 300 676 l 312 676 l 312 688 l h -6 +6 292 716 m 292 728 l @@ -514,11 +490,11 @@ h 4 5 6 - + 436 708 m 436 716 l - + 364 708 m 364 716 l @@ -535,11 +511,11 @@ h 308 716 l 308 716 l - + 264 688 m 268 696 l - + 292 688 m 292 696 l @@ -555,5 +531,65 @@ h 448 612 m 448 620 l +3 + +300 688 m +300 676 l +312 676 l +312 688 l +h + + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +364 688 m +364 696 l + + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +436 708 m +436 716 l + + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +300 688 m +300 676 l +312 676 l +312 688 l +h + +6 + +436 708 m +436 716 l + diff --git a/src/Alpha_complex/doc/alpha_complex_doc.png b/src/Alpha_complex/doc/alpha_complex_doc.png index cfe3ede6..0b6201da 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_doc.png and b/src/Alpha_complex/doc/alpha_complex_doc.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_420.ipe b/src/Alpha_complex/doc/alpha_complex_doc_420.ipe new file mode 100644 index 00000000..5d1d29d4 --- /dev/null +++ b/src/Alpha_complex/doc/alpha_complex_doc_420.ipe @@ -0,0 +1,514 @@ + + + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + +0.6 0 0 0.6 0 0 e + + + + + +0.5 0 0 0.5 0 0 e + + +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e + + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h + + + + + +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h + + +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h + + + + + + +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h + + +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h + + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h + + + + +-1 0.333 m +0 0 l +-1 -0.333 l + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +Cell [4,2,0] +0 +1 +2 +3 +4 +5 +6 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + + +77.2727 0 0 77.2727 243.636 591.818 e + + +243.428 591.569 m +186.061 643.28 l + +$\alpha_{420}$ + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[2,0] is Gabriel $\rightarrow$ $\alpha_{20}$ is not$\\$ +modified (NaN) + +0 +2 +3 +4 +5 +6 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{20}$ + +290 530 m +320 580 l + + +29.1548 0 0 29.1548 305 555 e + + +304.883 555.015 m +334.509 555.015 l + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +[0,4] is not Gabriel $\rightarrow$ $\alpha_{40} = \alpha_{420}$ +0 +3 +5 +6 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{40}$ + +290 530 m +280 660 l + + +320 580 m +350 520 l +290 530 l +320 580 l +320 580 l + + +320 580 m +280 660 l +290 530 l +320 580 l +320 580 l + + +320 580 m +370 580 l +350 520 l +320 580 l + +0 +1 +2 +3 +5 +6 + +280 660 m +300 710 l +370 690 l +280 660 l + + +320 580 m +370 690 l +370 580 l +320 580 l + + +280 660 m +370 690 l +320 580 l +280 660 l + +$\alpha_{42}$ +4 + +406.093 497.775 m +446.094 418.092 l + + +44.5799 0 0 44.5799 425.934 457.774 e + + +425.854 457.774 m +470.795 457.774 l + +[2,4] is Gabriel $\rightarrow$ $\alpha_{42}$ is not modified (NaN) + + +205.028 596.091 m +110.946 544.02 l + + +280.768 588.99 m +280.768 547.57 l + + +341.123 594.316 m +413.904 554.079 l + +For all faces of [4,2,0] +N.B. : is Gabriel on a single point has no sense. +Dimension =2 - $\sigma$ = [4,2,0] + +247.333 430.892 m +311.764 430.892 l + + + + + + + + + + + + + + +1 + + + + + +4 + + +1 + + +2 + +65.192 0 0 65.192 285 595 e + + + + + + + + + + + + + diff --git a/src/Alpha_complex/doc/alpha_complex_doc_420.png b/src/Alpha_complex/doc/alpha_complex_doc_420.png new file mode 100644 index 00000000..ef7187f7 Binary files /dev/null and b/src/Alpha_complex/doc/alpha_complex_doc_420.png differ diff --git a/src/Alpha_complex/doc/alpha_complex_doc_421.ipe b/src/Alpha_complex/doc/alpha_complex_doc_421.ipe deleted file mode 100644 index 727816c5..00000000 --- a/src/Alpha_complex/doc/alpha_complex_doc_421.ipe +++ /dev/null @@ -1,514 +0,0 @@ - - - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - -0.6 0 0 0.6 0 0 e - - - - - -0.5 0 0 0.5 0 0 e - - -0.6 0 0 0.6 0 0 e -0.4 0 0 0.4 0 0 e - - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h - - - - - --0.5 -0.5 m -0.5 -0.5 l -0.5 0.5 l --0.5 0.5 l -h - - --0.6 -0.6 m -0.6 -0.6 l -0.6 0.6 l --0.6 0.6 l -h --0.4 -0.4 m -0.4 -0.4 l -0.4 0.4 l --0.4 0.4 l -h - - - - - - --0.43 -0.57 m -0.57 0.43 l -0.43 0.57 l --0.57 -0.43 l -h - - --0.43 0.57 m -0.57 -0.43 l -0.43 -0.57 l --0.57 0.43 l -h - - - - - -0 0 m --1 0.333 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - -0 0 m --1 0.333 l --0.8 0 l --1 -0.333 l -h - - - - --1 0.333 m -0 0 l --1 -0.333 l - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - -0 0 m --1 0.333 l --1 -0.333 l -h --1 0 m --2 0.333 l --2 -0.333 l -h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -Cell [4,2,1] -2 -6 -4 -5 -1 -3 -0 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - - -77.2727 0 0 77.2727 243.636 591.818 e - - -243.428 591.569 m -186.061 643.28 l - -$\alpha_{421}$ - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -[4,2] is Gabriel $\rightarrow$ $\alpha_{42}$ is not$\\$ -modified (NaN) - -2 -4 -5 -1 -3 -0 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{42}$ - -290 530 m -320 580 l - - -29.1548 0 0 29.1548 305 555 e - - -304.883 555.015 m -334.509 555.015 l - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -[2,1] is not Gabriel $\rightarrow$ $\alpha_{21} = \alpha_{421}$ -2 -5 -3 -0 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{12}$ - -290 530 m -280 660 l - - -320 580 m -350 520 l -290 530 l -320 580 l -320 580 l - - -320 580 m -280 660 l -290 530 l -320 580 l -320 580 l - - -320 580 m -370 580 l -350 520 l -320 580 l - -2 -6 -4 -5 -3 -0 - -280 660 m -300 710 l -370 690 l -280 660 l - - -320 580 m -370 690 l -370 580 l -320 580 l - - -280 660 m -370 690 l -320 580 l -280 660 l - -$\alpha_{41}$ -1 - -406.093 497.775 m -446.094 418.092 l - - -44.5799 0 0 44.5799 425.934 457.774 e - - -425.854 457.774 m -470.795 457.774 l - -[4,1] is Gabriel $\rightarrow$ $\alpha_{41}$ is not modified (NaN) - - -205.028 596.091 m -110.946 544.02 l - - -280.768 588.99 m -280.768 547.57 l - - -341.123 594.316 m -413.904 554.079 l - -For all faces of [4,2,1] -N.B. : is Gabriel on a single point has no sense. -Dimension =2 - $\sigma$ = [4,2,1] - -247.333 430.892 m -311.764 430.892 l - - - - - - - - - - - - - - -6 - - - - - -1 - - -6 - - -4 - -65.192 0 0 65.192 285 595 e - - - - - - - - - - - - - diff --git a/src/Alpha_complex/doc/alpha_complex_doc_421.png b/src/Alpha_complex/doc/alpha_complex_doc_421.png deleted file mode 100644 index 1cce4402..00000000 Binary files a/src/Alpha_complex/doc/alpha_complex_doc_421.png and /dev/null differ diff --git a/src/Alpha_complex/doc/alpha_complex_representation.ipe b/src/Alpha_complex/doc/alpha_complex_representation.ipe index fead1661..e8096b93 100644 --- a/src/Alpha_complex/doc/alpha_complex_representation.ipe +++ b/src/Alpha_complex/doc/alpha_complex_representation.ipe @@ -1,7 +1,7 @@ - + @@ -251,13 +251,13 @@ h h Alpha complex -2 -6 -4 -5 -1 -3 -0 +0 +1 +2 +3 +4 +5 +6 58.1341 0 0 58.1341 218.925 692.601 e diff --git a/src/Alpha_complex/doc/alpha_complex_representation.png b/src/Alpha_complex/doc/alpha_complex_representation.png index 9833bff3..7b81cd69 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_representation.png and b/src/Alpha_complex/doc/alpha_complex_representation.png differ diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 18a1a20d..963ef5ca 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -4,17 +4,15 @@ #include #include -void usage(char * const progName) { +void usage(int nbArgs, char * const progName) { + std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n"; std::cerr << "Usage: " << progName << " filename.off alpha_square_max_value [ouput_file.txt]\n"; std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0\n"; exit(-1); // ----- >> } int main(int argc, char **argv) { - if ((argc != 3) && (argc != 4)) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; - usage(argv[0]); - } + if ((argc != 3) && (argc != 4)) usage(argc, (argv[0] - 1)); std::string off_file_name(argv[1]); double alpha_square_max_value = atof(argv[2]); diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 815e40d7..cd17af1e 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -4,13 +4,26 @@ #include #include #include +#include // for numeric limits typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel; typedef Kernel::Point_d Point; typedef std::vector Vector_of_points; +void usage(int nbArgs, char * const progName) { + std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n"; + std::cerr << "Usage: " << progName << " [alpha_square_max_value]\n"; + std::cerr << " i.e.: " << progName << " 60.0\n"; + exit(-1); // ----- >> +} + int main(int argc, char **argv) { - double alpha_square_max_value = 60.0; + if ((argc != 1) && (argc != 2)) usage(argc, (argv[0] - 1)); + + // Delaunay complex if alpha_square_max_value is not given by the user. + double alpha_square_max_value = std::numeric_limits::infinity(); + if (argc == 2) + alpha_square_max_value = atof(argv[1]); // ---------------------------------------------------------------------------- // Init of a list of points diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt index 5869fdff..13183e86 100644 --- a/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_32.txt @@ -7,16 +7,16 @@ Iterator on alpha complex simplices in the filtration order, with [filtration va ( 4 ) -> [0] ( 5 ) -> [0] ( 6 ) -> [0] - ( 5 4 ) -> [6.25] - ( 3 1 ) -> [7.25] - ( 4 2 ) -> [8.5] - ( 6 2 ) -> [9.25] - ( 6 5 ) -> [10] - ( 6 4 ) -> [11.25] - ( 6 5 4 ) -> [12.5] - ( 6 4 2 ) -> [12.9959] - ( 3 0 ) -> [13.25] - ( 4 1 ) -> [20] - ( 1 0 ) -> [22.7367] - ( 3 1 0 ) -> [22.7367] - ( 5 0 ) -> [30.25] + ( 3 2 ) -> [6.25] + ( 5 4 ) -> [7.25] + ( 2 0 ) -> [8.5] + ( 1 0 ) -> [9.25] + ( 3 1 ) -> [10] + ( 2 1 ) -> [11.25] + ( 3 2 1 ) -> [12.5] + ( 2 1 0 ) -> [12.9959] + ( 6 5 ) -> [13.25] + ( 4 2 ) -> [20] + ( 6 4 ) -> [22.7367] + ( 6 5 4 ) -> [22.7367] + ( 6 3 ) -> [30.25] diff --git a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt index 1d17a58a..71f29a00 100644 --- a/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt +++ b/src/Alpha_complex/example/alphaoffreader_for_doc_60.txt @@ -7,21 +7,21 @@ Iterator on alpha complex simplices in the filtration order, with [filtration va ( 4 ) -> [0] ( 5 ) -> [0] ( 6 ) -> [0] - ( 5 4 ) -> [6.25] - ( 3 1 ) -> [7.25] - ( 4 2 ) -> [8.5] - ( 6 2 ) -> [9.25] - ( 6 5 ) -> [10] - ( 6 4 ) -> [11.25] - ( 6 5 4 ) -> [12.5] - ( 6 4 2 ) -> [12.9959] - ( 3 0 ) -> [13.25] - ( 4 1 ) -> [20] - ( 1 0 ) -> [22.7367] - ( 3 1 0 ) -> [22.7367] - ( 5 0 ) -> [30.25] - ( 4 0 ) -> [36.5] - ( 5 4 0 ) -> [36.5] - ( 4 1 0 ) -> [37.2449] - ( 2 1 ) -> [59.7107] - ( 4 2 1 ) -> [59.7107] + ( 3 2 ) -> [6.25] + ( 5 4 ) -> [7.25] + ( 2 0 ) -> [8.5] + ( 1 0 ) -> [9.25] + ( 3 1 ) -> [10] + ( 2 1 ) -> [11.25] + ( 3 2 1 ) -> [12.5] + ( 2 1 0 ) -> [12.9959] + ( 6 5 ) -> [13.25] + ( 4 2 ) -> [20] + ( 6 4 ) -> [22.7367] + ( 6 5 4 ) -> [22.7367] + ( 6 3 ) -> [30.25] + ( 6 2 ) -> [36.5] + ( 6 3 2 ) -> [36.5] + ( 6 4 2 ) -> [37.2449] + ( 4 0 ) -> [59.7107] + ( 4 2 0 ) -> [59.7107] diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 2b27a459..21eb5f48 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -27,14 +27,16 @@ #include #include #include -// to construct a Delaunay_triangulation from a OFF file -#include +// to construct Alpha_complex from a OFF file of points +#include #include #include // isnan, fmax +//#include #include #include +#include #include #include @@ -43,6 +45,7 @@ #include #include // std::pair #include +#include // for std::iota namespace Gudhi { @@ -57,7 +60,7 @@ namespace alphacomplex { * \details * The data structure can be constructed from a CGAL Delaunay triangulation (for more informations on CGAL Delaunay * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) or from - * an OFF file (cf. Delaunay_triangulation_off_reader). + * an OFF file (cf. Points_off_reader). * * Please refer to \ref alpha_complex for examples. * @@ -74,13 +77,19 @@ namespace alphacomplex { template> class Alpha_complex : public Simplex_tree<> { public: + // Add an int in TDS to save point index in the structure + typedef CGAL::Triangulation_data_structure, + CGAL::Triangulation_full_cell > TDS; /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ - typedef typename CGAL::Delaunay_triangulation Delaunay_triangulation; + typedef CGAL::Delaunay_triangulation Delaunay_triangulation; + /** \brief A point in Euclidean space.*/ typedef typename Kernel::Point_d Point_d; /** \brief Geometric traits class that provides the geometric types and predicates needed by Delaunay * triangulations.*/ typedef Kernel Geom_traits; + private: // From Simplex_tree // Type required to insert into a simplex_tree (with or without subfaces). @@ -104,7 +113,7 @@ class Alpha_complex : public Simplex_tree<> { // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; - typedef typename std::vector< CGAL_vertex_iterator > Vector_vertex_iterator; + typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Vector_vertex_iterator; private: /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ @@ -128,28 +137,13 @@ class Alpha_complex : public Simplex_tree<> { Alpha_complex(const std::string& off_file_name, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(nullptr) { - Gudhi::Delaunay_triangulation_off_reader off_reader(off_file_name); + Gudhi::Points_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { std::cerr << "Alpha_complex - Unable to read file " << off_file_name << "\n"; exit(-1); // ----- >> } - triangulation_ = off_reader.get_complex(); - init(max_alpha_square); - } - /** \brief Alpha_complex constructor from a Delaunay triangulation. - * - * @param[in] triangulation_ptr Pointer on a - * CGAL::Delaunay_triangulation \cite cgal:hdj-t-15b. - * Alpha_complex takes ownership of the Delaunay_triangulation object, which must have been allocated using operator - * new. - * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. - */ - Alpha_complex(Delaunay_triangulation* triangulation_ptr, - Filtration_value max_alpha_square = std::numeric_limits::infinity()) - : triangulation_(triangulation_ptr) { - init(max_alpha_square); + init_from_range(off_reader.get_point_cloud(), max_alpha_square); } /** \brief Alpha_complex constructor from a list of points. @@ -164,23 +158,7 @@ class Alpha_complex : public Simplex_tree<> { Alpha_complex(const InputPointRange& points, Filtration_value max_alpha_square = std::numeric_limits::infinity()) : triangulation_(nullptr) { - auto first = std::begin(points); - auto last = std::end(points); - - if (first != last) { - // point_dimension function initialization - Point_Dimension point_dimension = kernel_.point_dimension_d_object(); - - // Delaunay triangulation is point dimension. - triangulation_ = new Delaunay_triangulation(point_dimension(*first)); - - size_type inserted = triangulation_->insert(first, last); - if (inserted != (last -first)) { - std::cerr << "Alpha_complex - insertion failed " << inserted << " != " << (last -first) << "\n"; - exit(-1); // ----- >> - } - init(max_alpha_square); - } + init_from_range(points, max_alpha_square); } /** \brief Alpha_complex destructor. @@ -191,6 +169,12 @@ class Alpha_complex : public Simplex_tree<> { delete triangulation_; } + // Forbid copy/move constructor/assignment operator + Alpha_complex(const Alpha_complex& other) = delete; + Alpha_complex& operator= (const Alpha_complex& other) = delete; + Alpha_complex (Alpha_complex&& other) = delete; + Alpha_complex& operator= (Alpha_complex&& other) = delete; + /** \brief get_point returns the point corresponding to the vertex given as parameter. * * @param[in] vertex Vertex handle of the point to retrieve. @@ -202,6 +186,44 @@ class Alpha_complex : public Simplex_tree<> { } private: + template + void init_from_range(const InputPointRange& points, Filtration_value max_alpha_square) { + auto first = std::begin(points); + auto last = std::end(points); + if (first != last) { + // point_dimension function initialization + Point_Dimension point_dimension = kernel_.point_dimension_d_object(); + + // Delaunay triangulation is point dimension. + triangulation_ = new Delaunay_triangulation(point_dimension(*first)); + + std::vector points(first, last); + + // Creates a vector {0, 1, ..., N-1} + std::vector indices(boost::counting_iterator(0), + boost::counting_iterator(points.size())); + + // Sort indices considering CGAL spatial sort + typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; + spatial_sort(indices.begin(),indices.end(),Search_traits_d(&(points[0]))); + + typename Delaunay_triangulation::Full_cell_handle hint; + for (auto index : indices) { + typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(points[index], hint); + // Save index value as data to retrieve it after insertion + pos->data() = index; + hint = pos->full_cell(); + } + + if (triangulation_->number_of_vertices() != (last -first)) { + std::cerr << "Alpha_complex - insertion failed " << triangulation_->number_of_vertices() << " != " << + (last -first) << "\n"; + exit(-1); // ----- >> + } + init(max_alpha_square); + } + } + /** \brief Initialize the Alpha_complex from the Delaunay triangulation. * * @param[in] max_alpha_square maximum for alpha square value. @@ -233,18 +255,15 @@ class Alpha_complex : public Simplex_tree<> { // -------------------------------------------------------------------------------------------- // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa - // Start to insert at handle = 0 - default integer value - Vertex_handle vertex_handle = Vertex_handle(); // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { if (!triangulation_->is_infinite(*vit)) { #ifdef DEBUG_TRACES - std::cout << "Vertex insertion - " << vertex_handle << " -> " << vit->point() << std::endl; + std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES - vertex_iterator_to_handle_.emplace(vit, vertex_handle); - vertex_handle_to_iterator_.push_back(vit); - vertex_handle++; + vertex_iterator_to_handle_.emplace(vit, vit->data()); + vertex_handle_to_iterator_.emplace(vit->data(), vit); } } // -------------------------------------------------------------------------------------------- diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 315582d1..80b39924 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -32,8 +32,6 @@ #include #include -// to construct a Delaunay_triangulation from a OFF file -#include #include // Use dynamic_dimension_tag for the user to be able to set dimension diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp index d2f9a4a2..8f9f077c 100644 --- a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp @@ -1,8 +1,7 @@ #include #include -// to construct a Delaunay_triangulation from a OFF file -#include + #include #include diff --git a/src/common/example/CGAL_points_off_reader.cpp b/src/common/example/CGAL_points_off_reader.cpp new file mode 100644 index 00000000..076afd5b --- /dev/null +++ b/src/common/example/CGAL_points_off_reader.cpp @@ -0,0 +1,43 @@ +#include + +// For CGAL points type in dimension d +// cf. http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Point__d.html +#include + +#include +#include + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef typename Kernel::Point_d Point_d; + +void usage(int argc, char * const progName) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; + std::cerr << "Usage: " << progName << " inputFile.off" << std::endl; + exit(-1); +} + +int main(int argc, char **argv) { + if (argc != 2) usage(argc, (argv[0] - 1)); + + std::string offInputFile(argv[1]); + // Read the OFF file (input file name given as parameter) and triangulate points + Gudhi::Points_off_reader off_reader(offInputFile); + // Check the read operation was correct + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << offInputFile << std::endl; + exit(-1); + } + + // Retrieve the triangulation + std::vector point_cloud = off_reader.get_point_cloud(); + + int n = 0; + for (auto point : point_cloud) { + std::cout << "Point[" << n << "] = "; + for (int i = 0; i < point.dimension(); i++) + std::cout << point[i] << " "; + std::cout << "\n"; + ++n; + } + return 0; +} diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index 91e78ea2..2914756e 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -9,15 +9,9 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - add_executable ( dtoffrw Delaunay_triangulation_off_rw.cpp ) - target_link_libraries(dtoffrw ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test(dtoffrw ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw ${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) - - if (DIFF_PATH) - # Do not forget to copy test results files in current binary dir - file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - add_test(dtoffrw_result_off_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off ${CMAKE_CURRENT_BINARY_DIR}/result.off) - endif() + add_executable ( cgaloffreader CGAL_points_off_reader.cpp ) + target_link_libraries(cgaloffreader ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_test(cgaloffreader ${CMAKE_CURRENT_BINARY_DIR}/cgaloffreader ${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") diff --git a/src/common/example/Delaunay_triangulation_off_rw.cpp b/src/common/example/Delaunay_triangulation_off_rw.cpp deleted file mode 100644 index 4c7a9aaf..00000000 --- a/src/common/example/Delaunay_triangulation_off_rw.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// to construct a Delaunay_triangulation from a OFF file -#include - -#include -#include - -#include -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; -// The triangulation uses the default instantiation of the -// TriangulationDataStructure template parameter - -void usage(char * const progName) { - std::cerr << "Usage: " << progName << " inputFile.off outputFile.off" << std::endl; - exit(-1); -} - -int main(int argc, char **argv) { - if (argc != 3) { - std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl; - usage(argv[0]); - } - - std::string offInputFile(argv[1]); - // Read the OFF file (input file name given as parameter) and triangulates points - Gudhi::Delaunay_triangulation_off_reader off_reader(offInputFile); - // Check the read operation was correct - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << offInputFile << std::endl; - exit(-1); - } - - // Retrieve the triangulation - T* triangulation = off_reader.get_complex(); - // Operations on triangulation - std::cout << "Number of vertices= " << triangulation->number_of_vertices() << std::endl; - std::cout << "Number of finite full cells= " << triangulation->number_of_finite_full_cells() << std::endl; - - std::string outFileName(argv[2]); - std::string offOutputFile(outFileName); - // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces - Gudhi::Delaunay_triangulation_off_writer off_writer(offOutputFile, triangulation); - - // Check the write operation was correct - if (!off_writer.is_valid()) { - std::cerr << "Unable to write file " << offOutputFile << std::endl; - exit(-1); - } - - return 0; -} diff --git a/src/common/example/cgaloffreader_result.txt b/src/common/example/cgaloffreader_result.txt new file mode 100644 index 00000000..1deb8dbd --- /dev/null +++ b/src/common/example/cgaloffreader_result.txt @@ -0,0 +1,7 @@ +Point[0] = 1 1 +Point[1] = 7 0 +Point[2] = 4 6 +Point[3] = 9 6 +Point[4] = 0 14 +Point[5] = 2 19 +Point[6] = 9 17 diff --git a/src/common/example/dtoffrw_alphashapedoc_result.off b/src/common/example/dtoffrw_alphashapedoc_result.off deleted file mode 100644 index d1839a43..00000000 --- a/src/common/example/dtoffrw_alphashapedoc_result.off +++ /dev/null @@ -1,15 +0,0 @@ -nOFF -2 7 6 0 -9 17 -0 14 -1 1 -2 19 -4 6 -9 6 -7 0 -3 5 0 4 -3 0 1 4 -3 3 1 0 -3 4 1 2 -3 5 4 6 -3 6 4 2 diff --git a/src/common/example/dtoffrw_alphashapedoc_result.txt b/src/common/example/dtoffrw_alphashapedoc_result.txt deleted file mode 100644 index 8e659740..00000000 --- a/src/common/example/dtoffrw_alphashapedoc_result.txt +++ /dev/null @@ -1,2 +0,0 @@ -Number of vertices= 7 -Number of finite full cells= 6 diff --git a/src/common/include/gudhi/Delaunay_triangulation_off_io.h b/src/common/include/gudhi/Delaunay_triangulation_off_io.h deleted file mode 100644 index 50be9a59..00000000 --- a/src/common/include/gudhi/Delaunay_triangulation_off_io.h +++ /dev/null @@ -1,348 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2015 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef DELAUNAY_TRIANGULATION_OFF_IO_H_ -#define DELAUNAY_TRIANGULATION_OFF_IO_H_ - -#include -#include -#include -#include - -#include - -#include - -#include "gudhi/Off_reader.h" - -namespace Gudhi { - -/** - * \class Delaunay_triangulation_off_visitor_reader Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h - * \brief OFF file visitor implementation according to Off_reader in order to construct a CGAL Delaunay triangulation. - * - * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page - * http://doc.cgal.org/latest/Triangulation/ - */ -template -class Delaunay_triangulation_off_visitor_reader { - private: - Complex* complex_; - typedef typename Complex::Point_d Point_d; - typedef typename Complex::size_type size_type; - std::vector point_cloud; - - public: - // TODO(VR) : Pass a Complex as a parameter is required, even if not used. Otherwise, compilation is KO. - - /** \brief Delaunay_triangulation_off_visitor_reader constructor - * - * @param[in] complex_ptr_ pointer on a Delaunay triangulation. - */ - Delaunay_triangulation_off_visitor_reader(Complex* complex_ptr_) - : complex_(nullptr) { } - - /** \brief Off_reader visitor init implementation. - * - * The init parameters are set from OFF file header. - * Dimension value is required in order to construct Delaunay triangulation. - * - * @param[in] dim space dimension of vertices. - * @param[in] num_vertices number of vertices in the OFF file (not used). - * @param[in] num_faces number of faces in the OFF file (not used). - * @param[in] num_edges number of edges in the OFF file (not used). - */ - void init(int dim, int num_vertices, int num_faces, int num_edges) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << - num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; -#endif // DEBUG_TRACES - if (num_faces > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init faces are not taken into account from OFF " << - "file for Delaunay triangulation - faces are computed.\n"; - } - if (num_edges > 0) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::init edges are not taken into account from OFF " << - "file for Delaunay triangulation - edges are computed.\n"; - } - // Complex construction with dimension from file - complex_ = new Complex(dim); - } - - /** \brief Off_reader visitor point implementation. - * - * The point function is called on each vertex line from OFF file. - * This function inserts the vertex in the Delaunay triangulation. - * - * @param[in] point vector of vertex coordinates. - */ - void point(const std::vector& point) { -#ifdef DEBUG_TRACES - std::cout << "Delaunay_triangulation_off_visitor_reader::point "; - for (auto coordinate : point) { - std::cout << coordinate << " | "; - } - std::cout << std::endl; -#endif // DEBUG_TRACES - // Fill the point cloud - point_cloud.push_back(Point_d(point.size(), point.begin(), point.end())); - } - - // Off_reader visitor maximal_face implementation - not used - void maximal_face(const std::vector& face) { - // For Delaunay Triangulation, only points are read - } - - // Off_reader visitor done implementation - void done() { - // It is advised to insert all the points at a time in a Delaunay Triangulation because points are sorted at the - // beginning of the insertion - size_type inserted = complex_->insert(point_cloud.begin(), point_cloud.end()); - if (inserted != (point_cloud.end() -point_cloud.begin())) { - std::cerr << "Delaunay_triangulation_off_visitor_reader::done - insertion failed " << inserted << " != " << - (point_cloud.end() -point_cloud.begin()) << "\n"; - } - } - - /** \brief Returns the constructed Delaunay triangulation. - * - * @return A pointer on the Delaunay triangulation. Default value is nullptr. - */ - Complex* get_complex() const { - return complex_; - } - - private: - template - size_type insert_with_index(const PointRangeIterator& first, const PointRangeIterator& last) { - size_type vertices_before_insertion = complex_->number_of_vertices(); - std::vector points(first, last); - - std::vector indices; - indices.reserve(points.size()); - - // Creates a vector {0, 1, ..., N-1} - std::copy(boost::counting_iterator(0), boost::counting_iterator(points.size()), - std::back_inserter(indices)); - - // Sort indices considering CGAL spatial sort - typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; - spatial_sort(indices.begin(),indices.end(),Search_traits_d(&(points[0]))); - - typename Delaunay_triangulation::Full_cell_handle hint; - for (typename std::vector::const_iterator it = indices.begin(), end = indices.end(); - it != end; ++it) { - typename Delaunay_triangulation::Vertex_handle pos = complex_->insert(points[*it], hint); - // Save index value as data to retrieve it after insertion - pos->data() = *it; - hint = pos->full_cell(); - } - - return (complex_->number_of_vertices() - vertices_before_insertion); - } - -}; - -/** - * \class Delaunay_triangulation_off_reader Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h - * \brief OFF file reader implementation in order to construct a Delaunay triangulation. - * - * This class is using the Delaunay_triangulation_off_visitor_reader to visit the OFF file according to Off_reader. - * - * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page - * http://doc.cgal.org/latest/Triangulation/ - * - * \section Example - * - * This example loads points from an OFF file and builds the Delaunay triangulation. - * Then, it is asked to display the number of vertices and finites full cells from the Delaunay triangulation. - * - * \include Delaunay_triangulation_off_rw.cpp - * - * When launching: - * - * \code $> ./dtoffrw ../../data/points/alphacomplexdoc.off triangulated.off - * \endcode - * - * the program output is: - * - * \include dtoffrw_alphashapedoc_result.txt - */ -template -class Delaunay_triangulation_off_reader { - public: - /** \brief Reads the OFF file and constructs the Delaunay triangulation from the points - * that are in the OFF file. - * - * @param[in] name_file OFF file to read. - * - * \post Check with is_valid() function to see if read operation was successful. - */ - Delaunay_triangulation_off_reader(const std::string & name_file) - : valid_(false) { - std::ifstream stream(name_file); - if (stream.is_open()) { - Delaunay_triangulation_off_visitor_reader off_visitor(complex_); - Off_reader off_reader(stream); - valid_ = off_reader.read(off_visitor); - if (valid_) { - complex_ = off_visitor.get_complex(); - if (complex_ == nullptr) { - std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader off_visitor returns " << - "an empty pointer\n"; - valid_ = false; - } - } - } else { - std::cerr << "Delaunay_triangulation_off_reader::Delaunay_triangulation_off_reader could not open file " << - name_file << "\n"; - } - } - - /** \brief Returns if the OFF file read operation was successful or not. - * - * @return OFF file read status. - */ - bool is_valid() const { - return valid_; - } - - /** \brief Returns the constructed Delaunay triangulation. - * - * @return A pointer on the Delaunay triangulation. Default value is nullptr. - */ - Complex* get_complex() const { - if (valid_) - return complex_; - return nullptr; - } - - private: - /** \brief OFF file read status.*/ - bool valid_; - /** \brief A pointer on the Delaunay triangulation.*/ - Complex* complex_; -}; - -/** - * \class Delaunay_triangulation_off_writer Delaunay_triangulation_off_io.h gudhi/Delaunay_triangulation_off_io.h - * \brief OFF file writer from a Delaunay triangulation. - * - * This class constructs the OFF file header according to http://www.geomview.org/docs/html/OFF.html - * - * The header is followed by the list of points coordinates (Delaunay triangulation vertices) - * - * And finally is followed by the list of faces (Delaunay triangulation finite full cells) - * - * For more informations on CGAL Delaunay triangulation, please refer to the corresponding chapter in page - * http://doc.cgal.org/latest/Triangulation/ - * - * \section Example - * - * This example loads points from an OFF file and builds the Delaunay triangulation. - * Then, the Delaunay triangulation is saved in a new file including the triangulation as a list of faces. - * - * \include Delaunay_triangulation_off_rw.cpp - * - * When launching: - * - * \code $> ./dtoffrw ../../data/points/alphashapedoc.off triangulated.off - * \endcode - * - * The result will be an OFF file of dimension 2 with the 7 points from alphashapedoc.off followed by the 6 - * triangulations of dimension 3 (the first value on each faces): - * \include dtoffrw_alphashapedoc_result.off - */ -template -class Delaunay_triangulation_off_writer { - public: - typedef typename Complex::Point Point; - - /** \brief Writes the OFF file from the Delaunay triangulation. - * - * @param[in] name_file OFF file to write. - * @param[in] complex_ptr pointer on a Delaunay triangulation. - * - * \post Check with is_valid() function to see if write operation was successful. - */ - Delaunay_triangulation_off_writer(const std::string & name_file, Complex* complex_ptr) - : valid_(false) { - std::ofstream stream(name_file); - if (stream.is_open()) { - if (complex_ptr->current_dimension() == 3) { - // OFF header - stream << "OFF" << std::endl; - // no endl on next line - don't know why... - stream << complex_ptr->number_of_vertices() << " " << complex_ptr->number_of_finite_full_cells() << " 0"; - } else { - // nOFF header - stream << "nOFF" << std::endl; - // no endl on next line - don't know why... - stream << complex_ptr->current_dimension() << " " << complex_ptr->number_of_vertices() << " " << - complex_ptr->number_of_finite_full_cells() << " 0"; - } - - // bimap to retrieve vertex handles from points and vice versa - std::map< Point, int > points_to_vh; - // Start to insert at default handle value - int vertex_handle = int(); - - // Points list - for (auto vit = complex_ptr->vertices_begin(); vit != complex_ptr->vertices_end(); ++vit) { - for (auto Coord = vit->point().cartesian_begin(); Coord != vit->point().cartesian_end(); ++Coord) { - stream << *Coord << " "; - } - stream << std::endl; - points_to_vh[vit->point()] = vertex_handle; - vertex_handle++; - } - - for (auto cit = complex_ptr->finite_full_cells_begin(); cit != complex_ptr->finite_full_cells_end(); ++cit) { - stream << std::distance(cit->vertices_begin(), cit->vertices_end()) << " "; - for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { - stream << points_to_vh[(*vit)->point()] - 1 << " "; - } - stream << std::endl; - } - stream.close(); - valid_ = true; - } else { - std::cerr << "Delaunay_triangulation_off_writer::Delaunay_triangulation_off_writer could not open file " << - name_file << "\n"; - } - } - - /** \brief Returns if the OFF write operation was successful or not. - * - * @return OFF file write status. - */ - bool is_valid() const { - return valid_; - } - - private: - /* \brief OFF file write status. */ - bool valid_; -}; - -} // namespace Gudhi - -#endif // DELAUNAY_TRIANGULATION_OFF_IO_H_ diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h new file mode 100644 index 00000000..d9f9a74b --- /dev/null +++ b/src/common/include/gudhi/Points_off_io.h @@ -0,0 +1,178 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef POINTS_OFF_IO_H_ +#define POINTS_OFF_IO_H_ + +#include +#include +#include +#include + +#include + +namespace Gudhi { + +/** + * \brief OFF file visitor implementation according to Off_reader in order to read points from an OFF file. + */ +template +class Points_off_visitor_reader { + private: + std::vector point_cloud; + + public: + /** \brief Off_reader visitor init implementation. + * + * The init parameters are set from OFF file header. + * Dimension value is required in order to construct Alpha complex. + * + * @param[in] dim space dimension of vertices. + * @param[in] num_vertices number of vertices in the OFF file (not used). + * @param[in] num_faces number of faces in the OFF file (not used). + * @param[in] num_edges number of edges in the OFF file (not used). + */ + void init(int dim, int num_vertices, int num_faces, int num_edges) { +#ifdef DEBUG_TRACES + std::cout << "Points_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; +#endif // DEBUG_TRACES + if (num_faces > 0) { + std::cerr << "Points_off_visitor_reader::init faces are not taken into account from OFF file for Points.\n"; + } + if (num_edges > 0) { + std::cerr << "Points_off_visitor_reader::init edges are not taken into account from OFF file for Points.\n"; + } + } + + /** \brief Off_reader visitor point implementation. + * + * The point function is called on each vertex line from OFF file. + * This function inserts the vertex in the Alpha complex. + * + * @param[in] point vector of vertex coordinates. + */ + void point(const std::vector& point) { +#ifdef DEBUG_TRACES + std::cout << "Points_off_visitor_reader::point "; + for (auto coordinate : point) { + std::cout << coordinate << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + // Fill the point cloud + point_cloud.push_back(Point_d(point.size(), point.begin(), point.end())); + } + + // Off_reader visitor maximal_face implementation - Only points are read + void maximal_face(const std::vector& face) { } + + // Off_reader visitor done implementation - Only points are read + void done() { } + + /** \brief Point cloud getter. + * + * @return point_cloud. + */ + const std::vector& get_point_cloud() { + return point_cloud; + } + +}; + +/** + * \brief OFF file reader implementation in order to read points from an OFF file. + * + * This class is using the Points_off_visitor_reader to visit the OFF file according to Off_reader. + * + * Point_d must have a constructor with the following form: + * + * \code template Point_d::Point_d(int d, InputIterator first, InputIterator last) \endcode + * + * where d is the point dimension. + * + * \section Example + * + * This example loads points from an OFF file and builds a vector of CGAL points in dimension d. + * Then, it is asked to display the points. + * + * \include CGAL_points_off_reader.cpp + * + * When launching: + * + * \code $> ./cgaloffreader ../../data/points/alphacomplexdoc.off + * \endcode + * + * the program output is: + * + * \include cgaloffreader_result.txt + */ +template +class Points_off_reader { + public: + /** \brief Reads the OFF file and constructs the Alpha complex from the points + * that are in the OFF file. + * + * @param[in] name_file OFF file to read. + * + * \post Check with is_valid() function to see if read operation was successful. + */ + Points_off_reader(const std::string& name_file) + : valid_(false) { + std::ifstream stream(name_file); + if (stream.is_open()) { + Off_reader off_reader(stream); + Points_off_visitor_reader off_visitor; + valid_ = off_reader.read(off_visitor); + if (valid_) { + point_cloud = off_visitor.get_point_cloud(); + } + } else { + std::cerr << "Points_off_reader::Points_off_reader could not open file " << name_file << "\n"; + } + } + + /** \brief Returns if the OFF file read operation was successful or not. + * + * @return OFF file read status. + */ + bool is_valid() const { + return valid_; + } + + /** \brief Point cloud getter. + * + * @return point_cloud. + */ + const std::vector& get_point_cloud() { + return point_cloud; + } + + private: + /** \brief point_cloud.*/ + std::vector point_cloud; + /** \brief OFF file read status.*/ + bool valid_; +}; + +} // namespace Gudhi + +#endif // POINTS_OFF_IO_H_ diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 12eecda8..6205f0e4 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -18,22 +18,16 @@ if(CGAL_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") include( ${EIGEN3_USE_FILE} ) - add_executable ( dtoffrw_UT dtoffrw_unit_test.cpp ) - target_link_libraries(dtoffrw_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + add_executable ( poffreader_UT points_off_reader_unit_test.cpp ) + target_link_libraries(poffreader_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) # Unitary tests - add_test(dtoffrw_UT ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_UT + add_test(poffreader_UT ${CMAKE_CURRENT_BINARY_DIR}/poffreader_UT # XML format for Jenkins xUnit plugin - --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/dtoffrw_UT.xml --log_level=test_suite --report_level=no) - - if (DIFF_PATH) - # Do not forget to copy test result files in current binary dir - file(COPY "dtoffrw_alphashapedoc_result.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - add_test(dtoffrw_diff_files_UT ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/UT.off ${CMAKE_CURRENT_BINARY_DIR}/dtoffrw_alphashapedoc_result.off) - endif() + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/poffreader_UT.xml --log_level=test_suite --report_level=no) else() message(WARNING "Eigen3 not found. Version 3.1.0 is required for Alpha shapes feature.") diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off index d1839a43..1deb8dbd 100644 --- a/src/common/test/dtoffrw_alphashapedoc_result.off +++ b/src/common/test/dtoffrw_alphashapedoc_result.off @@ -1,15 +1,7 @@ -nOFF -2 7 6 0 -9 17 -0 14 -1 1 -2 19 -4 6 -9 6 -7 0 -3 5 0 4 -3 0 1 4 -3 3 1 0 -3 4 1 2 -3 5 4 6 -3 6 4 2 +Point[0] = 1 1 +Point[1] = 7 0 +Point[2] = 4 6 +Point[3] = 9 6 +Point[4] = 0 14 +Point[5] = 2 19 +Point[6] = 9 17 diff --git a/src/common/test/dtoffrw_unit_test.cpp b/src/common/test/dtoffrw_unit_test.cpp deleted file mode 100644 index f682df1a..00000000 --- a/src/common/test/dtoffrw_unit_test.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2015 INRIA Saclay (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// to construct a Delaunay_triangulation from a OFF file -#include "gudhi/Delaunay_triangulation_off_io.h" - -#include -#include - -#include - -#include -#include - -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "delaunay_triangulation_off_read_write" -#include - -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K; -typedef CGAL::Delaunay_triangulation T; - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation_doc_test ) -{ - // Read the OFF file (input file name given as parameter) and triangulates points - Gudhi::Delaunay_triangulation_off_reader off_reader("alphacomplexdoc.off"); - // Check the read operation was correct - BOOST_CHECK(off_reader.is_valid()); - - // Retrieve the triangulation - T* triangulation = off_reader.get_complex(); - BOOST_CHECK(triangulation != nullptr); - // Operations on triangulation - BOOST_CHECK(triangulation->number_of_vertices() == 7); - BOOST_CHECK(triangulation->number_of_finite_full_cells() == 6); - - // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces - Gudhi::Delaunay_triangulation_off_writer off_writer("UT.off", triangulation); - - // Check the write operation was correct - BOOST_CHECK(off_writer.is_valid()); - - delete triangulation; -} - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) -{ - Gudhi::Delaunay_triangulation_off_reader off_reader("some_impossible_weird_file_name.off"); - // Check the read operation was correct - BOOST_CHECK(!off_reader.is_valid()); - T* triangulation = off_reader.get_complex(); - BOOST_CHECK(triangulation == nullptr); -} - -BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_write_test ) -{ - // Read the OFF file (input file name given as parameter) and triangulates points - Gudhi::Delaunay_triangulation_off_reader off_reader("alphacomplexdoc.off"); - - // Retrieve the triangulation - T* triangulation = off_reader.get_complex(); - - // Write the OFF file (output file name given as parameter) with the points and triangulated cells as faces - Gudhi::Delaunay_triangulation_off_writer off_writer("/some_impossible_weird_directory_name/another_weird_directory_name/some_impossible_weird_file_name.off", triangulation); - - // Check the write operation was correct - BOOST_CHECK(!off_writer.is_valid()); - - delete triangulation; -} - diff --git a/src/common/test/points_off_reader_unit_test.cpp b/src/common/test/points_off_reader_unit_test.cpp new file mode 100644 index 00000000..73e19cbc --- /dev/null +++ b/src/common/test/points_off_reader_unit_test.cpp @@ -0,0 +1,78 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +// For CGAL points type in dimension d +// cf. http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Point__d.html +#include + +#include +#include +#include + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "points_off_read_write" +#include + +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; +typedef typename Kernel::Point_d Point_d; + +BOOST_AUTO_TEST_CASE( points_doc_test ) +{ + // Read the OFF file (input file name given as parameter) and triangulates points + Gudhi::Points_off_reader off_reader("alphacomplexdoc.off"); + // Check the read operation was correct + BOOST_CHECK(off_reader.is_valid()); + + // Retrieve the triangulation + std::vector point_cloud = off_reader.get_point_cloud(); + BOOST_CHECK(point_cloud.size() == 7); + + std::vector expected_points; + std::vector point = {1.0, 1.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {7.0, 0.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {4.0, 6.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {9.0, 6.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {0.0, 14.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {2.0, 19.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + point = {9.0, 17.0}; + expected_points.push_back(Point_d(2, point.begin(), point.end())); + + BOOST_CHECK(point_cloud == expected_points); +} + +BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test ) +{ + Gudhi::Points_off_reader off_reader("some_impossible_weird_file_name.off"); + // Check the read operation was correct + BOOST_CHECK(!off_reader.is_valid()); + + std::vector point_cloud = off_reader.get_point_cloud(); + BOOST_CHECK(point_cloud.size() == 0); +} -- cgit v1.2.3 From 01d50e3c77a6f8a2aa7e538f90512482af85d317 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 11:18:19 +0000 Subject: CGAL version requires 4.7 to access CGAL Point_d dimension() function git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1099 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fe6bb4958f7d98427fb705b7c02b64bddb7e190d --- src/common/example/CMakeLists.txt | 4 ++-- src/common/test/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index 2914756e..5aeaa8c6 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -1,9 +1,9 @@ cmake_minimum_required(VERSION 2.6) project(GUDHIDelaunayTriangulationOffFileReadWrite) -# need CGAL 4.6 +# need CGAL 4.7 if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index 6205f0e4..789546ae 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -10,9 +10,9 @@ if (GPROF_PATH) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") endif() -# need CGAL 4.6 +# need CGAL 4.7 if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) message(STATUS "Eigen3 version: ${EIGEN3_VERSION}.") -- cgit v1.2.3 From 8e76285d6d2ea35a9709117896390b718f1f15f1 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 6 Apr 2016 21:11:38 +0000 Subject: Marc review fix cpplint/cppcheck fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1102 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f47277da05debb56dd9a4a96bf89ec7b3ffa2e27 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 22 ++++++++-------------- .../concept/FilteredComplex.h | 2 +- src/common/example/CGAL_points_off_reader.cpp | 1 + src/common/include/gudhi/Off_reader.h | 1 + src/common/include/gudhi/Points_off_io.h | 7 +++---- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 21eb5f48..753fa58a 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -33,7 +33,6 @@ #include #include // isnan, fmax -//#include #include #include #include @@ -79,7 +78,7 @@ class Alpha_complex : public Simplex_tree<> { public: // Add an int in TDS to save point index in the structure typedef CGAL::Triangulation_data_structure, + CGAL::Triangulation_vertex, CGAL::Triangulation_full_cell > TDS; /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ typedef CGAL::Delaunay_triangulation Delaunay_triangulation; @@ -111,13 +110,10 @@ class Alpha_complex : public Simplex_tree<> { // size_type type from CGAL. typedef typename Delaunay_triangulation::size_type size_type; - // Double map type to switch from CGAL vertex iterator to simplex tree vertex handle and vice versa. - typedef typename std::map< CGAL_vertex_iterator, Vertex_handle > Map_vertex_iterator_to_handle; + // Map type to switch from simplex tree vertex handle to CGAL vertex iterator. typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Vector_vertex_iterator; private: - /** \brief Map to switch from CGAL vertex iterator to simplex tree vertex handle.*/ - Map_vertex_iterator_to_handle vertex_iterator_to_handle_; /** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator. * Vertex handles are inserted sequentially, starting at 0.*/ Vector_vertex_iterator vertex_handle_to_iterator_; @@ -198,15 +194,15 @@ class Alpha_complex : public Simplex_tree<> { triangulation_ = new Delaunay_triangulation(point_dimension(*first)); std::vector points(first, last); - + // Creates a vector {0, 1, ..., N-1} std::vector indices(boost::counting_iterator(0), boost::counting_iterator(points.size())); - + // Sort indices considering CGAL spatial sort typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; - spatial_sort(indices.begin(),indices.end(),Search_traits_d(&(points[0]))); - + spatial_sort(indices.begin(), indices.end(), Search_traits_d(&(points[0]))); + typename Delaunay_triangulation::Full_cell_handle hint; for (auto index : indices) { typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(points[index], hint); @@ -261,8 +257,6 @@ class Alpha_complex : public Simplex_tree<> { #ifdef DEBUG_TRACES std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES - - vertex_iterator_to_handle_.emplace(vit, vit->data()); vertex_handle_to_iterator_.emplace(vit->data(), vit); } } @@ -278,10 +272,10 @@ class Alpha_complex : public Simplex_tree<> { for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) { if (*vit != nullptr) { #ifdef DEBUG_TRACES - std::cout << " " << vertex_iterator_to_handle_[*vit]; + std::cout << " " << (*vit)->data(); #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure - vertexVector.push_back(vertex_iterator_to_handle_[*vit]); + vertexVector.push_back((*vit)->data()); } } #ifdef DEBUG_TRACES diff --git a/src/Persistent_cohomology/concept/FilteredComplex.h b/src/Persistent_cohomology/concept/FilteredComplex.h index e124d524..949aafc2 100644 --- a/src/Persistent_cohomology/concept/FilteredComplex.h +++ b/src/Persistent_cohomology/concept/FilteredComplex.h @@ -138,6 +138,6 @@ Filtration_simplex_range filtration_simplex_range(); * @todo use an enum? Just a bool? */ //int is_before_in_filtration(Simplex_handle s, Simplex_handle t); -/*************************************************/ +/*************************************************/ }; diff --git a/src/common/example/CGAL_points_off_reader.cpp b/src/common/example/CGAL_points_off_reader.cpp index 076afd5b..45e9f1e6 100644 --- a/src/common/example/CGAL_points_off_reader.cpp +++ b/src/common/example/CGAL_points_off_reader.cpp @@ -6,6 +6,7 @@ #include #include +#include typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; typedef typename Kernel::Point_d Point_d; diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index 2420ae72..4fcd2af2 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -31,6 +31,7 @@ #include #include #include +#include namespace Gudhi { diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h index d9f9a74b..79287e3c 100644 --- a/src/common/include/gudhi/Points_off_io.h +++ b/src/common/include/gudhi/Points_off_io.h @@ -22,13 +22,13 @@ #ifndef POINTS_OFF_IO_H_ #define POINTS_OFF_IO_H_ +#include + #include #include #include #include -#include - namespace Gudhi { /** @@ -87,7 +87,7 @@ class Points_off_visitor_reader { // Off_reader visitor done implementation - Only points are read void done() { } - + /** \brief Point cloud getter. * * @return point_cloud. @@ -95,7 +95,6 @@ class Points_off_visitor_reader { const std::vector& get_point_cloud() { return point_cloud; } - }; /** -- cgit v1.2.3 From dffe72221d325a446151012121a6ba069319596e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 7 Apr 2016 14:21:31 +0000 Subject: Remove insertion check for duplicate points case. Cpplint fixes git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1103 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7ee7cf0ca7085966039d048199c35b6adf945aa2 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 753fa58a..ca2b68ca 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -126,6 +126,8 @@ class Alpha_complex : public Simplex_tree<> { /** \brief Alpha_complex constructor from an OFF file name. * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize * the Alpha_complex. + * + * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. * * @param[in] off_file_name OFF file [path and] name. * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. @@ -144,11 +146,15 @@ class Alpha_complex : public Simplex_tree<> { /** \brief Alpha_complex constructor from a list of points. * + * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. + * * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$. * * The type InputPointRange must be a range for which std::begin and * std::end return input iterators on a Kernel::Point_d. + * + * @post Compare num_simplices with InputPointRange points number (not the same in case of duplicate points). */ template Alpha_complex(const InputPointRange& points, @@ -210,12 +216,6 @@ class Alpha_complex : public Simplex_tree<> { pos->data() = index; hint = pos->full_cell(); } - - if (triangulation_->number_of_vertices() != (last -first)) { - std::cerr << "Alpha_complex - insertion failed " << triangulation_->number_of_vertices() << " != " << - (last -first) << "\n"; - exit(-1); // ----- >> - } init(max_alpha_square); } } @@ -282,8 +282,7 @@ class Alpha_complex : public Simplex_tree<> { std::cout << std::endl; #endif // DEBUG_TRACES // Insert each simplex and its subfaces in the simplex tree - filtration is NaN - Simplex_result insert_result = insert_simplex_and_subfaces(vertexVector, - std::numeric_limits::quiet_NaN()); + insert_simplex_and_subfaces(vertexVector, std::numeric_limits::quiet_NaN()); } // -------------------------------------------------------------------------------------------- @@ -368,7 +367,9 @@ class Alpha_complex : public Simplex_tree<> { if (decr_dim > 1) { // insert the Tau points in a vector for is_gabriel function Vector_of_CGAL_points pointVector; +#ifdef DEBUG_TRACES Vertex_handle vertexForGabriel = Vertex_handle(); +#endif // DEBUG_TRACES for (auto vertex : simplex_vertex_range(f_boundary)) { pointVector.push_back(get_point(vertex)); } @@ -377,8 +378,10 @@ class Alpha_complex : public Simplex_tree<> { for (auto vertex : simplex_vertex_range(f_simplex)) { point_for_gabriel = get_point(vertex); if (std::find(pointVector.begin(), pointVector.end(), point_for_gabriel) == pointVector.end()) { +#ifdef DEBUG_TRACES // vertex is not found in Tau vertexForGabriel = vertex; +#endif // DEBUG_TRACES // No need to continue loop break; } -- cgit v1.2.3 From e61484887ab37b1295114eca0c8996e98a72e41e Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 7 Apr 2016 15:52:20 +0000 Subject: Fix Doxygen warning git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1104 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c5873a4a207f01e20729d3ce964ae67f6cf55331 --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index afc7d613..f60e5c72 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1191,8 +1191,8 @@ class Simplex_tree { * function is not launching `initialize_filtration()` but returns the filtration modification information. If the * complex has changed , please call `initialize_filtration()` to recompute it. */ - bool prune_above_filtration(Filtration_value filt) { - return rec_prune_above_filtration(root(), filt); + bool prune_above_filtration(Filtration_value filtration) { + return rec_prune_above_filtration(root(), filtration); } private: -- cgit v1.2.3 From 3cabde73eaf1a29f36a6014bccc795349666346c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 7 Apr 2016 16:07:03 +0000 Subject: get_point_cloud can be const git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/alphashapes@1105 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c9b905e8f01c671964b4151883a6385e47adaa06 --- src/common/include/gudhi/Points_off_io.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h index 79287e3c..1bd5c1e6 100644 --- a/src/common/include/gudhi/Points_off_io.h +++ b/src/common/include/gudhi/Points_off_io.h @@ -92,7 +92,7 @@ class Points_off_visitor_reader { * * @return point_cloud. */ - const std::vector& get_point_cloud() { + const std::vector& get_point_cloud() const { return point_cloud; } }; @@ -161,7 +161,7 @@ class Points_off_reader { * * @return point_cloud. */ - const std::vector& get_point_cloud() { + const std::vector& get_point_cloud() const { return point_cloud; } -- cgit v1.2.3