summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2019-01-17 16:15:59 +0000
committervrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2019-01-17 16:15:59 +0000
commit6b70186caa620f9cd734903db978b2117509f8b1 (patch)
treecb2cd36bfbeb480a6e7d7580c48591aa4d9c5440 /src
parenta3b3e527f75ea05a7840ecf73f613f56c3c52273 (diff)
parente105da964b96218459c8822816de36273f6cdf17 (diff)
Merge last trunk modifications
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/cubical_complex_small_fix@4062 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 495752e4da032e54a1a88adbcd030f526bc80a43
Diffstat (limited to 'src')
-rw-r--r--src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp278
-rw-r--r--src/Alpha_complex/benchmark/CMakeLists.txt9
-rw-r--r--src/Alpha_complex/concept/SimplicialComplexForAlpha.h14
-rw-r--r--src/Alpha_complex/concept/SimplicialComplexForAlpha3d.h57
-rw-r--r--src/Alpha_complex/doc/Intro_alpha_complex.h103
-rw-r--r--src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp56
-rw-r--r--src/Alpha_complex/example/Alpha_complex_from_points.cpp20
-rw-r--r--src/Alpha_complex/example/CMakeLists.txt23
-rw-r--r--src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp52
-rw-r--r--src/Alpha_complex/example/weightedalpha3dfrompoints_for_doc.txt31
-rw-r--r--src/Alpha_complex/include/gudhi/Alpha_complex.h83
-rw-r--r--src/Alpha_complex/include/gudhi/Alpha_complex_3d.h584
-rw-r--r--src/Alpha_complex/include/gudhi/Alpha_complex_options.h45
-rw-r--r--src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp164
-rw-r--r--src/Alpha_complex/test/CMakeLists.txt30
-rw-r--r--src/Alpha_complex/test/Periodic_alpha_complex_3d_unit_test.cpp190
-rw-r--r--src/Alpha_complex/test/Weighted_alpha_complex_3d_unit_test.cpp147
-rw-r--r--src/Alpha_complex/test/Weighted_periodic_alpha_complex_3d_unit_test.cpp239
-rw-r--r--src/Alpha_complex/utilities/CMakeLists.txt101
-rw-r--r--src/Alpha_complex/utilities/alpha_complex_3d_helper.h74
-rw-r--r--src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp368
-rw-r--r--src/Alpha_complex/utilities/alphacomplex.md145
-rw-r--r--src/Alpha_complex/utilities/exact_alpha_complex_3d_persistence.cpp265
-rw-r--r--src/Alpha_complex/utilities/periodic_alpha_complex_3d_persistence.cpp302
-rw-r--r--src/Alpha_complex/utilities/weighted_alpha_complex_3d_persistence.cpp316
-rw-r--r--src/Alpha_complex/utilities/weighted_periodic_alpha_complex_3d_persistence.cpp288
-rw-r--r--src/Bottleneck_distance/utilities/bottleneckdistance.md2
-rw-r--r--src/CMakeLists.txt12
-rw-r--r--src/GudhUI/CMakeLists.txt81
-rw-r--r--src/Nerve_GIC/include/gudhi/GIC.h88
-rw-r--r--src/Rips_complex/doc/Intro_rips_complex.h7
-rw-r--r--src/Rips_complex/utilities/ripscomplex.md4
-rw-r--r--src/Simplex_tree/include/gudhi/Simplex_tree.h116
-rw-r--r--src/Simplex_tree/test/CMakeLists.txt8
-rw-r--r--src/Simplex_tree/test/simplex_tree_ctor_and_move_unit_test.cpp137
-rw-r--r--src/Tangential_complex/include/gudhi/Tangential_complex.h57
-rw-r--r--src/Witness_complex/utilities/witnesscomplex.md2
-rw-r--r--src/cmake/modules/GUDHI_compilation_flags.cmake13
-rw-r--r--src/cmake/modules/GUDHI_doxygen_target.cmake8
-rw-r--r--src/cmake/modules/GUDHI_modules.cmake5
-rw-r--r--src/cmake/modules/GUDHI_third_party_libraries.cmake11
-rw-r--r--src/common/doc/examples.h5
-rw-r--r--src/common/doc/installation.h34
-rw-r--r--src/common/doc/main_page.h7
-rw-r--r--src/common/include/gudhi/Unitary_tests_utils.h2
-rw-r--r--src/cython/CMakeLists.txt689
-rw-r--r--src/cython/cython/nerve_gic.pyx30
-rw-r--r--[-rwxr-xr-x]src/cython/cython/persistence_graphical_tools.py310
-rw-r--r--src/cython/cython/rips_complex.pyx56
-rw-r--r--src/cython/cython/simplex_tree.pyx14
-rw-r--r--src/cython/doc/examples.rst1
-rw-r--r--src/cython/doc/installation.rst11
-rw-r--r--src/cython/doc/nerve_gic_complex_sum.rst2
-rw-r--r--src/cython/doc/persistence_graphical_tools_ref.rst1
-rw-r--r--src/cython/doc/persistence_graphical_tools_sum.inc4
-rw-r--r--src/cython/doc/persistence_graphical_tools_user.rst37
-rw-r--r--src/cython/doc/persistent_cohomology_user.rst14
-rw-r--r--src/cython/doc/rips_complex_sum.inc6
-rw-r--r--src/cython/doc/rips_complex_user.rst67
-rwxr-xr-xsrc/cython/example/sparse_rips_persistence_diagram.py43
-rw-r--r--src/cython/include/Alpha_complex_interface.h2
-rw-r--r--src/cython/include/Rips_complex_interface.h41
-rwxr-xr-xsrc/cython/test/test_rips_complex.py20
63 files changed, 3621 insertions, 2310 deletions
diff --git a/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp b/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp
new file mode 100644
index 00000000..005a712a
--- /dev/null
+++ b/src/Alpha_complex/benchmark/Alpha_complex_3d_benchmark.cpp
@@ -0,0 +1,278 @@
+#include <gudhi/Alpha_complex_3d.h>
+#include <gudhi/Alpha_complex.h>
+// to construct a simplex_tree from alpha complex
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/random_point_generators.h>
+#include <gudhi/Clock.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <limits> // for numeric limits
+#include <fstream>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Epeck_d.h>
+#include <CGAL/Random.h>
+
+std::ofstream results_csv("results.csv");
+
+template <typename Kernel>
+void benchmark_points_on_torus_dD(const std::string& msg) {
+ std::cout << "+ " << msg << std::endl;
+
+ results_csv << "\"" << msg << "\";" << std::endl;
+ results_csv << "\"nb_points\";"
+ << "\"nb_simplices\";"
+ << "\"alpha_creation_time(sec.)\";"
+ << "\"complex_creation_time(sec.)\";" << std::endl;
+
+ using K = CGAL::Epick_d<CGAL::Dimension_tag<3>>;
+ for (int nb_points = 1000; nb_points <= 125000; nb_points *= 5) {
+ std::cout << " Alpha complex dD on torus with " << nb_points << " points." << std::endl;
+ std::vector<K::Point_d> points_on_torus = Gudhi::generate_points_on_torus_3D<K>(nb_points, 1.0, 0.5);
+ std::vector<typename Kernel::Point_d> points;
+
+ for (auto p : points_on_torus) {
+ points.push_back(typename Kernel::Point_d(p.begin(), p.end()));
+ }
+
+ Gudhi::Clock ac_create_clock(" benchmark_points_on_torus_dD - Alpha complex 3d creation");
+ ac_create_clock.begin();
+ Gudhi::alpha_complex::Alpha_complex<Kernel> alpha_complex_from_points(points);
+ ac_create_clock.end();
+ std::cout << ac_create_clock;
+
+ Gudhi::Simplex_tree<> complex;
+ Gudhi::Clock st_create_clock(" benchmark_points_on_torus_dD - complex creation");
+ st_create_clock.begin();
+ alpha_complex_from_points.create_complex(complex);
+ st_create_clock.end();
+ std::cout << st_create_clock;
+
+ results_csv << nb_points << ";" << complex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";"
+ << st_create_clock.num_seconds() << ";" << std::endl;
+
+ std::cout << " benchmark_points_on_torus_dD - nb simplices = " << complex.num_simplices() << std::endl;
+ }
+}
+
+template <typename Alpha_complex_3d>
+void benchmark_points_on_torus_3D(const std::string& msg) {
+ using K = CGAL::Epick_d<CGAL::Dimension_tag<3>>;
+ std::cout << "+ " << msg << std::endl;
+
+ results_csv << "\"" << msg << "\";" << std::endl;
+ results_csv << "\"nb_points\";"
+ << "\"nb_simplices\";"
+ << "\"alpha_creation_time(sec.)\";"
+ << "\"complex_creation_time(sec.)\";" << std::endl;
+
+ for (int nb_points = 1000; nb_points <= 125000; nb_points *= 5) {
+ std::cout << " Alpha complex 3d on torus with " << nb_points << " points." << std::endl;
+ std::vector<K::Point_d> points_on_torus = Gudhi::generate_points_on_torus_3D<K>(nb_points, 1.0, 0.5);
+ std::vector<typename Alpha_complex_3d::Point_3> points;
+
+ for (auto p : points_on_torus) {
+ points.push_back(typename Alpha_complex_3d::Point_3(p[0], p[1], p[2]));
+ }
+
+ Gudhi::Clock ac_create_clock(" benchmark_points_on_torus_3D - Alpha complex 3d creation");
+ ac_create_clock.begin();
+ Alpha_complex_3d alpha_complex_from_points(points);
+ ac_create_clock.end();
+ std::cout << ac_create_clock;
+
+ Gudhi::Simplex_tree<> complex;
+ Gudhi::Clock st_create_clock(" benchmark_points_on_torus_3D - complex creation");
+ st_create_clock.begin();
+ alpha_complex_from_points.create_complex(complex);
+ st_create_clock.end();
+ std::cout << st_create_clock;
+
+ results_csv << nb_points << ";" << complex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";"
+ << st_create_clock.num_seconds() << ";" << std::endl;
+
+ std::cout << " benchmark_points_on_torus_3D - nb simplices = " << complex.num_simplices() << std::endl;
+ }
+}
+
+template <typename Weighted_alpha_complex_3d>
+void benchmark_weighted_points_on_torus_3D(const std::string& msg) {
+ using K = CGAL::Epick_d<CGAL::Dimension_tag<3>>;
+
+ std::cout << "+ " << msg << std::endl;
+
+ results_csv << "\"" << msg << "\";" << std::endl;
+ results_csv << "\"nb_points\";"
+ << "\"nb_simplices\";"
+ << "\"alpha_creation_time(sec.)\";"
+ << "\"complex_creation_time(sec.)\";" << std::endl;
+
+ CGAL::Random random(8);
+
+ for (int nb_points = 1000; nb_points <= 125000; nb_points *= 5) {
+ std::cout << " Alpha complex 3d on torus with " << nb_points << " points." << std::endl;
+ std::vector<K::Point_d> points_on_torus = Gudhi::generate_points_on_torus_3D<K>(nb_points, 1.0, 0.5);
+
+ using Point = typename Weighted_alpha_complex_3d::Point_3;
+ using Weighted_point = typename Weighted_alpha_complex_3d::Weighted_point_3;
+
+ std::vector<Weighted_point> points;
+
+ for (auto p : points_on_torus) {
+ points.push_back(Weighted_point(Point(p[0], p[1], p[2]), 0.9 + random.get_double(0., 0.01)));
+ }
+
+ Gudhi::Clock ac_create_clock(" benchmark_weighted_points_on_torus_3D - Alpha complex 3d creation");
+ ac_create_clock.begin();
+ Weighted_alpha_complex_3d alpha_complex_from_points(points);
+ ac_create_clock.end();
+ std::cout << ac_create_clock;
+
+ Gudhi::Simplex_tree<> complex;
+ Gudhi::Clock st_create_clock(" benchmark_weighted_points_on_torus_3D - complex creation");
+ st_create_clock.begin();
+ alpha_complex_from_points.create_complex(complex);
+ st_create_clock.end();
+ std::cout << st_create_clock;
+
+ results_csv << nb_points << ";" << complex.num_simplices() << ";" << ac_create_clock.num_seconds() << ";"
+ << st_create_clock.num_seconds() << ";" << std::endl;
+
+ std::cout << " benchmark_weighted_points_on_torus_3D - nb simplices = " << complex.num_simplices() << std::endl;
+ }
+}
+
+template <typename Periodic_alpha_complex_3d>
+void benchmark_periodic_points(const std::string& msg) {
+ std::cout << "+ " << msg << std::endl;
+
+ results_csv << "\"" << msg << "\";" << std::endl;
+ results_csv << "\"nb_points\";"
+ << "\"nb_simplices\";"
+ << "\"alpha_creation_time(sec.)\";"
+ << "\"complex_creation_time(sec.)\";" << std::endl;
+
+ CGAL::Random random(8);
+
+ for (double nb_points = 10.; nb_points <= 40.; nb_points += 10.) {
+ std::cout << " Periodic alpha complex 3d with " << nb_points * nb_points * nb_points << " points." << std::endl;
+ using Point = typename Periodic_alpha_complex_3d::Point_3;
+ std::vector<Point> points;
+
+ for (double i = 0; i < nb_points; i++) {
+ for (double j = 0; j < nb_points; j++) {
+ for (double k = 0; k < nb_points; k++) {
+ points.push_back(
+ Point(i + random.get_double(0., 0.1), j + random.get_double(0., 0.1), k + random.get_double(0., 0.1)));
+ }
+ }
+ }
+
+ Gudhi::Clock ac_create_clock(" benchmark_periodic_points - Alpha complex 3d creation");
+ ac_create_clock.begin();
+ Periodic_alpha_complex_3d alpha_complex_from_points(points, 0., 0., 0., nb_points, nb_points, nb_points);
+ ac_create_clock.end();
+ std::cout << ac_create_clock;
+
+ Gudhi::Simplex_tree<> complex;
+ Gudhi::Clock st_create_clock(" benchmark_periodic_points - complex creation");
+ st_create_clock.begin();
+ alpha_complex_from_points.create_complex(complex);
+ st_create_clock.end();
+ std::cout << st_create_clock;
+
+ results_csv << nb_points * nb_points * nb_points << ";" << complex.num_simplices() << ";"
+ << ac_create_clock.num_seconds() << ";" << st_create_clock.num_seconds() << ";" << std::endl;
+
+ std::cout << " benchmark_periodic_points - nb simplices = " << complex.num_simplices() << std::endl;
+ }
+}
+
+template <typename Weighted_periodic_alpha_complex_3d>
+void benchmark_weighted_periodic_points(const std::string& msg) {
+ std::cout << "+ " << msg << std::endl;
+
+ results_csv << "\"" << msg << "\";" << std::endl;
+ results_csv << "\"nb_points\";"
+ << "\"nb_simplices\";"
+ << "\"alpha_creation_time(sec.)\";"
+ << "\"complex_creation_time(sec.)\";" << std::endl;
+
+ CGAL::Random random(8);
+
+ for (double nb_points = 10.; nb_points <= 40.; nb_points += 10.) {
+ std::cout << " Weighted periodic alpha complex 3d with " << nb_points * nb_points * nb_points << " points."
+ << std::endl;
+
+ using Point = typename Weighted_periodic_alpha_complex_3d::Point_3;
+ using Weighted_point = typename Weighted_periodic_alpha_complex_3d::Weighted_point_3;
+ std::vector<Weighted_point> points;
+
+ for (double i = 0; i < nb_points; i++) {
+ for (double j = 0; j < nb_points; j++) {
+ for (double k = 0; k < nb_points; k++) {
+ points.push_back(Weighted_point(
+ Point(i + random.get_double(0., 0.1), j + random.get_double(0., 0.1), k + random.get_double(0., 0.1)),
+ random.get_double(0., (nb_points * nb_points) / 64.)));
+ }
+ }
+ }
+
+ Gudhi::Clock ac_create_clock(" benchmark_weighted_periodic_points - Alpha complex 3d creation");
+ ac_create_clock.begin();
+ Weighted_periodic_alpha_complex_3d alpha_complex_from_points(points, 0., 0., 0., nb_points, nb_points, nb_points);
+ ac_create_clock.end();
+ std::cout << ac_create_clock;
+
+ Gudhi::Simplex_tree<> complex;
+ Gudhi::Clock st_create_clock(" benchmark_weighted_periodic_points - complex creation");
+ st_create_clock.begin();
+ alpha_complex_from_points.create_complex(complex);
+ st_create_clock.end();
+ std::cout << st_create_clock;
+
+ results_csv << nb_points * nb_points * nb_points << ";" << complex.num_simplices() << ";"
+ << ac_create_clock.num_seconds() << ";" << st_create_clock.num_seconds() << ";" << std::endl;
+
+ std::cout << " benchmark_weighted_periodic_points - nb simplices = " << complex.num_simplices() << std::endl;
+ }
+}
+
+int main(int argc, char** argv) {
+ benchmark_points_on_torus_dD<CGAL::Epick_d<CGAL::Dimension_tag<3>>>("Fast static dimension version");
+ benchmark_points_on_torus_dD<CGAL::Epick_d<CGAL::Dynamic_dimension_tag>>("Fast dynamic dimension version");
+ benchmark_points_on_torus_dD<CGAL::Epeck_d<CGAL::Dimension_tag<3>>>("Exact static dimension version");
+ benchmark_points_on_torus_dD<CGAL::Epeck_d<CGAL::Dynamic_dimension_tag>>("Exact dynamic dimension version");
+
+ benchmark_points_on_torus_3D<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, false, false>>("Fast version");
+ benchmark_points_on_torus_3D<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, false>>("Safe version");
+ benchmark_points_on_torus_3D<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, false>>("Exact version");
+
+ benchmark_weighted_points_on_torus_3D<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, false>>("Fast version");
+ benchmark_weighted_points_on_torus_3D<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, false>>("Safe version");
+ benchmark_weighted_points_on_torus_3D<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, false>>("Exact version");
+
+ benchmark_periodic_points<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, false, true>>("Fast version");
+ benchmark_periodic_points<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, true>>("Safe version");
+ benchmark_periodic_points<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, true>>("Exact version");
+
+ benchmark_weighted_periodic_points<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, true>>("Fast version");
+ benchmark_weighted_periodic_points<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, true>>("Safe version");
+ benchmark_weighted_periodic_points<
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, true>>("Exact version");
+
+ return 0;
+}
diff --git a/src/Alpha_complex/benchmark/CMakeLists.txt b/src/Alpha_complex/benchmark/CMakeLists.txt
new file mode 100644
index 00000000..622963dc
--- /dev/null
+++ b/src/Alpha_complex/benchmark/CMakeLists.txt
@@ -0,0 +1,9 @@
+project(Alpha_complex_benchmark)
+
+if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ add_executable(Alpha_complex_3d_benchmark Alpha_complex_3d_benchmark.cpp)
+ target_link_libraries(Alpha_complex_3d_benchmark ${CGAL_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(Alpha_complex_3d_benchmark ${TBB_LIBRARIES})
+ endif()
+endif ()
diff --git a/src/Alpha_complex/concept/SimplicialComplexForAlpha.h b/src/Alpha_complex/concept/SimplicialComplexForAlpha.h
index a51df127..ba97c802 100644
--- a/src/Alpha_complex/concept/SimplicialComplexForAlpha.h
+++ b/src/Alpha_complex/concept/SimplicialComplexForAlpha.h
@@ -41,9 +41,6 @@ struct SimplicialComplexForAlpha {
/** Returns the number of vertices in the simplicial complex. */
std::size_t num_vertices();
- /** Sets the simplicial complex dimension. */
- void set_dimension(int dimension);
-
/** Gets the 'simplex' dimension. */
int dimension(Simplex_handle simplex);
@@ -65,8 +62,7 @@ struct SimplicialComplexForAlpha {
* 'value type' must be 'Vertex_handle'.*/
typedef unspecified Simplex_vertex_range;
- /** \brief Returns a range over vertices of a given
- * simplex. */
+ /** \brief Returns a range over vertices of a given simplex. */
Simplex_vertex_range simplex_vertex_range(Simplex_handle const & simplex);
/** \brief Iterator over the boundaries of the complex, in an arbitrary order.
@@ -77,6 +73,14 @@ struct SimplicialComplexForAlpha {
/** \brief Returns a range over boundaries of a given simplex. */
Boundary_simplex_range boundary_simplex_range(Simplex_handle const & simplex);
+ /** \brief Iterator over the simplices of the skeleton of the complex, for a given dimension.
+ *
+ * 'value_type' must be 'Simplex_handle'. */
+ typedef unspecified Skeleton_simplex_range;
+ /** \brief Returns a range over the simplices of the skeleton of the simplicial complex, for a given
+ * dimension. */
+ Skeleton_simplex_range skeleton_simplex_range;
+
/** \brief Return type of an insertion of a simplex
*/
typedef unspecified Insertion_result_type;
diff --git a/src/Alpha_complex/concept/SimplicialComplexForAlpha3d.h b/src/Alpha_complex/concept/SimplicialComplexForAlpha3d.h
new file mode 100644
index 00000000..7acdf105
--- /dev/null
+++ b/src/Alpha_complex/concept/SimplicialComplexForAlpha3d.h
@@ -0,0 +1,57 @@
+/* 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) 2018 Inria
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CONCEPT_ALPHA_COMPLEX_SIMPLICIAL_COMPLEX_FOR_ALPHA_3D_H_
+#define CONCEPT_ALPHA_COMPLEX_SIMPLICIAL_COMPLEX_FOR_ALPHA_3D_H_
+
+namespace Gudhi {
+
+namespace alpha_complex {
+
+/** \brief The concept SimplicialComplexForAlpha3d describes the requirements for a type to implement a simplicial
+ * complex, that can be created from a `Alpha_complex_3d`.
+ */
+struct SimplicialComplexForAlpha3d {
+ /** Handle to specify a vertex. Must be a non-negative integer. */
+ typedef unspecified Vertex_handle;
+ /** Handle to specify the simplex filtration value. */
+ typedef unspecified Filtration_value;
+
+ /** Returns the number of vertices in the simplicial complex. */
+ std::size_t num_vertices();
+
+ /** \brief Inserts a simplex from a given simplex (represented by a vector of Vertex_handle) in the
+ * simplicial complex with the given 'filtration' value. */
+ void insert_simplex(std::vector<Vertex_handle> const& vertex_range, Filtration_value filtration);
+
+ /** Browses the simplicial complex to make the filtration non-decreasing. */
+ void make_filtration_non_decreasing();
+
+ /** Prune the simplicial complex above 'filtration' value given as parameter. */
+ void prune_above_filtration(Filtration_value filtration);
+};
+
+} // namespace alpha_complex
+
+} // namespace Gudhi
+
+#endif // CONCEPT_ALPHA_COMPLEX_SIMPLICIAL_COMPLEX_FOR_ALPHA_3D_H_
diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h
index 7a375c9f..ab7c4794 100644
--- a/src/Alpha_complex/doc/Intro_alpha_complex.h
+++ b/src/Alpha_complex/doc/Intro_alpha_complex.h
@@ -29,34 +29,34 @@ namespace Gudhi {
namespace alpha_complex {
/** \defgroup alpha_complex Alpha complex
- *
+ *
* \author Vincent Rouvreau
*
* @{
- *
+ *
* \section definition Definition
- *
+ *
* Alpha_complex is a <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a>
* constructed from the finite cells of a Delaunay Triangulation.
- *
+ *
* The filtration value of each simplex is computed as the square of the circumradius of the simplex if the
* circumsphere is empty (the simplex is then said to be Gabriel), and as the minimum of the filtration
* values of the codimension 1 cofaces that make it not Gabriel otherwise.
- *
+ *
* All simplices that have a filtration value strictly greater than a given alpha squared value are not inserted into
* the complex.
- *
+ *
* \image html "alpha_complex_representation.png" "Alpha-complex representation"
- *
+ *
* Alpha_complex is constructing a <a target="_blank"
* href="http://doc.cgal.org/latest/Triangulation/index.html#Chapter_Triangulations">Delaunay Triangulation</a>
* \cite cgal:hdj-t-15b from <a target="_blank" href="http://www.cgal.org/">CGAL</a> (the Computational Geometry
* Algorithms Library \cite cgal:eb-15b) and is able to create a `SimplicialComplexForAlpha`.
- *
+ *
* The complex is a template class requiring an Epick_d <a target="_blank"
* href="http://doc.cgal.org/latest/Kernel_d/index.html#Chapter_dD_Geometry_Kernel">dD Geometry Kernel</a>
* \cite cgal:s-gkd-15b from CGAL as template parameter.
- *
+ *
* \remark
* - When the simplicial complex is constructed with an infinite value of alpha, the complex is a Delaunay
* complex.
@@ -65,30 +65,30 @@ namespace alpha_complex {
* \ref cech_complex can still make sense in higher dimension precisely because you can bound the radii.
*
* \section pointsexample Example from points
- *
+ *
* This example builds the Delaunay triangulation from the given points in a 2D static kernel, and creates a
* `Simplex_tree` with it.
- *
+ *
* Then, it is asked to display information about the simplicial complex.
- *
+ *
* \include Alpha_complex/Alpha_complex_from_points.cpp
- *
+ *
* When launching:
- *
+ *
* \code $> ./Alpha_complex_example_from_points
* \endcode
*
* the program output is:
- *
+ *
* \include Alpha_complex/alphaoffreader_for_doc_60.txt
- *
+ *
* \section createcomplexalgorithm Create complex algorithm
- *
+ *
* \subsection datastructure Data structure
- *
+ *
* In order to create the simplicial complex, first, it is built from the cells of the Delaunay Triangulation.
* The filtration values are set to NaN, which stands for unknown value.
- *
+ *
* In example, :
* \image html "alpha_complex_doc.png" "Simplicial complex structure construction example"
*
@@ -106,7 +106,7 @@ namespace alpha_complex {
* \quad\quad\quad\quad \text{filtration(} \tau \text{) = min( filtration(} \tau \text{), filtration(} \sigma
* \text{) )}\\
* \quad\quad\quad \textbf{else}\\
- * \quad\quad\quad\quad \textbf{if } \textbf{if } \tau \text{ is not Gabriel for } \sigma \textbf{ then}\\
+ * \quad\quad\quad\quad \textbf{if } \tau \text{ is not Gabriel for } \sigma \textbf{ then}\\
* \quad\quad\quad\quad\quad \text{filtration(} \tau \text{) = filtration(} \sigma \text{)}\\
* \quad\quad\quad\quad \textbf{end if}\\
* \quad\quad\quad \textbf{end if}\\
@@ -118,53 +118,78 @@ namespace alpha_complex {
* \f$
*
* \subsubsection dimension2 Dimension 2
- *
+ *
* 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_420.png" "Filtration value propagation example"
- *
+ *
* \subsubsection dimension1 Dimension 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
- *
+ *
* 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
- *
+ *
* 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 `SimplicialComplexForAlpha::make_filtration_non_decreasing()`.
- *
+ *
* \subsubsection pruneabove Prune above given filtration value
- *
+ *
* The simplex tree is pruned from the given maximum alpha squared value (cf.
* `SimplicialComplexForAlpha::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
- *
+ *
* 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/Alpha_complex_from_off.cpp
- *
+ *
* When launching:
- *
+ *
* \code $> ./Alpha_complex_example_from_off ../../data/points/alphacomplexdoc.off 32.0
* \endcode
*
* the program output is:
- *
+ *
* \include Alpha_complex/alphaoffreader_for_doc_32.txt
- *
+ *
+ *
+ * \section weighted3dexample 3d specific example
+ *
+ * A specific module for Alpha complex is available in 3d (cf. Alpha_complex_3d) and allows to construct standard,
+ * weighted, periodic or weighted and periodic versions of alpha complexes. Alpha values computation can be
+ * Gudhi::alpha_complex::complexity::FAST, Gudhi::alpha_complex::complexity::SAFE (default value) or
+ * Gudhi::alpha_complex::complexity::EXACT.
+ *
+ * This example builds the CGAL 3d weighted alpha shapes from a small molecule, and initializes the alpha complex with
+ * it. This example is taken from <a href="https://doc.cgal.org/latest/Alpha_shapes_3/index.html#title13">CGAL 3d
+ * weighted alpha shapes</a>.
+ *
+ * Then, it is asked to display information about the alpha complex.
+ *
+ * \include Alpha_complex/Weighted_alpha_complex_3d_from_points.cpp
+ *
+ * When launching:
+ *
+ * \code $> ./Alpha_complex_example_weighted_3d_from_points
+ * \endcode
+ *
+ * the program output is:
+ *
+ * \include Alpha_complex/weightedalpha3dfrompoints_for_doc.txt
+ *
*/
/** @} */ // end defgroup alpha_complex
diff --git a/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp
new file mode 100644
index 00000000..0e359a27
--- /dev/null
+++ b/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp
@@ -0,0 +1,56 @@
+#include <gudhi/Alpha_complex_3d.h>
+// to construct a simplex_tree from alpha complex
+#include <gudhi/Simplex_tree.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <limits> // for numeric limits
+
+using Alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, false>;
+using Point = Alpha_complex_3d::Point_3;
+using Vector_of_points = std::vector<Point>;
+
+int main(int argc, char **argv) {
+ if (argc != 1) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n";
+ std::cerr << "Usage: " << (argv[0] - 1) << " \n";
+ exit(-1); // ----- >>
+ }
+
+ // ----------------------------------------------------------------------------
+ // Init of a list of points from a small molecule
+ // ----------------------------------------------------------------------------
+ Vector_of_points points;
+ points.push_back(Point(1, -1, -1));
+ points.push_back(Point(-1, 1, -1));
+ points.push_back(Point(-1, -1, 1));
+ points.push_back(Point(1, 1, 1));
+ points.push_back(Point(2, 2, 2));
+
+ // ----------------------------------------------------------------------------
+ // Init of an alpha complex from the list of points
+ // ----------------------------------------------------------------------------
+ Alpha_complex_3d alpha_complex_from_points(points);
+
+ Gudhi::Simplex_tree<> simplex;
+ if (alpha_complex_from_points.create_complex(simplex)) {
+ // ----------------------------------------------------------------------------
+ // Display information about the alpha complex
+ // ----------------------------------------------------------------------------
+ std::cout << "Alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices()
+ << " simplices - " << simplex.num_vertices() << " vertices." << std::endl;
+
+ std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl;
+ for (auto f_simplex : simplex.filtration_simplex_range()) {
+ std::cout << " ( ";
+ for (auto vertex : simplex.simplex_vertex_range(f_simplex)) {
+ std::cout << vertex << " ";
+ }
+ std::cout << ") -> "
+ << "[" << simplex.filtration(f_simplex) << "] ";
+ std::cout << std::endl;
+ }
+ }
+ 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 c19f7cc8..981aa470 100644
--- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp
+++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp
@@ -5,29 +5,13 @@
#include <CGAL/Epick_d.h>
#include <iostream>
-#include <string>
#include <vector>
-#include <limits> // for numeric limits
using Kernel = CGAL::Epick_d< CGAL::Dimension_tag<2> >;
using Point = Kernel::Point_d;
using Vector_of_points = std::vector<Point>;
-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) {
- 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<double>::infinity()};
- if (argc == 2)
- alpha_square_max_value = atof(argv[1]);
-
+int main() {
// ----------------------------------------------------------------------------
// Init of a list of points
// ----------------------------------------------------------------------------
@@ -46,7 +30,7 @@ int main(int argc, char **argv) {
Gudhi::alpha_complex::Alpha_complex<Kernel> alpha_complex_from_points(points);
Gudhi::Simplex_tree<> simplex;
- if (alpha_complex_from_points.create_complex(simplex, alpha_square_max_value)) {
+ if (alpha_complex_from_points.create_complex(simplex)) {
// ----------------------------------------------------------------------------
// Display information about the alpha complex
// ----------------------------------------------------------------------------
diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt
index 2fc62452..c62a220c 100644
--- a/src/Alpha_complex/example/CMakeLists.txt
+++ b/src/Alpha_complex/example/CMakeLists.txt
@@ -1,7 +1,5 @@
project(Alpha_complex_examples)
-# need CGAL 4.7
-# cmake -DCGAL_DIR=~/workspace/CGAL-4.7 ..
if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
add_executable ( Alpha_complex_example_from_points Alpha_complex_from_points.cpp )
target_link_libraries(Alpha_complex_example_from_points ${CGAL_LIBRARY})
@@ -28,8 +26,23 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
add_test(Alpha_complex_example_from_off_32_diff_files ${DIFF_PATH}
${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt)
endif()
+endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
- install(TARGETS Alpha_complex_example_from_points DESTINATION bin)
- install(TARGETS Alpha_complex_example_from_off DESTINATION bin)
+if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ add_executable ( Alpha_complex_example_weighted_3d_from_points Weighted_alpha_complex_3d_from_points.cpp )
+ target_link_libraries(Alpha_complex_example_weighted_3d_from_points ${CGAL_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(Alpha_complex_example_weighted_3d_from_points ${TBB_LIBRARIES})
+ endif()
+ add_test(NAME Alpha_complex_example_weighted_3d_from_points
+ COMMAND $<TARGET_FILE:Alpha_complex_example_weighted_3d_from_points>)
-endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
+ add_executable ( Alpha_complex_example_3d_from_points Alpha_complex_3d_from_points.cpp )
+ target_link_libraries(Alpha_complex_example_3d_from_points ${CGAL_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(Alpha_complex_example_3d_from_points ${TBB_LIBRARIES})
+ endif()
+ add_test(NAME Alpha_complex_example_3d_from_points
+ COMMAND $<TARGET_FILE:Alpha_complex_example_3d_from_points>)
+
+endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp
new file mode 100644
index 00000000..ac11b68c
--- /dev/null
+++ b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp
@@ -0,0 +1,52 @@
+#include <gudhi/Alpha_complex_3d.h>
+// to construct a simplex_tree from alpha complex
+#include <gudhi/Simplex_tree.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <limits> // for numeric limits
+
+// Complexity = FAST, weighted = true, periodic = false
+using Weighted_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, false>;
+using Point = Weighted_alpha_complex_3d::Point_3;
+using Weighted_point = Weighted_alpha_complex_3d::Weighted_point_3;
+
+int main(int argc, char **argv) {
+ // ----------------------------------------------------------------------------
+ // Init of a list of points and weights from a small molecule
+ // ----------------------------------------------------------------------------
+ std::vector<Weighted_point> weighted_points;
+ weighted_points.push_back(Weighted_point(Point(1, -1, -1), 4.));
+ weighted_points.push_back(Weighted_point(Point(-1, 1, -1), 4.));
+ weighted_points.push_back(Weighted_point(Point(-1, -1, 1), 4.));
+ weighted_points.push_back(Weighted_point(Point(1, 1, 1), 4.));
+ weighted_points.push_back(Weighted_point(Point(2, 2, 2), 1.));
+
+ // ----------------------------------------------------------------------------
+ // Init of an alpha complex from the list of points
+ // ----------------------------------------------------------------------------
+ Weighted_alpha_complex_3d alpha_complex_from_points(weighted_points);
+
+ Gudhi::Simplex_tree<> simplex;
+ if (alpha_complex_from_points.create_complex(simplex)) {
+ // ----------------------------------------------------------------------------
+ // Display information about the alpha complex
+ // ----------------------------------------------------------------------------
+ std::cout << "Alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices()
+ << " simplices - " << simplex.num_vertices() << " vertices." << std::endl;
+
+ std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl;
+ for (auto f_simplex : simplex.filtration_simplex_range()) {
+ std::cout << " ( ";
+ for (auto vertex : simplex.simplex_vertex_range(f_simplex)) {
+ std::cout << vertex << " ";
+ }
+ std::cout << ") -> "
+ << "[" << simplex.filtration(f_simplex) << "] ";
+ std::cout << std::endl;
+ }
+ }
+ return 0;
+}
diff --git a/src/Alpha_complex/example/weightedalpha3dfrompoints_for_doc.txt b/src/Alpha_complex/example/weightedalpha3dfrompoints_for_doc.txt
new file mode 100644
index 00000000..7a09998d
--- /dev/null
+++ b/src/Alpha_complex/example/weightedalpha3dfrompoints_for_doc.txt
@@ -0,0 +1,31 @@
+Alpha complex is of dimension 3 - 29 simplices - 5 vertices.
+Iterator on alpha complex simplices in the filtration order, with [filtration value]:
+ ( 0 ) -> [-4]
+ ( 1 ) -> [-4]
+ ( 2 ) -> [-4]
+ ( 3 ) -> [-4]
+ ( 1 0 ) -> [-2]
+ ( 2 0 ) -> [-2]
+ ( 2 1 ) -> [-2]
+ ( 3 0 ) -> [-2]
+ ( 3 1 ) -> [-2]
+ ( 3 2 ) -> [-2]
+ ( 2 1 0 ) -> [-1.33333]
+ ( 3 1 0 ) -> [-1.33333]
+ ( 3 2 0 ) -> [-1.33333]
+ ( 3 2 1 ) -> [-1.33333]
+ ( 3 2 1 0 ) -> [-1]
+ ( 4 ) -> [-1]
+ ( 4 2 ) -> [-1]
+ ( 4 0 ) -> [23]
+ ( 4 1 ) -> [23]
+ ( 4 2 0 ) -> [23]
+ ( 4 2 1 ) -> [23]
+ ( 4 3 ) -> [23]
+ ( 4 3 2 ) -> [23]
+ ( 4 1 0 ) -> [95]
+ ( 4 2 1 0 ) -> [95]
+ ( 4 3 0 ) -> [95]
+ ( 4 3 1 ) -> [95]
+ ( 4 3 2 0 ) -> [95]
+ ( 4 3 2 1 ) -> [95]
diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h
index 4c07eddb..af9f59ea 100644
--- a/src/Alpha_complex/include/gudhi/Alpha_complex.h
+++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h
@@ -228,19 +228,14 @@ class Alpha_complex {
}
public:
- template <typename SimplicialComplexForAlpha>
- bool create_complex(SimplicialComplexForAlpha& complex) {
- typedef typename SimplicialComplexForAlpha::Filtration_value Filtration_value;
- return create_complex(complex, std::numeric_limits<Filtration_value>::infinity());
- }
-
/** \brief Inserts all Delaunay triangulation into the simplicial complex.
* It also computes the filtration values accordingly to the \ref createcomplexalgorithm
*
* \tparam SimplicialComplexForAlpha must meet `SimplicialComplexForAlpha` concept.
*
* @param[in] complex SimplicialComplexForAlpha to be created.
- * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$.
+ * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$, and there is very
+ * little point using anything else since it does not save time.
*
* @return true if creation succeeds, false otherwise.
*
@@ -249,8 +244,10 @@ class Alpha_complex {
*
* Initialization can be launched once.
*/
- template <typename SimplicialComplexForAlpha, typename Filtration_value>
- bool create_complex(SimplicialComplexForAlpha& complex, Filtration_value max_alpha_square) {
+ template <typename SimplicialComplexForAlpha,
+ typename Filtration_value = typename SimplicialComplexForAlpha::Filtration_value>
+ bool create_complex(SimplicialComplexForAlpha& complex,
+ Filtration_value max_alpha_square = std::numeric_limits<Filtration_value>::infinity()) {
// From SimplicialComplexForAlpha type required to insert into a simplicial complex (with or without subfaces).
typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle;
typedef typename SimplicialComplexForAlpha::Simplex_handle Simplex_handle;
@@ -272,7 +269,9 @@ class Alpha_complex {
// --------------------------------------------------------------------------------------------
// Simplex_tree construction from loop on triangulation finite full cells list
if (triangulation_->number_of_vertices() > 0) {
- for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) {
+ 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 ";
@@ -333,7 +332,9 @@ class Alpha_complex {
std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << complex.filtration(f_simplex) << std::endl;
#endif // DEBUG_TRACES
}
- propagate_alpha_filtration(complex, f_simplex, decr_dim);
+ // No need to propagate further, unweighted points all have value 0
+ if (decr_dim > 1)
+ propagate_alpha_filtration(complex, f_simplex);
}
}
}
@@ -350,7 +351,7 @@ class Alpha_complex {
private:
template <typename SimplicialComplexForAlpha, typename Simplex_handle>
- void propagate_alpha_filtration(SimplicialComplexForAlpha& complex, Simplex_handle f_simplex, int decr_dim) {
+ void propagate_alpha_filtration(SimplicialComplexForAlpha& complex, Simplex_handle f_simplex) {
// From SimplicialComplexForAlpha type required to assign filtration values.
typedef typename SimplicialComplexForAlpha::Filtration_value Filtration_value;
#ifdef DEBUG_TRACES
@@ -379,46 +380,42 @@ class Alpha_complex {
#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;
+ // insert the Tau points in a vector for is_gabriel function
+ Vector_of_CGAL_points pointVector;
#ifdef DEBUG_TRACES
- Vertex_handle vertexForGabriel = Vertex_handle();
+ Vertex_handle vertexForGabriel = Vertex_handle();
#endif // DEBUG_TRACES
- for (auto vertex : complex.simplex_vertex_range(f_boundary)) {
- pointVector.push_back(get_point(vertex));
- }
- // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function
- Point_d point_for_gabriel;
- for (auto vertex : complex.simplex_vertex_range(f_simplex)) {
- point_for_gabriel = get_point(vertex);
- if (std::find(pointVector.begin(), pointVector.end(), point_for_gabriel) == pointVector.end()) {
+ for (auto vertex : complex.simplex_vertex_range(f_boundary)) {
+ pointVector.push_back(get_point(vertex));
+ }
+ // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function
+ Point_d point_for_gabriel;
+ for (auto vertex : complex.simplex_vertex_range(f_simplex)) {
+ point_for_gabriel = get_point(vertex);
+ if (std::find(pointVector.begin(), pointVector.end(), point_for_gabriel) == pointVector.end()) {
#ifdef DEBUG_TRACES
- // vertex is not found in Tau
- vertexForGabriel = vertex;
+ // vertex is not found in Tau
+ vertexForGabriel = vertex;
#endif // DEBUG_TRACES
- // No need to continue loop
- break;
- }
+ // No need to continue loop
+ break;
}
- // is_gabriel function initialization
- 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;
+ }
+ // is_gabriel function initialization
+ 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;
+ 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 = complex.filtration(f_simplex);
- complex.assign_filtration(f_boundary, alpha_complex_filtration);
+ // ### If Tau is not Gabriel of Sigma
+ if (false == is_gab) {
+ // ### filt(Tau) = filt(Sigma)
+ Filtration_value alpha_complex_filtration = complex.filtration(f_simplex);
+ complex.assign_filtration(f_boundary, alpha_complex_filtration);
#ifdef DEBUG_TRACES
- std::cout << " | filt(Tau) = filt(Sigma) = " << complex.filtration(f_boundary) << std::endl;
+ std::cout << " | filt(Tau) = filt(Sigma) = " << complex.filtration(f_boundary) << std::endl;
#endif // DEBUG_TRACES
- }
}
}
}
diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h
new file mode 100644
index 00000000..32dfcc16
--- /dev/null
+++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h
@@ -0,0 +1,584 @@
+/* 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) 2018 Inria
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ALPHA_COMPLEX_3D_H_
+#define ALPHA_COMPLEX_3D_H_
+
+#include <boost/version.hpp>
+#include <boost/variant.hpp>
+
+#include <gudhi/Debug_utils.h>
+#include <gudhi/Alpha_complex_options.h>
+
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <CGAL/Delaunay_triangulation_3.h>
+#include <CGAL/Periodic_3_Delaunay_triangulation_traits_3.h>
+#include <CGAL/Periodic_3_Delaunay_triangulation_3.h>
+#include <CGAL/Periodic_3_regular_triangulation_traits_3.h>
+#include <CGAL/Periodic_3_regular_triangulation_3.h>
+#include <CGAL/Regular_triangulation_3.h>
+#include <CGAL/Alpha_shape_3.h>
+#include <CGAL/Alpha_shape_cell_base_3.h>
+#include <CGAL/Alpha_shape_vertex_base_3.h>
+
+#include <CGAL/Object.h>
+#include <CGAL/tuple.h>
+#include <CGAL/iterator.h>
+#include <CGAL/version.h>
+
+#include <boost/container/static_vector.hpp>
+
+#include <iostream>
+#include <vector>
+#include <unordered_map>
+#include <stdexcept>
+#include <cstddef>
+#include <memory> // for std::unique_ptr
+#include <type_traits> // for std::conditional and std::enable_if
+#include <limits> // for numeric_limits<>
+
+#if CGAL_VERSION_NR < 1041101000
+// Make compilation fail - required for external projects - https://gitlab.inria.fr/GUDHI/gudhi-devel/issues/10
+# error Alpha_complex_3d is only available for CGAL >= 4.11
+#endif
+
+namespace Gudhi {
+
+namespace alpha_complex {
+
+#ifdef GUDHI_CAN_USE_CXX11_THREAD_LOCAL
+thread_local
+#endif // GUDHI_CAN_USE_CXX11_THREAD_LOCAL
+ double RELATIVE_PRECISION_OF_TO_DOUBLE = 0.00001;
+
+// Value_from_iterator returns the filtration value from an iterator on alpha shapes values
+//
+// FAST SAFE EXACT
+// CGAL::to_double(*iterator) CGAL::to_double(*iterator) CGAL::to_double(iterator->exact())
+
+template <complexity Complexity>
+struct Value_from_iterator {
+ template <typename Iterator>
+ static double perform(Iterator it) {
+ // Default behaviour
+ return CGAL::to_double(*it);
+ }
+};
+
+template <>
+struct Value_from_iterator<complexity::EXACT> {
+ template <typename Iterator>
+ static double perform(Iterator it) {
+ return CGAL::to_double(it->exact());
+ }
+};
+
+/**
+ * \class Alpha_complex_3d
+ * \brief Alpha complex data structure for 3d specific case.
+ *
+ * \ingroup alpha_complex
+ *
+ * \details
+ * The data structure is constructing a <a href="https://doc.cgal.org/latest/Alpha_shapes_3/index.html">CGAL 3D Alpha
+ * Shapes</a> from a range of points (can be read from an OFF file, cf. Points_off_reader).
+ * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous.
+ *
+ * \tparam Complexity shall be `Gudhi::alpha_complex::complexity` type. Default value is
+ * `Gudhi::alpha_complex::complexity::SAFE`.
+ *
+ * \tparam Weighted Boolean used to set/unset the weighted version of Alpha_complex_3d. Default value is false.
+ *
+ * \tparam Periodic Boolean used to set/unset the periodic version of Alpha_complex_3d. Default value is false.
+ *
+ * For the weighted version, weights values are explained on CGAL
+ * <a href="https://doc.cgal.org/latest/Alpha_shapes_3/index.html#title0">Alpha shapes 3d</a> and
+ * <a href="https://doc.cgal.org/latest/Triangulation_3/index.html#Triangulation3secclassRegulartriangulation">Regular
+ * triangulation</a> documentation.
+ *
+ * For the periodic version, refer to the
+ * <a href="https://doc.cgal.org/latest/Periodic_3_triangulation_3/index.html">CGAL’s 3D Periodic Triangulations User
+ * Manual </a> for more details.
+ * The periodicity is defined by an iso-oriented cuboid with diagonal opposite vertices (x_min, y_min, z_min) and
+ * (x_max, y_max, z_max).
+ *
+ * Please refer to \ref alpha_complex for examples.
+ *
+ * \remark When Alpha_complex_3d is constructed with an infinite value of alpha (default value), the complex is a
+ * 3d Delaunay complex.
+ *
+ */
+template <complexity Complexity = complexity::SAFE, bool Weighted = false, bool Periodic = false>
+class Alpha_complex_3d {
+ // Epick = Exact_predicates_inexact_constructions_kernel
+ // Epeck = Exact_predicates_exact_constructions_kernel
+ // Exact_alpha_comparison_tag = exact version of CGAL Alpha_shape_3 and of its objects (Alpha_shape_vertex_base_3 and
+ // Alpha_shape_cell_base_3). Not available if weighted or periodic.
+ // Can be CGAL::Tag_false or CGAL::Tag_true. Default is False.
+ // cf. https://doc.cgal.org/latest/Alpha_shapes_3/classCGAL_1_1Alpha__shape__3.html
+ //
+ // We could use Epick + CGAL::Tag_true for not weighted nor periodic, but during benchmark, we found a bug
+ // https://github.com/CGAL/cgal/issues/3460
+ // This is the reason we only use Epick + CGAL::Tag_false, or Epeck
+ //
+ // FAST SAFE EXACT
+ // Epick + CGAL::Tag_false Epeck Epeck
+ using Predicates = typename std::conditional<(Complexity == complexity::FAST),
+ CGAL::Exact_predicates_inexact_constructions_kernel,
+ CGAL::Exact_predicates_exact_constructions_kernel>::type;
+
+ // The other way to do a conditional type. Here there are 3 possibilities
+ template <typename Predicates, bool Weighted_version, bool Periodic_version>
+ struct Kernel_3 {};
+
+ template <typename Predicates, bool Is_periodic>
+ struct Kernel_3<Predicates, Is_periodic, false> {
+ using Kernel = Predicates;
+ };
+
+ template <typename Predicates>
+ struct Kernel_3<Predicates, false, true> {
+ using Kernel = CGAL::Periodic_3_Delaunay_triangulation_traits_3<Predicates>;
+ };
+ template <typename Predicates>
+ struct Kernel_3<Predicates, true, true> {
+ using Kernel = CGAL::Periodic_3_regular_triangulation_traits_3<Predicates>;
+ };
+
+ using Kernel = typename Kernel_3<Predicates, Weighted, Periodic>::Kernel;
+
+ using TdsVb = typename std::conditional<Periodic, CGAL::Periodic_3_triangulation_ds_vertex_base_3<>,
+ CGAL::Triangulation_ds_vertex_base_3<>>::type;
+
+ using Tvb = typename std::conditional<Weighted, CGAL::Regular_triangulation_vertex_base_3<Kernel, TdsVb>,
+ CGAL::Triangulation_vertex_base_3<Kernel, TdsVb>>::type;
+
+ using Vb = CGAL::Alpha_shape_vertex_base_3<Kernel, Tvb>;
+
+ using TdsCb = typename std::conditional<Periodic, CGAL::Periodic_3_triangulation_ds_cell_base_3<>,
+ CGAL::Triangulation_ds_cell_base_3<>>::type;
+
+ using Tcb = typename std::conditional<Weighted, CGAL::Regular_triangulation_cell_base_3<Kernel, TdsCb>,
+ CGAL::Triangulation_cell_base_3<Kernel, TdsCb>>::type;
+
+ using Cb = CGAL::Alpha_shape_cell_base_3<Kernel, Tcb>;
+ using Tds = CGAL::Triangulation_data_structure_3<Vb, Cb>;
+
+ // The other way to do a conditional type. Here there 4 possibilities, cannot use std::conditional
+ template <typename Kernel, typename Tds, bool Weighted_version, bool Periodic_version>
+ struct Triangulation_3 {};
+
+ template <typename Kernel, typename Tds>
+ struct Triangulation_3<Kernel, Tds, false, false> {
+ using Dt = CGAL::Delaunay_triangulation_3<Kernel, Tds>;
+ using Weighted_point_3 = void;
+ };
+ template <typename Kernel, typename Tds>
+ struct Triangulation_3<Kernel, Tds, true, false> {
+ using Dt = CGAL::Regular_triangulation_3<Kernel, Tds>;
+ using Weighted_point_3 = typename Dt::Weighted_point;
+ };
+ template <typename Kernel, typename Tds>
+ struct Triangulation_3<Kernel, Tds, false, true> {
+ using Dt = CGAL::Periodic_3_Delaunay_triangulation_3<Kernel, Tds>;
+ using Weighted_point_3 = void;
+ };
+ template <typename Kernel, typename Tds>
+ struct Triangulation_3<Kernel, Tds, true, true> {
+ using Dt = CGAL::Periodic_3_regular_triangulation_3<Kernel, Tds>;
+ using Weighted_point_3 = typename Dt::Weighted_point;
+ };
+
+ /** \brief Is either Delaunay_triangulation_3 (Weighted = false and Periodic = false),
+ * Regular_triangulation_3 (Weighted = true and Periodic = false),
+ * Periodic_3_Delaunay_triangulation_3 (Weighted = false and Periodic = true)
+ * or Periodic_3_regular_triangulation_3 (Weighted = true and Periodic = true).
+ *
+ * This type is required by `Gudhi::alpha_complex::Alpha_complex_3d::Alpha_shape_3`.
+ * */
+ using Dt = typename Triangulation_3<Kernel, Tds, Weighted, Periodic>::Dt;
+
+ public:
+ /** \brief The <a href="https://doc.cgal.org/latest/Alpha_shapes_3/classCGAL_1_1Alpha__shape__3.html">CGAL 3D Alpha
+ * Shapes</a> type.
+ *
+ * The `Gudhi::alpha_complex::Alpha_complex_3d` is a wrapper on top of this class to ease the standard, weighted
+ * and/or periodic build of the Alpha complex 3d.*/
+ using Alpha_shape_3 = CGAL::Alpha_shape_3<Dt>;
+
+ /** \brief The alpha values type.
+ * Must be compatible with double. */
+ using FT = typename Alpha_shape_3::FT;
+
+ /** \brief Gives public access to the Point_3 type. Here is a Point_3 constructor example:
+\code{.cpp}
+using Alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, false>;
+
+// x0 = 1., y0 = -1.1, z0 = -1..
+Alpha_complex_3d::Point_3 p0(1., -1.1, -1.);
+\endcode
+ * */
+ using Point_3 = typename Kernel::Point_3;
+
+ /** \brief Gives public access to the Weighted_point_3 type. A Weighted point can be constructed as follows:
+\code{.cpp}
+using Weighted_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, false>;
+
+// x0 = 1., y0 = -1.1, z0 = -1., weight = 4.
+Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Point_3(1., -1.1, -1.), 4.);
+\endcode
+ *
+ * Note: This type is defined to void if Alpha complex is not weighted.
+ *
+ * */
+ using Weighted_point_3 = typename Triangulation_3<Kernel, Tds, Weighted, Periodic>::Weighted_point_3;
+
+ private:
+ using Dispatch =
+ CGAL::Dispatch_output_iterator<CGAL::cpp11::tuple<CGAL::Object, FT>,
+ CGAL::cpp11::tuple<std::back_insert_iterator<std::vector<CGAL::Object>>,
+ std::back_insert_iterator<std::vector<FT>>>>;
+
+ using Cell_handle = typename Alpha_shape_3::Cell_handle;
+ using Facet = typename Alpha_shape_3::Facet;
+ using Edge = typename Alpha_shape_3::Edge;
+ using Alpha_vertex_handle = typename Alpha_shape_3::Vertex_handle;
+ using Vertex_list = boost::container::static_vector<Alpha_vertex_handle, 4>;
+
+ public:
+ /** \brief Alpha_complex constructor from a list of points.
+ *
+ * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3` or
+ * `Alpha_complex_3d::Weighted_point_3`.
+ *
+ * @pre Available if Alpha_complex_3d is not Periodic.
+ *
+ * The type InputPointRange must be a range for which std::begin and std::end return input iterators on a
+ * `Alpha_complex_3d::Point_3` or a `Alpha_complex_3d::Weighted_point_3`.
+ */
+ template <typename InputPointRange>
+ Alpha_complex_3d(const InputPointRange& points) {
+ static_assert(!Periodic, "This constructor is not available for periodic versions of Alpha_complex_3d");
+
+ alpha_shape_3_ptr_ = std::unique_ptr<Alpha_shape_3>(
+ new Alpha_shape_3(std::begin(points), std::end(points), 0, Alpha_shape_3::GENERAL));
+ }
+
+ /** \brief Alpha_complex constructor from a list of points and associated weights.
+ *
+ * @exception std::invalid_argument In debug mode, if points and weights do not have the same size.
+ *
+ * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3`.
+ * @param[in] weights Range of weights on points. Weights shall be in double.
+ *
+ * @pre Available if Alpha_complex_3d is Weighted and not Periodic.
+ *
+ * The type InputPointRange must be a range for which std::begin and
+ * std::end return input iterators on a `Alpha_complex_3d::Point_3`.
+ * The type WeightRange must be a range for which std::begin and
+ * std::end return an input iterator on a double.
+ */
+ template <typename InputPointRange, typename WeightRange>
+ Alpha_complex_3d(const InputPointRange& points, WeightRange weights) {
+ static_assert(Weighted, "This constructor is not available for non-weighted versions of Alpha_complex_3d");
+ static_assert(!Periodic, "This constructor is not available for periodic versions of Alpha_complex_3d");
+ GUDHI_CHECK((weights.size() == points.size()),
+ std::invalid_argument("Points number in range different from weights range number"));
+
+ std::vector<Weighted_point_3> weighted_points_3;
+
+ std::size_t index = 0;
+ weighted_points_3.reserve(points.size());
+ while ((index < weights.size()) && (index < points.size())) {
+ weighted_points_3.push_back(Weighted_point_3(points[index], weights[index]));
+ index++;
+ }
+
+ alpha_shape_3_ptr_ = std::unique_ptr<Alpha_shape_3>(
+ new Alpha_shape_3(std::begin(weighted_points_3), std::end(weighted_points_3), 0, Alpha_shape_3::GENERAL));
+ }
+
+ /** \brief Alpha_complex constructor from a list of points and an iso-cuboid coordinates.
+ *
+ * @exception std::invalid_argument In debug mode, if the size of the cuboid in every directions is not the same.
+ *
+ * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3` or
+ * `Alpha_complex_3d::Weighted_point_3`.
+ * @param[in] x_min Iso-oriented cuboid x_min.
+ * @param[in] y_min Iso-oriented cuboid y_min.
+ * @param[in] z_min Iso-oriented cuboid z_min.
+ * @param[in] x_max Iso-oriented cuboid x_max.
+ * @param[in] y_max Iso-oriented cuboid y_max.
+ * @param[in] z_max Iso-oriented cuboid z_max.
+ *
+ * @pre Available if Alpha_complex_3d is Periodic.
+ *
+ * The type InputPointRange must be a range for which std::begin and std::end return input iterators on a
+ * `Alpha_complex_3d::Point_3` or a `Alpha_complex_3d::Weighted_point_3`.
+ *
+ * @note In weighted version, please check weights are greater than zero, and lower than 1/64*cuboid length
+ * squared.
+ */
+ template <typename InputPointRange>
+ Alpha_complex_3d(const InputPointRange& points, FT x_min, FT y_min,
+ FT z_min, FT x_max, FT y_max, FT z_max) {
+ static_assert(Periodic, "This constructor is not available for non-periodic versions of Alpha_complex_3d");
+ // Checking if the cuboid is the same in x,y and z direction. If not, CGAL will not process it.
+ GUDHI_CHECK(
+ (x_max - x_min == y_max - y_min) && (x_max - x_min == z_max - z_min) && (z_max - z_min == y_max - y_min),
+ std::invalid_argument("The size of the cuboid in every directions is not the same."));
+
+ // Define the periodic cube
+ Dt pdt(typename Kernel::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max));
+ // Heuristic for inserting large point sets (if pts is reasonably large)
+ pdt.insert(std::begin(points), std::end(points), true);
+ // As pdt won't be modified anymore switch to 1-sheeted cover if possible
+ if (!pdt.is_triangulation_in_1_sheet()) {
+ throw std::invalid_argument("Unable to construct a triangulation within a single periodic domain.");
+ }
+ pdt.convert_to_1_sheeted_covering();
+
+ // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. This is the default mode
+ // Maybe need to set it to GENERAL mode
+ alpha_shape_3_ptr_ = std::unique_ptr<Alpha_shape_3>(new Alpha_shape_3(pdt, 0, Alpha_shape_3::GENERAL));
+ }
+
+ /** \brief Alpha_complex constructor from a list of points, associated weights and an iso-cuboid coordinates.
+ *
+ * @exception std::invalid_argument In debug mode, if points and weights do not have the same size.
+ * @exception std::invalid_argument In debug mode, if the size of the cuboid in every directions is not the same.
+ * @exception std::invalid_argument In debug mode, if a weight is negative, zero, or greater than 1/64*cuboid length
+ * squared.
+ *
+ * @param[in] points Range of points to triangulate. Points must be in `Alpha_complex_3d::Point_3`.
+ * @param[in] weights Range of weights on points. Weights shall be in double.
+ * @param[in] x_min Iso-oriented cuboid x_min.
+ * @param[in] y_min Iso-oriented cuboid y_min.
+ * @param[in] z_min Iso-oriented cuboid z_min.
+ * @param[in] x_max Iso-oriented cuboid x_max.
+ * @param[in] y_max Iso-oriented cuboid y_max.
+ * @param[in] z_max Iso-oriented cuboid z_max.
+ *
+ * @pre Available if Alpha_complex_3d is Weighted and Periodic.
+ *
+ * The type InputPointRange must be a range for which std::begin and
+ * std::end return input iterators on a `Alpha_complex_3d::Point_3`.
+ * The type WeightRange must be a range for which std::begin and
+ * std::end return an input iterator on a double.
+ * The type of x_min, y_min, z_min, x_max, y_max and z_max must be a double.
+ */
+ template <typename InputPointRange, typename WeightRange>
+ Alpha_complex_3d(const InputPointRange& points, WeightRange weights, FT x_min, FT y_min,
+ FT z_min, FT x_max, FT y_max, FT z_max) {
+ static_assert(Weighted, "This constructor is not available for non-weighted versions of Alpha_complex_3d");
+ static_assert(Periodic, "This constructor is not available for non-periodic versions of Alpha_complex_3d");
+ GUDHI_CHECK((weights.size() == points.size()),
+ std::invalid_argument("Points number in range different from weights range number"));
+ // Checking if the cuboid is the same in x,y and z direction. If not, CGAL will not process it.
+ GUDHI_CHECK(
+ (x_max - x_min == y_max - y_min) && (x_max - x_min == z_max - z_min) && (z_max - z_min == y_max - y_min),
+ std::invalid_argument("The size of the cuboid in every directions is not the same."));
+
+ std::vector<Weighted_point_3> weighted_points_3;
+
+ std::size_t index = 0;
+ weighted_points_3.reserve(points.size());
+
+#ifdef GUDHI_DEBUG
+ // Defined in GUDHI_DEBUG to avoid unused variable warning for GUDHI_CHECK
+ FT maximal_possible_weight = 0.015625 * (x_max - x_min) * (x_max - x_min);
+#endif
+
+ while ((index < weights.size()) && (index < points.size())) {
+ GUDHI_CHECK((weights[index] < maximal_possible_weight) && (weights[index] >= 0),
+ std::invalid_argument("Invalid weight at index " + std::to_string(index + 1) +
+ ". Must be positive and less than maximal possible weight = 1/64*cuboid length "
+ "squared, which is not an acceptable input."));
+ weighted_points_3.push_back(Weighted_point_3(points[index], weights[index]));
+ index++;
+ }
+
+ // Define the periodic cube
+ Dt pdt(typename Kernel::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max));
+ // Heuristic for inserting large point sets (if pts is reasonably large)
+ pdt.insert(std::begin(weighted_points_3), std::end(weighted_points_3), true);
+ // As pdt won't be modified anymore switch to 1-sheeted cover if possible
+ if (!pdt.is_triangulation_in_1_sheet()) {
+ throw std::invalid_argument("Unable to construct a triangulation within a single periodic domain.");
+ }
+ pdt.convert_to_1_sheeted_covering();
+
+ // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. This is the default mode
+ // Maybe need to set it to GENERAL mode
+ alpha_shape_3_ptr_ = std::unique_ptr<Alpha_shape_3>(new Alpha_shape_3(pdt, 0, Alpha_shape_3::GENERAL));
+ }
+
+ /** \brief Inserts all Delaunay triangulation into the simplicial complex.
+ * It also computes the filtration values accordingly to the \ref createcomplexalgorithm
+ *
+ * \tparam SimplicialComplexForAlpha3d must meet `SimplicialComplexForAlpha3d` concept.
+ *
+ * @param[in] complex SimplicialComplexForAlpha3d to be created.
+ * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$, and there is very
+ * little point using anything else since it does not save time.
+ *
+ * @return true if creation succeeds, false otherwise.
+ *
+ * @pre The simplicial complex must be empty (no vertices).
+ *
+ */
+ template <typename SimplicialComplexForAlpha3d,
+ typename Filtration_value = typename SimplicialComplexForAlpha3d::Filtration_value>
+ bool create_complex(SimplicialComplexForAlpha3d& complex,
+ Filtration_value max_alpha_square = std::numeric_limits<Filtration_value>::infinity()) {
+ if (complex.num_vertices() > 0) {
+ std::cerr << "Alpha_complex_3d create_complex - complex is not empty\n";
+ return false; // ----- >>
+ }
+
+ // using Filtration_value = typename SimplicialComplexForAlpha3d::Filtration_value;
+ using Complex_vertex_handle = typename SimplicialComplexForAlpha3d::Vertex_handle;
+ using Alpha_shape_simplex_tree_map = std::unordered_map<Alpha_vertex_handle, Complex_vertex_handle>;
+ using Simplex_tree_vector_vertex = std::vector<Complex_vertex_handle>;
+
+#ifdef DEBUG_TRACES
+ std::size_t count_vertices = 0;
+ std::size_t count_edges = 0;
+ std::size_t count_facets = 0;
+ std::size_t count_cells = 0;
+#endif // DEBUG_TRACES
+ std::vector<CGAL::Object> objects;
+ std::vector<FT> alpha_values;
+
+ Dispatch dispatcher = CGAL::dispatch_output<CGAL::Object, FT>(std::back_inserter(objects),
+ std::back_inserter(alpha_values));
+
+ alpha_shape_3_ptr_->filtration_with_alpha_values(dispatcher);
+#ifdef DEBUG_TRACES
+ std::cout << "filtration_with_alpha_values returns : " << objects.size() << " objects" << std::endl;
+#endif // DEBUG_TRACES
+
+ Alpha_shape_simplex_tree_map map_cgal_simplex_tree;
+ using Alpha_value_iterator = typename std::vector<FT>::const_iterator;
+ Alpha_value_iterator alpha_value_iterator = alpha_values.begin();
+ for (auto object_iterator : objects) {
+ Vertex_list vertex_list;
+
+ // Retrieve Alpha shape vertex list from object
+ if (const Cell_handle* cell = CGAL::object_cast<Cell_handle>(&object_iterator)) {
+ for (auto i = 0; i < 4; i++) {
+#ifdef DEBUG_TRACES
+ std::cout << "from cell[" << i << "]=" << (*cell)->vertex(i)->point() << std::endl;
+#endif // DEBUG_TRACES
+ vertex_list.push_back((*cell)->vertex(i));
+ }
+#ifdef DEBUG_TRACES
+ count_cells++;
+#endif // DEBUG_TRACES
+ } else if (const Facet* facet = CGAL::object_cast<Facet>(&object_iterator)) {
+ for (auto i = 0; i < 4; i++) {
+ if ((*facet).second != i) {
+#ifdef DEBUG_TRACES
+ std::cout << "from facet=[" << i << "]" << (*facet).first->vertex(i)->point() << std::endl;
+#endif // DEBUG_TRACES
+ vertex_list.push_back((*facet).first->vertex(i));
+ }
+ }
+#ifdef DEBUG_TRACES
+ count_facets++;
+#endif // DEBUG_TRACES
+ } else if (const Edge* edge = CGAL::object_cast<Edge>(&object_iterator)) {
+ for (auto i : {(*edge).second, (*edge).third}) {
+#ifdef DEBUG_TRACES
+ std::cout << "from edge[" << i << "]=" << (*edge).first->vertex(i)->point() << std::endl;
+#endif // DEBUG_TRACES
+ vertex_list.push_back((*edge).first->vertex(i));
+ }
+#ifdef DEBUG_TRACES
+ count_edges++;
+#endif // DEBUG_TRACES
+ } else if (const Alpha_vertex_handle* vertex = CGAL::object_cast<Alpha_vertex_handle>(&object_iterator)) {
+#ifdef DEBUG_TRACES
+ count_vertices++;
+ std::cout << "from vertex=" << (*vertex)->point() << std::endl;
+#endif // DEBUG_TRACES
+ vertex_list.push_back((*vertex));
+ }
+ // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex
+ Simplex_tree_vector_vertex the_simplex;
+ for (auto the_alpha_shape_vertex : vertex_list) {
+ auto 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
+ Complex_vertex_handle 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.push_back(vertex);
+ map_cgal_simplex_tree.emplace(the_alpha_shape_vertex, vertex);
+ } else {
+ // alpha shape found
+ Complex_vertex_handle 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.push_back(vertex);
+ }
+ }
+ // Construction of the simplex_tree
+ Filtration_value filtr = Value_from_iterator<Complexity>::perform(alpha_value_iterator);
+
+#ifdef DEBUG_TRACES
+ std::cout << "filtration = " << filtr << std::endl;
+#endif // DEBUG_TRACES
+ complex.insert_simplex(the_simplex, static_cast<Filtration_value>(filtr));
+ GUDHI_CHECK(alpha_value_iterator != alpha_values.end(), "CGAL provided more simplices than values");
+ ++alpha_value_iterator;
+ }
+
+#ifdef DEBUG_TRACES
+ std::cout << "vertices \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;
+#endif // DEBUG_TRACES
+ // --------------------------------------------------------------------------------------------
+ // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension
+ complex.make_filtration_non_decreasing();
+ // Remove all simplices that have a filtration value greater than max_alpha_square
+ complex.prune_above_filtration(max_alpha_square);
+ // --------------------------------------------------------------------------------------------
+ return true;
+ }
+
+ private:
+ // use of a unique_ptr on cgal Alpha_shape_3, as copy and default constructor is not available - no need to be freed
+ std::unique_ptr<Alpha_shape_3> alpha_shape_3_ptr_;
+};
+
+} // namespace alpha_complex
+
+} // namespace Gudhi
+
+#endif // ALPHA_COMPLEX_3D_H_
diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_options.h b/src/Alpha_complex/include/gudhi/Alpha_complex_options.h
new file mode 100644
index 00000000..7a555fa1
--- /dev/null
+++ b/src/Alpha_complex/include/gudhi/Alpha_complex_options.h
@@ -0,0 +1,45 @@
+/* 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) 2018 Inria
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ALPHA_COMPLEX_OPTIONS_H_
+#define ALPHA_COMPLEX_OPTIONS_H_
+
+namespace Gudhi {
+
+namespace alpha_complex {
+
+/**
+ * \brief Alpha complex complexity template parameter possible values.
+ *
+ * \ingroup alpha_complex
+ */
+enum class complexity : char {
+ FAST = 'f', ///< Fast version.
+ SAFE = 's', ///< Safe version.
+ EXACT = 'e', ///< Exact version.
+};
+
+} // namespace alpha_complex
+
+} // namespace Gudhi
+
+#endif // ALPHA_COMPLEX_OPTIONS_H_
diff --git a/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp
new file mode 100644
index 00000000..ec905d5b
--- /dev/null
+++ b/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp
@@ -0,0 +1,164 @@
+/* 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
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "alpha_complex_3d"
+#include <boost/test/unit_test.hpp>
+
+#include <cmath> // float comparison
+#include <limits>
+#include <string>
+#include <vector>
+#include <random>
+#include <cstddef> // for std::size_t
+
+#include <gudhi/Alpha_complex_3d.h>
+#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Unitary_tests_utils.h>
+// to construct Alpha_complex from a OFF file of points
+#include <gudhi/Points_3D_off_io.h>
+
+#include <CGAL/Random.h>
+#include <CGAL/point_generators_3.h>
+
+using Fast_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, false, false>;
+using Safe_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, false>;
+using Exact_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, false>;
+
+template <typename Point>
+std::vector<Point> get_points() {
+ std::vector<Point> points;
+ points.push_back(Point(0.0, 0.0, 0.0));
+ points.push_back(Point(0.0, 0.0, 0.2));
+ points.push_back(Point(0.2, 0.0, 0.2));
+ points.push_back(Point(0.6, 0.6, 0.0));
+ points.push_back(Point(0.8, 0.8, 0.2));
+ points.push_back(Point(0.2, 0.8, 0.6));
+
+ return points;
+}
+
+
+BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) {
+ // -----------------
+ // Fast version
+ // -----------------
+ std::cout << "Fast alpha complex 3d" << std::endl;
+
+ Fast_alpha_complex_3d alpha_complex(get_points<Fast_alpha_complex_3d::Point_3>());
+
+ Gudhi::Simplex_tree<> stree;
+ alpha_complex.create_complex(stree);
+
+ // -----------------
+ // Exact version
+ // -----------------
+ std::cout << "Exact alpha complex 3d" << std::endl;
+
+ Exact_alpha_complex_3d exact_alpha_complex(get_points<Exact_alpha_complex_3d::Point_3>());
+
+ Gudhi::Simplex_tree<> exact_stree;
+ exact_alpha_complex.create_complex(exact_stree);
+
+ // ---------------------
+ // Compare both versions
+ // ---------------------
+ std::cout << "Exact Alpha complex 3d is of dimension " << exact_stree.dimension() << " - Fast is "
+ << stree.dimension() << std::endl;
+ BOOST_CHECK(exact_stree.dimension() == stree.dimension());
+ std::cout << "Exact Alpha complex 3d num_simplices " << exact_stree.num_simplices() << " - Fast is "
+ << stree.num_simplices() << std::endl;
+ BOOST_CHECK(exact_stree.num_simplices() == stree.num_simplices());
+ std::cout << "Exact Alpha complex 3d num_vertices " << exact_stree.num_vertices() << " - Fast is "
+ << stree.num_vertices() << std::endl;
+ BOOST_CHECK(exact_stree.num_vertices() == stree.num_vertices());
+
+ auto sh = stree.filtration_simplex_range().begin();
+ while (sh != stree.filtration_simplex_range().end()) {
+ std::vector<int> simplex;
+ std::vector<int> exact_simplex;
+ std::cout << "Fast ( ";
+ for (auto vertex : stree.simplex_vertex_range(*sh)) {
+ simplex.push_back(vertex);
+ std::cout << vertex << " ";
+ }
+ std::cout << ") -> [" << stree.filtration(*sh) << "] ";
+
+ // Find it in the exact structure
+ auto sh_exact = exact_stree.find(simplex);
+ BOOST_CHECK(sh_exact != exact_stree.null_simplex());
+
+ std::cout << " versus [" << exact_stree.filtration(sh_exact) << "] " << std::endl;
+ // Exact and non-exact version is not exactly the same due to float comparison
+ GUDHI_TEST_FLOAT_EQUALITY_CHECK(exact_stree.filtration(sh_exact), stree.filtration(*sh));
+
+ ++sh;
+ }
+ // -----------------
+ // Safe version
+ // -----------------
+ std::cout << "Safe alpha complex 3d" << std::endl;
+
+ Safe_alpha_complex_3d safe_alpha_complex(get_points<Safe_alpha_complex_3d::Point_3>());
+
+ Gudhi::Simplex_tree<> safe_stree;
+ safe_alpha_complex.create_complex(safe_stree);
+
+ // ---------------------
+ // Compare both versions
+ // ---------------------
+ std::cout << "Safe Alpha complex 3d is of dimension " << safe_stree.dimension() << " - Fast is "
+ << stree.dimension() << std::endl;
+ BOOST_CHECK(safe_stree.dimension() == stree.dimension());
+ std::cout << "Safe Alpha complex 3d num_simplices " << safe_stree.num_simplices() << " - Fast is "
+ << stree.num_simplices() << std::endl;
+ BOOST_CHECK(safe_stree.num_simplices() == stree.num_simplices());
+ std::cout << "Safe Alpha complex 3d num_vertices " << safe_stree.num_vertices() << " - Fast is "
+ << stree.num_vertices() << std::endl;
+ BOOST_CHECK(safe_stree.num_vertices() == stree.num_vertices());
+
+ auto safe_sh = stree.filtration_simplex_range().begin();
+ while (safe_sh != stree.filtration_simplex_range().end()) {
+ std::vector<int> simplex;
+ std::vector<int> exact_simplex;
+ std::cout << "Fast ( ";
+ for (auto vertex : stree.simplex_vertex_range(*safe_sh)) {
+ simplex.push_back(vertex);
+ std::cout << vertex << " ";
+ }
+ std::cout << ") -> [" << stree.filtration(*safe_sh) << "] ";
+
+ // Find it in the exact structure
+ auto sh_exact = safe_stree.find(simplex);
+ BOOST_CHECK(sh_exact != safe_stree.null_simplex());
+
+ std::cout << " versus [" << safe_stree.filtration(sh_exact) << "] " << std::endl;
+ // Exact and non-exact version is not exactly the same due to float comparison
+ GUDHI_TEST_FLOAT_EQUALITY_CHECK(safe_stree.filtration(sh_exact), stree.filtration(*safe_sh), 1e-15);
+
+ ++safe_sh;
+ }
+}
diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt
index 9255d3db..7c6bf9aa 100644
--- a/src/Alpha_complex/test/CMakeLists.txt
+++ b/src/Alpha_complex/test/CMakeLists.txt
@@ -1,7 +1,10 @@
project(Alpha_complex_tests)
+include(GUDHI_test_coverage)
if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
- include(GUDHI_test_coverage)
+
+ # 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}/)
add_executable ( Alpha_complex_test_unit Alpha_complex_unit_test.cpp )
target_link_libraries(Alpha_complex_test_unit ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
@@ -9,10 +12,29 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
target_link_libraries(Alpha_complex_test_unit ${TBB_LIBRARIES})
endif()
- # 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}/)
-
gudhi_add_coverage_test(Alpha_complex_test_unit)
endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
+if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ add_executable ( Alpha_complex_3d_test_unit Alpha_complex_3d_unit_test.cpp )
+ target_link_libraries(Alpha_complex_3d_test_unit ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+ add_executable ( Weighted_alpha_complex_3d_test_unit Weighted_alpha_complex_3d_unit_test.cpp )
+ target_link_libraries(Weighted_alpha_complex_3d_test_unit ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+ add_executable ( Periodic_alpha_complex_3d_test_unit Periodic_alpha_complex_3d_unit_test.cpp )
+ target_link_libraries(Periodic_alpha_complex_3d_test_unit ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+ add_executable ( Weighted_periodic_alpha_complex_3d_test_unit Weighted_periodic_alpha_complex_3d_unit_test.cpp )
+ target_link_libraries(Weighted_periodic_alpha_complex_3d_test_unit ${CGAL_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(Alpha_complex_3d_test_unit ${TBB_LIBRARIES})
+ target_link_libraries(Weighted_alpha_complex_3d_test_unit ${TBB_LIBRARIES})
+ target_link_libraries(Periodic_alpha_complex_3d_test_unit ${TBB_LIBRARIES})
+ target_link_libraries(Weighted_periodic_alpha_complex_3d_test_unit ${TBB_LIBRARIES})
+ endif()
+
+ gudhi_add_coverage_test(Alpha_complex_3d_test_unit)
+ gudhi_add_coverage_test(Weighted_alpha_complex_3d_test_unit)
+ gudhi_add_coverage_test(Periodic_alpha_complex_3d_test_unit)
+ gudhi_add_coverage_test(Weighted_periodic_alpha_complex_3d_test_unit)
+
+endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
diff --git a/src/Alpha_complex/test/Periodic_alpha_complex_3d_unit_test.cpp b/src/Alpha_complex/test/Periodic_alpha_complex_3d_unit_test.cpp
new file mode 100644
index 00000000..ed4cbff0
--- /dev/null
+++ b/src/Alpha_complex/test/Periodic_alpha_complex_3d_unit_test.cpp
@@ -0,0 +1,190 @@
+/* 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
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "alpha_complex_3d"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <cmath> // float comparison
+#include <limits>
+#include <string>
+#include <vector>
+#include <random>
+#include <cstddef> // for std::size_t
+
+#include <gudhi/Alpha_complex_3d.h>
+#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Unitary_tests_utils.h>
+// to construct Alpha_complex from a OFF file of points
+#include <gudhi/Points_3D_off_io.h>
+
+#include <CGAL/Random.h>
+#include <CGAL/point_generators_3.h>
+
+using Fast_periodic_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, false, true>;
+using Safe_periodic_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, true>;
+using Exact_periodic_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, true>;
+
+#ifdef GUDHI_DEBUG
+typedef boost::mpl::list<Fast_periodic_alpha_complex_3d, Safe_periodic_alpha_complex_3d,
+ Exact_periodic_alpha_complex_3d>
+ periodic_variants_type_list;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_periodic_throw, Periodic_alpha_complex_3d, periodic_variants_type_list) {
+ std::cout << "Periodic alpha complex 3d exception throw" << std::endl;
+ using Point_3 = typename Periodic_alpha_complex_3d::Point_3;
+ std::vector<Point_3> p_points;
+
+ // Not important, this is not what we want to check
+ p_points.push_back(Point_3(0.0, 0.0, 0.0));
+
+ std::cout << "Check exception throw in debug mode" << std::endl;
+ // Check it throws an exception when the cuboid is not iso
+ BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 0.9, 1., 1.),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 0.9, 1.),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 1., 0.9),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1.1, 1., 1.),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 1.1, 1.),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(Periodic_alpha_complex_3d periodic_alpha_complex(p_points, 0., 0., 0., 1., 1., 1.1),
+ std::invalid_argument);
+}
+#endif
+
+BOOST_AUTO_TEST_CASE(Alpha_complex_periodic) {
+ // ---------------------
+ // Fast periodic version
+ // ---------------------
+ std::cout << "Fast periodic alpha complex 3d" << std::endl;
+
+ using Creator = CGAL::Creator_uniform_3<double, Fast_periodic_alpha_complex_3d::Point_3>;
+ CGAL::Random random(7);
+ CGAL::Random_points_in_cube_3<Fast_periodic_alpha_complex_3d::Point_3, Creator> in_cube(1, random);
+ std::vector<Fast_periodic_alpha_complex_3d::Point_3> p_points;
+
+ for (int i = 0; i < 50; i++) {
+ Fast_periodic_alpha_complex_3d::Point_3 p = *in_cube++;
+ p_points.push_back(p);
+ }
+
+ Fast_periodic_alpha_complex_3d periodic_alpha_complex(p_points, -1., -1., -1., 1., 1., 1.);
+
+ Gudhi::Simplex_tree<> stree;
+ periodic_alpha_complex.create_complex(stree);
+
+ // ----------------------
+ // Exact periodic version
+ // ----------------------
+ std::cout << "Exact periodic alpha complex 3d" << std::endl;
+
+ std::vector<Exact_periodic_alpha_complex_3d::Point_3> e_p_points;
+
+ for (auto p : p_points) {
+ e_p_points.push_back(Exact_periodic_alpha_complex_3d::Point_3(p[0], p[1], p[2]));
+ }
+
+ Exact_periodic_alpha_complex_3d exact_alpha_complex(e_p_points, -1., -1., -1., 1., 1., 1.);
+
+ Gudhi::Simplex_tree<> exact_stree;
+ exact_alpha_complex.create_complex(exact_stree);
+
+ // ---------------------
+ // Compare both versions
+ // ---------------------
+ std::cout << "Exact periodic alpha complex 3d is of dimension " << exact_stree.dimension() << " - Non exact is "
+ << stree.dimension() << std::endl;
+ BOOST_CHECK(exact_stree.dimension() == stree.dimension());
+ std::cout << "Exact periodic alpha complex 3d num_simplices " << exact_stree.num_simplices() << " - Non exact is "
+ << stree.num_simplices() << std::endl;
+ BOOST_CHECK(exact_stree.num_simplices() == stree.num_simplices());
+ std::cout << "Exact periodic alpha complex 3d num_vertices " << exact_stree.num_vertices() << " - Non exact is "
+ << stree.num_vertices() << std::endl;
+ BOOST_CHECK(exact_stree.num_vertices() == stree.num_vertices());
+
+ // We cannot compare as objects from dispatcher on the alpha shape is not deterministic.
+ // cf. https://github.com/CGAL/cgal/issues/3346
+ auto sh = stree.filtration_simplex_range().begin();
+ auto sh_exact = exact_stree.filtration_simplex_range().begin();
+
+ while (sh != stree.filtration_simplex_range().end() || sh_exact != exact_stree.filtration_simplex_range().end()) {
+ GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), exact_stree.filtration(*sh_exact), 1e-14);
+
+ std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end());
+ std::vector<int> exact_vh(exact_stree.simplex_vertex_range(*sh_exact).begin(),
+ exact_stree.simplex_vertex_range(*sh_exact).end());
+
+ BOOST_CHECK(vh.size() == exact_vh.size());
+ ++sh;
+ ++sh_exact;
+ }
+
+ BOOST_CHECK(sh == stree.filtration_simplex_range().end());
+ BOOST_CHECK(sh_exact == exact_stree.filtration_simplex_range().end());
+
+ // ----------------------
+ // Safe periodic version
+ // ----------------------
+ std::cout << "Safe periodic alpha complex 3d" << std::endl;
+
+ std::vector<Safe_periodic_alpha_complex_3d::Point_3> s_p_points;
+
+ for (auto p : p_points) {
+ s_p_points.push_back(Safe_periodic_alpha_complex_3d::Point_3(p[0], p[1], p[2]));
+ }
+
+ Safe_periodic_alpha_complex_3d safe_alpha_complex(s_p_points, -1., -1., -1., 1., 1., 1.);
+
+ Gudhi::Simplex_tree<> safe_stree;
+ safe_alpha_complex.create_complex(safe_stree);
+
+ // ---------------------
+ // Compare both versions
+ // ---------------------
+ // We cannot compare as objects from dispatcher on the alpha shape is not deterministic.
+ // cf. https://github.com/CGAL/cgal/issues/3346
+ sh = stree.filtration_simplex_range().begin();
+ auto sh_safe = safe_stree.filtration_simplex_range().begin();
+
+ while (sh != stree.filtration_simplex_range().end() || sh_safe != safe_stree.filtration_simplex_range().end()) {
+ GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), safe_stree.filtration(*sh_safe), 1e-14);
+
+ std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end());
+ std::vector<int> safe_vh(safe_stree.simplex_vertex_range(*sh_safe).begin(),
+ safe_stree.simplex_vertex_range(*sh_safe).end());
+
+ BOOST_CHECK(vh.size() == safe_vh.size());
+ ++sh;
+ ++sh_safe;
+ }
+
+ BOOST_CHECK(sh == stree.filtration_simplex_range().end());
+ BOOST_CHECK(sh_safe == safe_stree.filtration_simplex_range().end());
+}
diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_3d_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_3d_unit_test.cpp
new file mode 100644
index 00000000..c16b3718
--- /dev/null
+++ b/src/Alpha_complex/test/Weighted_alpha_complex_3d_unit_test.cpp
@@ -0,0 +1,147 @@
+/* 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
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "alpha_complex_3d"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <cmath> // float comparison
+#include <limits>
+#include <string>
+#include <vector>
+#include <random>
+#include <cstddef> // for std::size_t
+
+#include <gudhi/Alpha_complex_3d.h>
+#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Unitary_tests_utils.h>
+// to construct Alpha_complex from a OFF file of points
+#include <gudhi/Points_3D_off_io.h>
+
+#include <CGAL/Random.h>
+#include <CGAL/point_generators_3.h>
+
+using Fast_weighted_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, false>;
+using Safe_weighted_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, false>;
+using Exact_weighted_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, false>;
+
+typedef boost::mpl::list<Fast_weighted_alpha_complex_3d, Safe_weighted_alpha_complex_3d,
+ Exact_weighted_alpha_complex_3d>
+ weighted_variants_type_list;
+
+#ifdef GUDHI_DEBUG
+BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted_throw, Weighted_alpha_complex_3d, weighted_variants_type_list) {
+ using Point_3 = typename Weighted_alpha_complex_3d::Point_3;
+ std::vector<Point_3> w_points;
+ w_points.push_back(Point_3(0.0, 0.0, 0.0));
+ w_points.push_back(Point_3(0.0, 0.0, 0.2));
+ w_points.push_back(Point_3(0.2, 0.0, 0.2));
+ // w_points.push_back(Point_3(0.6, 0.6, 0.0));
+ // w_points.push_back(Point_3(0.8, 0.8, 0.2));
+ // w_points.push_back(Point_3(0.2, 0.8, 0.6));
+
+ // weights size is different from w_points size to make weighted Alpha_complex_3d throw in debug mode
+ std::vector<double> weights = {0.01, 0.005, 0.006, 0.01, 0.009, 0.001};
+
+ std::cout << "Check exception throw in debug mode" << std::endl;
+ BOOST_CHECK_THROW(Weighted_alpha_complex_3d wac(w_points, weights), std::invalid_argument);
+}
+#endif
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted, Weighted_alpha_complex_3d, weighted_variants_type_list) {
+ std::cout << "Weighted alpha complex 3d from points and weights" << std::endl;
+ using Point_3 = typename Weighted_alpha_complex_3d::Point_3;
+ std::vector<Point_3> w_points;
+ w_points.push_back(Point_3(0.0, 0.0, 0.0));
+ w_points.push_back(Point_3(0.0, 0.0, 0.2));
+ w_points.push_back(Point_3(0.2, 0.0, 0.2));
+ w_points.push_back(Point_3(0.6, 0.6, 0.0));
+ w_points.push_back(Point_3(0.8, 0.8, 0.2));
+ w_points.push_back(Point_3(0.2, 0.8, 0.6));
+
+ // weights size is different from w_points size to make weighted Alpha_complex_3d throw in debug mode
+ std::vector<double> weights = {0.01, 0.005, 0.006, 0.01, 0.009, 0.001};
+
+ Weighted_alpha_complex_3d alpha_complex_p_a_w(w_points, weights);
+ Gudhi::Simplex_tree<> stree;
+ alpha_complex_p_a_w.create_complex(stree);
+
+ std::cout << "Weighted alpha complex 3d from weighted points" << std::endl;
+ using Weighted_point_3 = typename Weighted_alpha_complex_3d::Weighted_point_3;
+
+ std::vector<Weighted_point_3> weighted_points;
+
+ for (std::size_t i = 0; i < w_points.size(); i++) {
+ weighted_points.push_back(Weighted_point_3(w_points[i], weights[i]));
+ }
+ Weighted_alpha_complex_3d alpha_complex_w_p(weighted_points);
+
+ Gudhi::Simplex_tree<> stree_bis;
+ alpha_complex_w_p.create_complex(stree_bis);
+
+ // ---------------------
+ // Compare both versions
+ // ---------------------
+ std::cout << "Weighted alpha complex 3d is of dimension " << stree_bis.dimension() << " - versus "
+ << stree.dimension() << std::endl;
+ BOOST_CHECK(stree_bis.dimension() == stree.dimension());
+ std::cout << "Weighted alpha complex 3d num_simplices " << stree_bis.num_simplices() << " - versus "
+ << stree.num_simplices() << std::endl;
+ BOOST_CHECK(stree_bis.num_simplices() == stree.num_simplices());
+ std::cout << "Weighted alpha complex 3d num_vertices " << stree_bis.num_vertices() << " - versus "
+ << stree.num_vertices() << std::endl;
+ BOOST_CHECK(stree_bis.num_vertices() == stree.num_vertices());
+
+ auto sh = stree.filtration_simplex_range().begin();
+ while (sh != stree.filtration_simplex_range().end()) {
+ std::vector<int> simplex;
+ std::vector<int> exact_simplex;
+#ifdef DEBUG_TRACES
+ std::cout << " ( ";
+#endif
+ for (auto vertex : stree.simplex_vertex_range(*sh)) {
+ simplex.push_back(vertex);
+#ifdef DEBUG_TRACES
+ std::cout << vertex << " ";
+#endif
+ }
+#ifdef DEBUG_TRACES
+ std::cout << ") -> "
+ << "[" << stree.filtration(*sh) << "] ";
+ std::cout << std::endl;
+#endif
+
+ // Find it in the exact structure
+ auto sh_exact = stree_bis.find(simplex);
+ BOOST_CHECK(sh_exact != stree_bis.null_simplex());
+
+ // Exact and non-exact version is not exactly the same due to float comparison
+ GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree_bis.filtration(sh_exact), stree.filtration(*sh));
+
+ ++sh;
+ }
+}
diff --git a/src/Alpha_complex/test/Weighted_periodic_alpha_complex_3d_unit_test.cpp b/src/Alpha_complex/test/Weighted_periodic_alpha_complex_3d_unit_test.cpp
new file mode 100644
index 00000000..e8ac83e5
--- /dev/null
+++ b/src/Alpha_complex/test/Weighted_periodic_alpha_complex_3d_unit_test.cpp
@@ -0,0 +1,239 @@
+/* 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
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "alpha_complex_3d"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <cmath> // float comparison
+#include <limits>
+#include <string>
+#include <vector>
+#include <random>
+#include <cstddef> // for std::size_t
+
+#include <gudhi/Alpha_complex_3d.h>
+#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Unitary_tests_utils.h>
+// to construct Alpha_complex from a OFF file of points
+#include <gudhi/Points_3D_off_io.h>
+
+#include <CGAL/Random.h>
+#include <CGAL/point_generators_3.h>
+
+using Fast_weighted_periodic_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, true>;
+using Safe_weighted_periodic_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, true>;
+using Exact_weighted_periodic_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, true>;
+
+
+typedef boost::mpl::list<Fast_weighted_periodic_alpha_complex_3d, Exact_weighted_periodic_alpha_complex_3d,
+ Safe_weighted_periodic_alpha_complex_3d>
+ wp_variants_type_list;
+
+#ifdef GUDHI_DEBUG
+BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_weighted_periodic_throw, Weighted_periodic_alpha_complex_3d,
+ wp_variants_type_list) {
+ std::cout << "Weighted periodic alpha complex 3d exception throw" << std::endl;
+
+ using Creator = CGAL::Creator_uniform_3<double, typename Weighted_periodic_alpha_complex_3d::Point_3>;
+ CGAL::Random random(7);
+ CGAL::Random_points_in_cube_3<typename Weighted_periodic_alpha_complex_3d::Point_3, Creator> in_cube(1, random);
+ std::vector<typename Weighted_periodic_alpha_complex_3d::Point_3> wp_points;
+
+ for (int i = 0; i < 50; i++) {
+ typename Weighted_periodic_alpha_complex_3d::Point_3 p = *in_cube++;
+ wp_points.push_back(p);
+ }
+ std::vector<double> p_weights;
+ // Weights must be in range ]0, 1/64 = 0.015625[
+ for (std::size_t i = 0; i < wp_points.size(); ++i) {
+ p_weights.push_back(random.get_double(0., 0.01));
+ }
+
+ std::cout << "Cuboid is not iso exception" << std::endl;
+ // Check it throws an exception when the cuboid is not iso
+ BOOST_CHECK_THROW(
+ Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 0.9, 1., 1.),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(
+ Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 0.9, 1.),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(
+ Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 1., 0.9),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(
+ Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1.1, 1., 1.),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(
+ Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 1.1, 1.),
+ std::invalid_argument);
+ BOOST_CHECK_THROW(
+ Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, -1., -1., -1., 1., 1., 1.1),
+ std::invalid_argument);
+
+ std::cout << "0 <= point.weight() < 1/64 * domain_size * domain_size exception" << std::endl;
+ // Weights must be in range ]0, 1/64 = 0.015625[
+ double temp = p_weights[25];
+ p_weights[25] = 1.0;
+ BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.),
+ std::invalid_argument);
+ // Weights must be in range ]0, 1/64 = 0.015625[
+ p_weights[25] = temp;
+ temp = p_weights[14];
+ p_weights[14] = -1e-10;
+ BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.),
+ std::invalid_argument);
+ p_weights[14] = temp;
+
+ std::cout << "wp_points and p_weights size exception" << std::endl;
+ // Weights and points must have the same size
+ // + 1
+ p_weights.push_back(1e-10);
+ BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.),
+ std::invalid_argument);
+ // - 1
+ p_weights.pop_back();
+ p_weights.pop_back();
+ BOOST_CHECK_THROW(Weighted_periodic_alpha_complex_3d wp_alpha_complex(wp_points, p_weights, 0., 0., 0., 1., 1., 1.),
+ std::invalid_argument);
+}
+#endif
+
+BOOST_AUTO_TEST_CASE(Alpha_complex_weighted_periodic) {
+ // ---------------------
+ // Fast weighted periodic version
+ // ---------------------
+ std::cout << "Fast weighted periodic alpha complex 3d" << std::endl;
+
+ using Creator = CGAL::Creator_uniform_3<double, Fast_weighted_periodic_alpha_complex_3d::Point_3>;
+ CGAL::Random random(7);
+ CGAL::Random_points_in_cube_3<Fast_weighted_periodic_alpha_complex_3d::Point_3, Creator> in_cube(1, random);
+ std::vector<Fast_weighted_periodic_alpha_complex_3d::Point_3> p_points;
+
+ for (int i = 0; i < 50; i++) {
+ Fast_weighted_periodic_alpha_complex_3d::Point_3 p = *in_cube++;
+ p_points.push_back(p);
+ }
+ std::vector<double> p_weights;
+ // Weights must be in range ]0, 1/64 = 0.015625[
+ for (std::size_t i = 0; i < p_points.size(); ++i) {
+ p_weights.push_back(random.get_double(0., 0.01));
+ }
+
+ Fast_weighted_periodic_alpha_complex_3d periodic_alpha_complex(p_points, p_weights, -1., -1., -1., 1., 1., 1.);
+
+ Gudhi::Simplex_tree<> stree;
+ periodic_alpha_complex.create_complex(stree);
+
+ // ----------------------
+ // Exact weighted periodic version
+ // ----------------------
+ std::cout << "Exact weighted periodic alpha complex 3d" << std::endl;
+
+ std::vector<Exact_weighted_periodic_alpha_complex_3d::Point_3> e_p_points;
+
+ for (auto p : p_points) {
+ e_p_points.push_back(Exact_weighted_periodic_alpha_complex_3d::Point_3(p[0], p[1], p[2]));
+ }
+
+ Exact_weighted_periodic_alpha_complex_3d exact_alpha_complex(e_p_points, p_weights, -1., -1., -1., 1., 1., 1.);
+
+ Gudhi::Simplex_tree<> exact_stree;
+ exact_alpha_complex.create_complex(exact_stree);
+
+ // ---------------------
+ // Compare both versions
+ // ---------------------
+ std::cout << "Exact weighted periodic alpha complex 3d is of dimension " << exact_stree.dimension()
+ << " - Non exact is " << stree.dimension() << std::endl;
+ BOOST_CHECK(exact_stree.dimension() == stree.dimension());
+ std::cout << "Exact weighted periodic alpha complex 3d num_simplices " << exact_stree.num_simplices()
+ << " - Non exact is " << stree.num_simplices() << std::endl;
+ BOOST_CHECK(exact_stree.num_simplices() == stree.num_simplices());
+ std::cout << "Exact weighted periodic alpha complex 3d num_vertices " << exact_stree.num_vertices()
+ << " - Non exact is " << stree.num_vertices() << std::endl;
+ BOOST_CHECK(exact_stree.num_vertices() == stree.num_vertices());
+
+ // We cannot compare as objects from dispatcher on the alpha shape is not deterministic.
+ // cf. https://github.com/CGAL/cgal/issues/3346
+ auto sh = stree.filtration_simplex_range().begin();
+ auto sh_exact = exact_stree.filtration_simplex_range().begin();
+
+ while (sh != stree.filtration_simplex_range().end() || sh_exact != exact_stree.filtration_simplex_range().end()) {
+ GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), exact_stree.filtration(*sh_exact), 1e-14);
+
+ std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end());
+ std::vector<int> exact_vh(exact_stree.simplex_vertex_range(*sh_exact).begin(),
+ exact_stree.simplex_vertex_range(*sh_exact).end());
+
+ BOOST_CHECK(vh.size() == exact_vh.size());
+ ++sh;
+ ++sh_exact;
+ }
+
+ BOOST_CHECK(sh == stree.filtration_simplex_range().end());
+ BOOST_CHECK(sh_exact == exact_stree.filtration_simplex_range().end());
+
+ // ----------------------
+ // Safe weighted periodic version
+ // ----------------------
+ std::cout << "Safe weighted periodic alpha complex 3d" << std::endl;
+
+ std::vector<Safe_weighted_periodic_alpha_complex_3d::Point_3> s_p_points;
+
+ for (auto p : p_points) {
+ s_p_points.push_back(Safe_weighted_periodic_alpha_complex_3d::Point_3(p[0], p[1], p[2]));
+ }
+
+ Safe_weighted_periodic_alpha_complex_3d safe_alpha_complex(s_p_points, p_weights, -1., -1., -1., 1., 1., 1.);
+
+ Gudhi::Simplex_tree<> safe_stree;
+ safe_alpha_complex.create_complex(safe_stree);
+
+ // ---------------------
+ // Compare both versions
+ // ---------------------
+ // We cannot compare as objects from dispatcher on the alpha shape is not deterministic.
+ // cf. https://github.com/CGAL/cgal/issues/3346
+ sh = stree.filtration_simplex_range().begin();
+ auto sh_safe = safe_stree.filtration_simplex_range().begin();
+
+ while (sh != stree.filtration_simplex_range().end() || sh_safe != safe_stree.filtration_simplex_range().end()) {
+ GUDHI_TEST_FLOAT_EQUALITY_CHECK(stree.filtration(*sh), safe_stree.filtration(*sh_safe), 1e-14);
+
+ std::vector<int> vh(stree.simplex_vertex_range(*sh).begin(), stree.simplex_vertex_range(*sh).end());
+ std::vector<int> safe_vh(safe_stree.simplex_vertex_range(*sh_safe).begin(),
+ safe_stree.simplex_vertex_range(*sh_safe).end());
+
+ BOOST_CHECK(vh.size() == safe_vh.size());
+ ++sh;
+ ++sh_safe;
+ }
+
+ BOOST_CHECK(sh == stree.filtration_simplex_range().end());
+ BOOST_CHECK(sh_safe == safe_stree.filtration_simplex_range().end());
+}
diff --git a/src/Alpha_complex/utilities/CMakeLists.txt b/src/Alpha_complex/utilities/CMakeLists.txt
index 7ace6064..b12c9690 100644
--- a/src/Alpha_complex/utilities/CMakeLists.txt
+++ b/src/Alpha_complex/utilities/CMakeLists.txt
@@ -1,64 +1,61 @@
project(Alpha_complex_utilities)
-if(CGAL_FOUND)
- add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp)
- target_link_libraries(alpha_complex_3d_persistence ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
- add_executable(exact_alpha_complex_3d_persistence exact_alpha_complex_3d_persistence.cpp)
- target_link_libraries(exact_alpha_complex_3d_persistence ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
- add_executable(weighted_alpha_complex_3d_persistence weighted_alpha_complex_3d_persistence.cpp)
- target_link_libraries(weighted_alpha_complex_3d_persistence ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
+ add_executable (alpha_complex_persistence alpha_complex_persistence.cpp)
+ target_link_libraries(alpha_complex_persistence ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
if (TBB_FOUND)
- target_link_libraries(alpha_complex_3d_persistence ${TBB_LIBRARIES})
- target_link_libraries(exact_alpha_complex_3d_persistence ${TBB_LIBRARIES})
- target_link_libraries(weighted_alpha_complex_3d_persistence ${TBB_LIBRARIES})
+ target_link_libraries(alpha_complex_persistence ${TBB_LIBRARIES})
endif(TBB_FOUND)
-
- add_test(NAME Alpha_complex_utilities_alpha_complex_3d_persistence COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ add_test(NAME Alpha_complex_utilities_alpha_complex_persistence COMMAND $<TARGET_FILE:alpha_complex_persistence>
"${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45")
- add_test(NAME Alpha_complex_utilities_exact_alpha_complex_3d COMMAND $<TARGET_FILE:exact_alpha_complex_3d_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45")
- add_test(NAME Alpha_complex_utilities_weighted_alpha_complex_3d COMMAND $<TARGET_FILE:weighted_alpha_complex_3d_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.weights" "-p" "2" "-m" "0.45")
-
- install(TARGETS alpha_complex_3d_persistence DESTINATION bin)
- install(TARGETS exact_alpha_complex_3d_persistence DESTINATION bin)
- install(TARGETS weighted_alpha_complex_3d_persistence DESTINATION bin)
-
- if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
- add_executable (alpha_complex_persistence alpha_complex_persistence.cpp)
- target_link_libraries(alpha_complex_persistence ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
-
- add_executable(periodic_alpha_complex_3d_persistence periodic_alpha_complex_3d_persistence.cpp)
- target_link_libraries(periodic_alpha_complex_3d_persistence ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
-
- if (TBB_FOUND)
- target_link_libraries(alpha_complex_persistence ${TBB_LIBRARIES})
- target_link_libraries(periodic_alpha_complex_3d_persistence ${TBB_LIBRARIES})
- endif(TBB_FOUND)
- add_test(NAME Alpha_complex_utilities_alpha_complex_persistence COMMAND $<TARGET_FILE:alpha_complex_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45")
- add_test(NAME Alpha_complex_utilities_periodic_alpha_complex_3d_persistence COMMAND $<TARGET_FILE:periodic_alpha_complex_3d_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off" "${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt" "-p" "2" "-m" "0")
- install(TARGETS alpha_complex_persistence DESTINATION bin)
- install(TARGETS periodic_alpha_complex_3d_persistence DESTINATION bin)
+ install(TARGETS alpha_complex_persistence DESTINATION bin)
- endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
+endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
- if (NOT CGAL_VERSION VERSION_LESS 4.11.0)
- add_executable(weighted_periodic_alpha_complex_3d_persistence weighted_periodic_alpha_complex_3d_persistence.cpp)
- target_link_libraries(weighted_periodic_alpha_complex_3d_persistence ${CGAL_LIBRARY})
- if (TBB_FOUND)
- target_link_libraries(weighted_periodic_alpha_complex_3d_persistence ${TBB_LIBRARIES})
- endif(TBB_FOUND)
-
- add_test(NAME Alpha_complex_utilities_weigted_periodic_alpha_complex_3d COMMAND $<TARGET_FILE:weighted_periodic_alpha_complex_3d_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off" "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.weights"
- "${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt" "3" "1.0")
+if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp)
+ target_link_libraries(alpha_complex_3d_persistence ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(alpha_complex_3d_persistence ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
- install(TARGETS weighted_periodic_alpha_complex_3d_persistence DESTINATION bin)
+ add_test(NAME Alpha_complex_utilities_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
+ "-p" "2" "-m" "0.45" "-o" "alpha.pers")
+
+ add_test(NAME Alpha_complex_utilities_exact_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
+ "-p" "2" "-m" "0.45" "-o" "exact.pers" "-e")
+
+ add_test(NAME Alpha_complex_utilities_safe_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
+ "-p" "2" "-m" "0.45" "-o" "safe.pers" "-s")
+
+ if (DIFF_PATH)
+ add_test(Alpha_complex_utilities_diff_alpha_complex_3d ${DIFF_PATH}
+ "exact.pers" "alpha.pers")
+ add_test(Alpha_complex_utilities_diff_alpha_complex_3d ${DIFF_PATH}
+ "safe.pers" "alpha.pers")
+ endif()
+
+ add_test(NAME Alpha_complex_utilities_periodic_alpha_complex_3d_persistence COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off"
+ "-c" "${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt"
+ "-p" "2" "-m" "0")
+
+ add_test(NAME Alpha_complex_utilities_weighted_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off"
+ "-w" "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.weights"
+ "-p" "2" "-m" "0")
+
+ add_test(NAME Alpha_complex_utilities_weighted_periodic_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off"
+ "-w" "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.weights"
+ "-c" "${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt"
+ "-p" "2" "-m" "0" "-e")
- endif (NOT CGAL_VERSION VERSION_LESS 4.11.0)
+ install(TARGETS alpha_complex_3d_persistence DESTINATION bin)
-endif(CGAL_FOUND)
+endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
diff --git a/src/Alpha_complex/utilities/alpha_complex_3d_helper.h b/src/Alpha_complex/utilities/alpha_complex_3d_helper.h
deleted file mode 100644
index a72fd96d..00000000
--- a/src/Alpha_complex/utilities/alpha_complex_3d_helper.h
+++ /dev/null
@@ -1,74 +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
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#ifndef ALPHA_COMPLEX_3D_HELPER_H_
-#define ALPHA_COMPLEX_3D_HELPER_H_
-
-template <class Vertex_list, class Cell_handle>
-Vertex_list from_cell(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;
-}
-
-template <class Vertex_list, class Facet>
-Vertex_list from_facet(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;
-}
-
-template <class Vertex_list, class Edge_3>
-Vertex_list from_edge(const Edge_3& edg) {
- Vertex_list the_list;
- for (auto i : {edg.second, edg.third}) {
-#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;
-}
-
-template <class Vertex_list, class Vertex_handle>
-Vertex_list from_vertex(const 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;
-}
-
-#endif // ALPHA_COMPLEX_3D_HELPER_H_
diff --git a/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp b/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp
index 6e603155..19e608ad 100644
--- a/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp
+++ b/src/Alpha_complex/utilities/alpha_complex_3d_persistence.cpp
@@ -20,188 +20,219 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <boost/version.hpp>
#include <boost/program_options.hpp>
#include <boost/variant.hpp>
-#if BOOST_VERSION >= 105400
-#include <boost/container/static_vector.hpp>
-#endif
-
+#include <gudhi/Alpha_complex_3d.h>
#include <gudhi/Simplex_tree.h>
#include <gudhi/Persistent_cohomology.h>
#include <gudhi/Points_3D_off_io.h>
-#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
-#include <CGAL/Delaunay_triangulation_3.h>
-#include <CGAL/Alpha_shape_3.h>
-#include <CGAL/Alpha_shape_cell_base_3.h>
-#include <CGAL/Alpha_shape_vertex_base_3.h>
-#include <CGAL/iterator.h>
-
#include <fstream>
-#include <cmath>
#include <string>
-#include <tuple>
-#include <map>
-#include <utility>
#include <vector>
-#include <cstdlib>
-
-#include "alpha_complex_3d_helper.h"
-
-// Alpha_shape_3 templates type definitions
-using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
-using Vb = CGAL::Alpha_shape_vertex_base_3<Kernel>;
-using Fb = CGAL::Alpha_shape_cell_base_3<Kernel>;
-using Tds = CGAL::Triangulation_data_structure_3<Vb, Fb>;
-using Triangulation_3 = CGAL::Delaunay_triangulation_3<Kernel, Tds>;
-using Alpha_shape_3 = CGAL::Alpha_shape_3<Triangulation_3>;
-
-// From file type definition
-using Point_3 = Kernel::Point_3;
-
-// filtration with alpha values needed type definition
-using Alpha_value_type = Alpha_shape_3::FT;
-using Object = CGAL::Object;
-using Dispatch =
- CGAL::Dispatch_output_iterator<CGAL::cpp11::tuple<Object, Alpha_value_type>,
- CGAL::cpp11::tuple<std::back_insert_iterator<std::vector<Object> >,
- std::back_insert_iterator<std::vector<Alpha_value_type> > > >;
-using Cell_handle = Alpha_shape_3::Cell_handle;
-using Facet = Alpha_shape_3::Facet;
-using Edge_3 = Alpha_shape_3::Edge;
-using Vertex_handle = Alpha_shape_3::Vertex_handle;
-
-#if BOOST_VERSION >= 105400
-using Vertex_list = boost::container::static_vector<Alpha_shape_3::Vertex_handle, 4>;
-#else
-using Vertex_list = std::vector<Alpha_shape_3::Vertex_handle>;
-#endif
+#include <limits> // for numeric_limits<>
// gudhi type definition
-using ST = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
-using Filtration_value = ST::Filtration_value;
-using Simplex_tree_vertex = ST::Vertex_handle;
-using Alpha_shape_simplex_tree_map = std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex>;
-using Simplex_tree_vector_vertex = std::vector<Simplex_tree_vertex>;
+using Simplex_tree = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+using Filtration_value = Simplex_tree::Filtration_value;
using Persistent_cohomology =
- Gudhi::persistent_cohomology::Persistent_cohomology<ST, Gudhi::persistent_cohomology::Field_Zp>;
-
-void program_options(int argc, char *argv[], std::string &off_file_points, std::string &output_file_diag,
- int &coeff_field_characteristic, Filtration_value &min_persistence);
-
-int main(int argc, char **argv) {
- std::string off_file_points;
- std::string output_file_diag;
- int coeff_field_characteristic;
- Filtration_value min_persistence;
+ Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Gudhi::persistent_cohomology::Field_Zp>;
+
+void program_options(int argc, char *argv[], std::string &off_file_points, bool &exact, bool &safe,
+ std::string &weight_file, std::string &cuboid_file, std::string &output_file_diag,
+ Filtration_value &alpha_square_max_value, int &coeff_field_characteristic,
+ Filtration_value &min_persistence);
+
+bool read_weight_file(const std::string &weight_file, std::vector<double> &weights) {
+ // Read weights information from file
+ std::ifstream weights_ifstr(weight_file);
+ if (weights_ifstr.good()) {
+ double weight = 0.0;
+ // Attempt read the weight in a double format, return false if it fails
+ while (weights_ifstr >> weight) {
+ weights.push_back(weight);
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
- program_options(argc, argv, off_file_points, output_file_diag, coeff_field_characteristic, min_persistence);
+bool read_cuboid_file(const std::string &cuboid_file, double &x_min, double &y_min, double &z_min, double &x_max,
+ double &y_max, double &z_max) {
+ // Read weights information from file
+ std::ifstream iso_cuboid_str(cuboid_file);
+ if (iso_cuboid_str.is_open()) {
+ if (!(iso_cuboid_str >> x_min >> y_min >> z_min >> x_max >> y_max >> z_max)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+template <typename AlphaComplex3d>
+std::vector<typename AlphaComplex3d::Point_3> read_off(const std::string &off_file_points) {
// Read the OFF file (input file name given as parameter) and triangulate points
- Gudhi::Points_3D_off_reader<Point_3> off_reader(off_file_points);
+ Gudhi::Points_3D_off_reader<typename AlphaComplex3d::Point_3> off_reader(off_file_points);
// Check the read operation was correct
if (!off_reader.is_valid()) {
- std::cerr << "Unable to read file " << off_file_points << std::endl;
+ std::cerr << "Unable to read OFF file " << off_file_points << std::endl;
exit(-1);
}
+ return off_reader.get_point_cloud();
+}
- // Retrieve the points
- std::vector<Point_3> lp = off_reader.get_point_cloud();
-
- // 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<Object> the_objects;
- std::vector<Alpha_value_type> the_alpha_values;
-
- Dispatch disp = CGAL::dispatch_output<Object, Alpha_value_type>(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<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin();
- for (auto object_iterator : the_objects) {
- // Retrieve Alpha shape vertex list from object
- if (const Cell_handle *cell = CGAL::object_cast<Cell_handle>(&object_iterator)) {
- vertex_list = from_cell<Vertex_list, Cell_handle>(*cell);
- count_cells++;
- } else if (const Facet *facet = CGAL::object_cast<Facet>(&object_iterator)) {
- vertex_list = from_facet<Vertex_list, Facet>(*facet);
- count_facets++;
- } else if (const Edge_3 *edge = CGAL::object_cast<Edge_3>(&object_iterator)) {
- vertex_list = from_edge<Vertex_list, Edge_3>(*edge);
- count_edges++;
- } else if (const Vertex_handle *vertex = CGAL::object_cast<Vertex_handle>(&object_iterator)) {
- count_vertices++;
- vertex_list = from_vertex<Vertex_list, Vertex_handle>(*vertex);
- }
- // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex
- Simplex_tree_vector_vertex the_simplex;
- 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.push_back(vertex);
- map_cgal_simplex_tree.emplace(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.push_back(vertex);
- }
+int main(int argc, char **argv) {
+ std::string off_file_points;
+ std::string weight_file;
+ std::string cuboid_file;
+ std::string output_file_diag;
+ Filtration_value alpha_square_max_value = 0.;
+ int coeff_field_characteristic = 0;
+ Filtration_value min_persistence = 0.;
+ bool exact_version = false;
+ bool safe_version = false;
+ bool weighted_version = false;
+ bool periodic_version = false;
+
+ program_options(argc, argv, off_file_points, exact_version, safe_version, weight_file, cuboid_file, output_file_diag,
+ alpha_square_max_value, coeff_field_characteristic, min_persistence);
+
+ std::vector<double> weights;
+ if (weight_file != std::string()) {
+ if (!read_weight_file(weight_file, weights)) {
+ std::cerr << "Unable to read weights file " << weight_file << std::endl;
+ exit(-1);
}
- // 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
- simplex_tree.insert_simplex(the_simplex, filtr);
- GUDHI_CHECK(the_alpha_value_iterator != the_alpha_values.end(), "CGAL provided more simplices than values");
- ++the_alpha_value_iterator;
+ weighted_version = true;
}
-#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;
+ double x_min = 0., y_min = 0., z_min = 0., x_max = 0., y_max = 0., z_max = 0.;
+ std::ifstream iso_cuboid_str(argv[3]);
+ if (cuboid_file != std::string()) {
+ if (!read_cuboid_file(cuboid_file, x_min, y_min, z_min, x_max, y_max, z_max)) {
+ std::cerr << "Unable to read cuboid file " << cuboid_file << std::endl;
+ exit(-1);
+ }
+ periodic_version = true;
+ }
- 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() << " ";
-#endif // DEBUG_TRACES
+ Gudhi::alpha_complex::complexity complexity = Gudhi::alpha_complex::complexity::FAST;
+ if (exact_version) {
+ if (safe_version) {
+ std::cerr << "You cannot set the exact and the safe version." << std::endl;
+ exit(-1);
+ }
+ complexity = Gudhi::alpha_complex::complexity::EXACT;
+ }
+ if (safe_version) {
+ complexity = Gudhi::alpha_complex::complexity::SAFE;
+ }
-#ifdef DEBUG_TRACES
- std::cout << "Iterator on vertices: " << std::endl;
- for (auto vertex : simplex_tree.complex_vertex_range()) {
- std::cout << vertex << " ";
+ Simplex_tree simplex_tree;
+
+ switch (complexity) {
+ case Gudhi::alpha_complex::complexity::FAST:
+ if (weighted_version) {
+ if (periodic_version) {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, true>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points, weights, x_min, y_min, z_min, x_max, y_max, z_max);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ } else {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, true, false>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points, weights);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ }
+ } else {
+ if (periodic_version) {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, false, true>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points, x_min, y_min, z_min, x_max, y_max, z_max);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ } else {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::FAST, false, false>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ }
+ }
+ break;
+ case Gudhi::alpha_complex::complexity::EXACT:
+ if (weighted_version) {
+ if (periodic_version) {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, true>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points, weights, x_min, y_min, z_min, x_max, y_max, z_max);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ } else {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, false>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points, weights);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ }
+ } else {
+ if (periodic_version) {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, true>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points, x_min, y_min, z_min, x_max, y_max, z_max);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ } else {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, false, false>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ }
+ }
+ break;
+ case Gudhi::alpha_complex::complexity::SAFE:
+ if (weighted_version) {
+ if (periodic_version) {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, true>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points, weights, x_min, y_min, z_min, x_max, y_max, z_max);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ } else {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, true, false>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points, weights);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ }
+ } else {
+ if (periodic_version) {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, true>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points, x_min, y_min, z_min, x_max, y_max, z_max);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ } else {
+ using Alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::SAFE, false, false>;
+ auto points = read_off<Alpha_complex_3d>(off_file_points);
+ Alpha_complex_3d alpha_complex(points);
+ alpha_complex.create_complex(simplex_tree, alpha_square_max_value);
+ }
+ }
+ break;
+ default:
+ std::cerr << "Unknown complexity value " << std::endl;
+ exit(-1);
+ break;
}
-#endif // DEBUG_TRACES
// Sort the simplices in the order of the filtration
simplex_tree.initialize_filtration();
@@ -227,8 +258,10 @@ int main(int argc, char **argv) {
return 0;
}
-void program_options(int argc, char *argv[], std::string &off_file_points, std::string &output_file_diag,
- int &coeff_field_characteristic, Filtration_value &min_persistence) {
+void program_options(int argc, char *argv[], std::string &off_file_points, bool &exact, bool &safe,
+ std::string &weight_file, std::string &cuboid_file, 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<std::string>(&off_file_points),
@@ -236,8 +269,20 @@ void program_options(int argc, char *argv[], std::string &off_file_points, std::
po::options_description visible("Allowed options", 100);
visible.add_options()("help,h", "produce help message")(
+ "exact,e", po::bool_switch(&exact),
+ "To activate exact version of Alpha complex 3d (default is false, not available if safe is set)")(
+ "safe,s", po::bool_switch(&safe),
+ "To activate safe version of Alpha complex 3d (default is false, not available if exact is set)")(
+ "weight-file,w", po::value<std::string>(&weight_file)->default_value(std::string()),
+ "Name of file containing a point weights. Format is one weight per line:\n W1\n ...\n Wn ")(
+ "cuboid-file,c", po::value<std::string>(&cuboid_file),
+ "Name of file describing the periodic domain. Format is:\n min_hx min_hy min_hz\n max_hx max_hy max_hz")(
"output-file,o", po::value<std::string>(&output_file_diag)->default_value(std::string()),
"Name of file in which the persistence diagram is written. Default print in std::cout")(
+ "max-alpha-square-value,r",
+ po::value<Filtration_value>(&alpha_square_max_value)
+ ->default_value(std::numeric_limits<Filtration_value>::infinity()),
+ "Maximal alpha square value for the Alpha complex construction.")(
"field-charac,p", po::value<int>(&coeff_field_characteristic)->default_value(11),
"Characteristic p of the coefficient field Z/pZ for computing homology.")(
"min-persistence,m", po::value<Filtration_value>(&min_persistence),
@@ -254,17 +299,18 @@ void program_options(int argc, char *argv[], std::string &off_file_points, std::
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")) {
+ if (vm.count("help") || !vm.count("input-file") || !vm.count("weight-file")) {
std::cout << std::endl;
std::cout << "Compute the persistent homology with coefficient field Z/pZ \n";
- std::cout << "of a 3D Alpha complex defined on a set of input points.\n \n";
+ std::cout << "of a 3D Alpha complex defined on a set of input points.\n";
+ std::cout << "3D Alpha complex can be exact or safe, weighted and/or periodic\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 << "p is the characteristic of the field Z/pZ used for homology coefficients.\n\n";
- std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl << std::endl;
+ std::cout << "Usage: " << argv[0] << " [options] input-file weight-file\n\n";
std::cout << visible << std::endl;
exit(-1);
}
diff --git a/src/Alpha_complex/utilities/alphacomplex.md b/src/Alpha_complex/utilities/alphacomplex.md
index 0fe98837..98f56802 100644
--- a/src/Alpha_complex/utilities/alphacomplex.md
+++ b/src/Alpha_complex/utilities/alphacomplex.md
@@ -12,15 +12,18 @@ Leave the lines above as it is required by the web site generator 'Jekyll'
## alpha_complex_persistence ##
-This program computes the persistent homology with coefficient field Z/pZ of the dD alpha complex built from a dD point cloud.
+This program computes the persistent homology with coefficient field Z/pZ of
+the dD alpha complex built from a dD point cloud.
The output diagram contains one bar per line, written with the convention:
```
p dim birth death
```
-where `dim` is the dimension of the homological feature, `birth` and `death` are respectively the birth and death of the feature,
-and `p` is the characteristic of the field *Z/pZ* used for homology coefficients (`p` must be a prime number).
+where `dim` is the dimension of the homological feature, `birth` and `death`
+are respectively the birth and death of the feature, and `p` is the
+characteristic of the field *Z/pZ* used for homology coefficients (`p` must be
+a prime number).
**Usage**
@@ -29,15 +32,20 @@ and `p` is the characteristic of the field *Z/pZ* used for homology coefficients
```
where
-`<input OFF file>` is the path to the input point cloud in [nOFF ASCII format](http://www.geomview.org/docs/html/OFF.html).
+`<input OFF file>` is the path to the input point cloud in
+[nOFF ASCII format](http://www.geomview.org/docs/html/OFF.html).
**Allowed options**
* `-h [ --help ]` Produce help message
-* `-o [ --output-file ]` Name of file in which the persistence diagram is written. Default print in standard output.
-* `-r [ --max-alpha-square-value ]` (default = inf) Maximal alpha square value for the Alpha complex construction.
-* `-p [ --field-charac ]` (default = 11) Characteristic p of the coefficient field Z/pZ for computing homology.
-* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals.
+* `-o [ --output-file ]` Name of file in which the persistence diagram is
+written. Default print in standard output.
+* `-r [ --max-alpha-square-value ]` (default = inf) Maximal alpha square value
+for the Alpha complex construction.
+* `-p [ --field-charac ]` (default = 11) Characteristic p of the
+coefficient field Z/pZ for computing homology.
+* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature
+to be recorded. Enter a negative value to see zero length intervals.
**Example**
@@ -51,13 +59,26 @@ N.B.:
## alpha_complex_3d_persistence ##
-This program computes the persistent homology with coefficient field Z/pZ of the 3D alpha complex built from a 3D point cloud. The output diagram contains one bar per line, written with the convention:
+This program computes the persistent homology with coefficient field Z/pZ of
+the 3D alpha complex built from a 3D point cloud.
+One can use exact computation. It is slower, but it is necessary when points
+are on a grid for instance.
+Alpha complex 3d can be weighted and/or periodic (refer to the
+[CGAL's 3D Periodic Triangulations User Manual](
+https://doc.cgal.org/latest/Periodic_3_triangulation_3/index.html)
+for more details).
+
+The output diagram contains
+one bar per line, written with the convention:
```
p dim birth death
```
-where `dim` is the dimension of the homological feature, `birth` and `death` are respectively the birth and death of the feature, and `p` is the characteristic of the field *Z/pZ* used for homology coefficients (`p` must be a prime number).
+where `dim` is the dimension of the homological feature, `birth` and `death`
+are respectively the birth and death of the feature, and `p` is the
+characteristic of the field *Z/pZ* used for homology coefficients (`p` must be
+a prime number).
**Usage**
@@ -65,14 +86,27 @@ where `dim` is the dimension of the homological feature, `birth` and `death` are
alpha_complex_3d_persistence [options] <input OFF file>
```
-where `<input OFF file>` is the path to the input point cloud in [nOFF ASCII format](http://www.geomview.org/docs/html/OFF.html).
+where `<input OFF file>` is the path to the input point cloud in
+[nOFF ASCII format](http://www.geomview.org/docs/html/OFF.html).
**Allowed options**
* `-h [ --help ]` Produce help message
-* `-o [ --output-file ]` Name of file in which the persistence diagram is written. Default print in standard output.
-* `-p [ --field-charac ]` (default=11) Characteristic p of the coefficient field Z/pZ for computing homology.
-* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals.
+* `-o [ --output-file ]` Name of file in which the persistence diagram is
+written. Default print in standard output.
+* `-r [ --max-alpha-square-value ]` (default = inf) Maximal alpha square value
+for the Alpha complex construction.
+* `-p [ --field-charac ]` (default=11) Characteristic p of the coefficient
+field Z/pZ for computing homology.
+* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature
+to be recorded. Enter a negative value to see zero length intervals.
+* `-c [ --cuboid-file ]` is the path to the file describing the periodic domain.
+It must be in the format described
+[here]({{ site.officialurl }}/doc/latest/fileformats.html#FileFormatsIsoCuboid).
+* `-w [ --weight-file ]` is the path to the file containing the weights of the
+points (one value per line).
+* `-e [ --exact ]` for the exact computation version (not compatible with
+weight and periodic version).
**Example**
@@ -84,82 +118,7 @@ N.B.:
* `alpha_complex_3d_persistence` only accepts OFF files in dimension 3.
* Filtration values are alpha square values.
-
-
-## exact_alpha_complex_3d_persistence ##
-
-Same as `alpha_complex_3d_persistence`, but using exact computation.
-It is slower, but it is necessary when points are on a grid for instance.
-
-
-
-## weighted_alpha_complex_3d_persistence ##
-
-Same as `alpha_complex_3d_persistence`, but using weighted points.
-
-**Usage**
-
-```
- weighted_alpha_complex_3d_persistence [options] <input OFF file> <weights input file>
-```
-
-where
-
-* `<input OFF file>` is the path to the input point cloud in [nOFF ASCII format](http://www.geomview.org/docs/html/OFF.html).
-* `<input weights file>` is the path to the file containing the weights of the points (one value per line).
-
-**Allowed options**
-
-* `-h [ --help ]` Produce help message
-* `-o [ --output-file ]` Name of file in which the persistence diagram is written. Default print in standard output.
-* `-p [ --field-charac ]` (default=11) Characteristic p of the coefficient field Z/pZ for computing homology.
-* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals.
-
-**Example**
-
-```
- weighted_alpha_complex_3d_persistence ../../data/points/tore3D_300.off ../../data/points/tore3D_300.weights -p 2 -m 0.45
-```
-
-
-N.B.:
-
-* Weights values are explained on CGAL [Alpha shape](https://doc.cgal.org/latest/Alpha_shapes_3/index.html#title0)
-and [Regular triangulation](https://doc.cgal.org/latest/Triangulation_3/index.html#Triangulation3secclassRegulartriangulation) documentation.
-* Filtration values are alpha square values.
-
-
-## periodic_alpha_complex_3d_persistence ##
-Same as `alpha_complex_3d_persistence`, but using periodic alpha shape 3d.
-Refer to the [CGAL's 3D Periodic Triangulations User Manual](https://doc.cgal.org/latest/Periodic_3_triangulation_3/index.html) for more details.
-
-**Usage**
-
-```
- periodic_alpha_complex_3d_persistence [options] <input OFF file> <cuboid file>
-```
-
-where
-
-* `<input OFF file>` is the path to the input point cloud in [nOFF ASCII format](http://www.geomview.org/docs/html/OFF.html).
-* `<cuboid file>` is the path to the file describing the periodic domain. It must be in the format described
-[here](/doc/latest/fileformats.html#FileFormatsIsoCuboid).
-
-**Allowed options**
-
-* `-h [ --help ]` Produce help message
-* `-o [ --output-file ]` Name of file in which the persistence diagram is written. Default print in standard output.
-* `-p [ --field-charac ]` (default=11) Characteristic p of the coefficient field Z/pZ for computing homology.
-* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals
-
-
-**Example**
-
-```
-periodic_alpha_complex_3d_persistence ../../data/points/grid_10_10_10_in_0_1.off ../../data/points/iso_cuboid_3_in_0_1.txt -p 3 -m 1.0
-```
-
-N.B.:
-
-* Cuboid file must be in the format described [here](/doc/latest/fileformats.html#FileFormatsIsoCuboid).
-* Filtration values are alpha square values.
+* Weights values are explained on CGAL
+[Alpha shape](https://doc.cgal.org/latest/Alpha_shapes_3/index.html#title0)
+and
+[Regular triangulation](https://doc.cgal.org/latest/Triangulation_3/index.html#Triangulation3secclassRegulartriangulation) documentation.
diff --git a/src/Alpha_complex/utilities/exact_alpha_complex_3d_persistence.cpp b/src/Alpha_complex/utilities/exact_alpha_complex_3d_persistence.cpp
deleted file mode 100644
index 61f49bb1..00000000
--- a/src/Alpha_complex/utilities/exact_alpha_complex_3d_persistence.cpp
+++ /dev/null
@@ -1,265 +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
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#include <boost/program_options.hpp>
-#include <boost/variant.hpp>
-
-#include <gudhi/Simplex_tree.h>
-#include <gudhi/Persistent_cohomology.h>
-#include <gudhi/Points_3D_off_io.h>
-
-#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
-#include <CGAL/Delaunay_triangulation_3.h>
-#include <CGAL/Alpha_shape_3.h>
-#include <CGAL/Alpha_shape_cell_base_3.h>
-#include <CGAL/Alpha_shape_vertex_base_3.h>
-#include <CGAL/iterator.h>
-
-#include <fstream>
-#include <cmath>
-#include <string>
-#include <tuple>
-#include <map>
-#include <utility>
-#include <vector>
-#include <cstdlib>
-
-#include "alpha_complex_3d_helper.h"
-
-// Alpha_shape_3 templates type definitions
-using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
-using Exact_tag = CGAL::Tag_true;
-using Vb = CGAL::Alpha_shape_vertex_base_3<Kernel, CGAL::Default, Exact_tag>;
-using Fb = CGAL::Alpha_shape_cell_base_3<Kernel, CGAL::Default, Exact_tag>;
-using Tds = CGAL::Triangulation_data_structure_3<Vb, Fb>;
-using Triangulation_3 = CGAL::Delaunay_triangulation_3<Kernel, Tds>;
-using Alpha_shape_3 = CGAL::Alpha_shape_3<Triangulation_3, Exact_tag>;
-
-// From file type definition
-using Point_3 = Kernel::Point_3;
-
-// filtration with alpha values needed type definition
-using Alpha_value_type = Alpha_shape_3::FT;
-using Object = CGAL::Object;
-using Dispatch =
- CGAL::Dispatch_output_iterator<CGAL::cpp11::tuple<Object, Alpha_value_type>,
- CGAL::cpp11::tuple<std::back_insert_iterator<std::vector<Object> >,
- std::back_insert_iterator<std::vector<Alpha_value_type> > > >;
-using Cell_handle = Alpha_shape_3::Cell_handle;
-using Facet = Alpha_shape_3::Facet;
-using Edge_3 = Alpha_shape_3::Edge;
-using Vertex_handle = Alpha_shape_3::Vertex_handle;
-using Vertex_list = std::vector<Vertex_handle>;
-
-// gudhi type definition
-using ST = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
-using Filtration_value = ST::Filtration_value;
-using Simplex_tree_vertex = ST::Vertex_handle;
-using Alpha_shape_simplex_tree_map = std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex>;
-using Simplex_tree_vector_vertex = std::vector<Simplex_tree_vertex>;
-using Persistent_cohomology =
- Gudhi::persistent_cohomology::Persistent_cohomology<ST, Gudhi::persistent_cohomology::Field_Zp>;
-
-void program_options(int argc, char *argv[], std::string &off_file_points, std::string &output_file_diag,
- int &coeff_field_characteristic, Filtration_value &min_persistence);
-
-int main(int argc, char **argv) {
- std::string off_file_points;
- std::string output_file_diag;
- int coeff_field_characteristic;
- Filtration_value min_persistence;
-
- program_options(argc, argv, off_file_points, output_file_diag, coeff_field_characteristic, min_persistence);
-
- // Read the OFF file (input file name given as parameter) and triangulate points
- Gudhi::Points_3D_off_reader<Point_3> off_reader(off_file_points);
- // Check the read operation was correct
- if (!off_reader.is_valid()) {
- std::cerr << "Unable to read file " << off_file_points << std::endl;
- exit(-1);
- }
-
- // Retrieve the points
- std::vector<Point_3> lp = off_reader.get_point_cloud();
-
- // 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<Object> the_objects;
- std::vector<Alpha_value_type> the_alpha_values;
-
- Dispatch disp = CGAL::dispatch_output<Object, Alpha_value_type>(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<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin();
- for (auto object_iterator : the_objects) {
- // Retrieve Alpha shape vertex list from object
- if (const Cell_handle *cell = CGAL::object_cast<Cell_handle>(&object_iterator)) {
- vertex_list = from_cell<Vertex_list, Cell_handle>(*cell);
- count_cells++;
- } else if (const Facet *facet = CGAL::object_cast<Facet>(&object_iterator)) {
- vertex_list = from_facet<Vertex_list, Facet>(*facet);
- count_facets++;
- } else if (const Edge_3 *edge = CGAL::object_cast<Edge_3>(&object_iterator)) {
- vertex_list = from_edge<Vertex_list, Edge_3>(*edge);
- count_edges++;
- } else if (const Vertex_handle *vertex = CGAL::object_cast<Vertex_handle>(&object_iterator)) {
- count_vertices++;
- vertex_list = from_vertex<Vertex_list, Vertex_handle>(*vertex);
- }
- // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex
- Simplex_tree_vector_vertex the_simplex;
- 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.push_back(vertex);
- map_cgal_simplex_tree.emplace(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.push_back(vertex);
- }
- }
- // Construction of the simplex_tree
- // you can also use the_alpha_value_iterator->exact()
- Filtration_value filtr = /*std::sqrt*/ CGAL::to_double(the_alpha_value_iterator->exact());
-#ifdef DEBUG_TRACES
- std::cout << "filtration = " << filtr << std::endl;
-#endif // DEBUG_TRACES
- simplex_tree.insert_simplex(the_simplex, filtr);
- if (the_alpha_value_iterator != the_alpha_values.end())
- ++the_alpha_value_iterator;
- else
- std::cout << "This shall not happen" << std::endl;
- }
-
-#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() << " ";
-#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 pcoh(simplex_tree, true);
- // initializes the coefficient field for homology
- pcoh.init_coefficients(coeff_field_characteristic);
-
- pcoh.compute_persistent_cohomology(min_persistence);
-
- // Output the diagram in filediag
- if (output_file_diag.empty()) {
- pcoh.output_diagram();
- } else {
- std::cout << "Result in file: " << output_file_diag << std::endl;
- std::ofstream out(output_file_diag);
- pcoh.output_diagram(out);
- out.close();
- }
-
- return 0;
-}
-
-void program_options(int argc, char *argv[], std::string &off_file_points, std::string &output_file_diag,
- 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<std::string>(&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<std::string>(&output_file_diag)->default_value(std::string()),
- "Name of file in which the persistence diagram is written. Default print in std::cout")(
- "field-charac,p", po::value<int>(&coeff_field_characteristic)->default_value(11),
- "Characteristic p of the coefficient field Z/pZ for computing homology.")(
- "min-persistence,m", po::value<Filtration_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 a 3D 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;
- exit(-1);
- }
-}
diff --git a/src/Alpha_complex/utilities/periodic_alpha_complex_3d_persistence.cpp b/src/Alpha_complex/utilities/periodic_alpha_complex_3d_persistence.cpp
deleted file mode 100644
index a261c5a3..00000000
--- a/src/Alpha_complex/utilities/periodic_alpha_complex_3d_persistence.cpp
+++ /dev/null
@@ -1,302 +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
- * Pawel Dlotko - 2017 - Swansea University, UK
- *
- * Copyright (C) 2014 Inria
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <boost/program_options.hpp>
-#include <boost/variant.hpp>
-
-#include <gudhi/Simplex_tree.h>
-#include <gudhi/Persistent_cohomology.h>
-#include <gudhi/Points_3D_off_io.h>
-
-#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
-#include <CGAL/Periodic_3_Delaunay_triangulation_traits_3.h>
-#include <CGAL/Periodic_3_Delaunay_triangulation_3.h>
-#include <CGAL/Alpha_shape_3.h>
-#include <CGAL/Alpha_shape_cell_base_3.h>
-#include <CGAL/Alpha_shape_vertex_base_3.h>
-#include <CGAL/iterator.h>
-
-#include <fstream>
-#include <cmath>
-#include <string>
-#include <tuple>
-#include <map>
-#include <utility>
-#include <vector>
-#include <cstdlib>
-
-#include "alpha_complex_3d_helper.h"
-
-// Traits
-using K = CGAL::Exact_predicates_inexact_constructions_kernel;
-using PK = CGAL::Periodic_3_Delaunay_triangulation_traits_3<K>;
-// Vertex type
-using DsVb = CGAL::Periodic_3_triangulation_ds_vertex_base_3<>;
-using Vb = CGAL::Triangulation_vertex_base_3<PK, DsVb>;
-using AsVb = CGAL::Alpha_shape_vertex_base_3<PK, Vb>;
-// Cell type
-using DsCb = CGAL::Periodic_3_triangulation_ds_cell_base_3<>;
-using Cb = CGAL::Triangulation_cell_base_3<PK, DsCb>;
-using AsCb = CGAL::Alpha_shape_cell_base_3<PK, Cb>;
-using Tds = CGAL::Triangulation_data_structure_3<AsVb, AsCb>;
-using P3DT3 = CGAL::Periodic_3_Delaunay_triangulation_3<PK, Tds>;
-using Alpha_shape_3 = CGAL::Alpha_shape_3<P3DT3>;
-using Point_3 = PK::Point_3;
-
-// filtration with alpha values needed type definition
-using Alpha_value_type = Alpha_shape_3::FT;
-using Object = CGAL::Object;
-using Dispatch =
- CGAL::Dispatch_output_iterator<CGAL::cpp11::tuple<Object, Alpha_value_type>,
- CGAL::cpp11::tuple<std::back_insert_iterator<std::vector<Object> >,
- std::back_insert_iterator<std::vector<Alpha_value_type> > > >;
-using Cell_handle = Alpha_shape_3::Cell_handle;
-using Facet = Alpha_shape_3::Facet;
-using Edge_3 = Alpha_shape_3::Edge;
-using Vertex_handle = Alpha_shape_3::Vertex_handle;
-using Vertex_list = std::vector<Alpha_shape_3::Vertex_handle>;
-
-// gudhi type definition
-using ST = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
-using Filtration_value = ST::Filtration_value;
-using Simplex_tree_vertex = ST::Vertex_handle;
-using Alpha_shape_simplex_tree_map = std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex>;
-using Simplex_tree_vector_vertex = std::vector<Simplex_tree_vertex>;
-using Persistent_cohomology =
- Gudhi::persistent_cohomology::Persistent_cohomology<ST, Gudhi::persistent_cohomology::Field_Zp>;
-
-void program_options(int argc, char *argv[], std::string &off_file_points, std::string &cuboid_file,
- std::string &output_file_diag, int &coeff_field_characteristic, Filtration_value &min_persistence);
-
-int main(int argc, char **argv) {
- std::string off_file_points;
- std::string cuboid_file;
- std::string output_file_diag;
- int coeff_field_characteristic;
- Filtration_value min_persistence;
-
- program_options(argc, argv, off_file_points, cuboid_file, output_file_diag, coeff_field_characteristic,
- min_persistence);
-
- // Read the OFF file (input file name given as parameter) and triangulate points
- Gudhi::Points_3D_off_reader<Point_3> off_reader(off_file_points);
- // Check the read operation was correct
- if (!off_reader.is_valid()) {
- std::cerr << "Unable to read OFF file " << off_file_points << std::endl;
- exit(-1);
- }
-
- // Read iso_cuboid_3 information from file
- std::ifstream iso_cuboid_str(cuboid_file);
- double x_min, y_min, z_min, x_max, y_max, z_max;
- if (iso_cuboid_str.good()) {
- iso_cuboid_str >> x_min >> y_min >> z_min >> x_max >> y_max >> z_max;
- } else {
- std::cerr << "Unable to read file " << cuboid_file << std::endl;
- exit(-1);
- }
- // Checking if the cuboid is the same in x,y and z direction. If not, CGAL will not process it.
- if ((x_max - x_min != y_max - y_min) || (x_max - x_min != z_max - z_min) || (z_max - z_min != y_max - y_min)) {
- std::cerr << "The size of the cuboid in every directions is not the same." << std::endl;
- exit(-1);
- }
-
- // Retrieve the points
- std::vector<Point_3> lp = off_reader.get_point_cloud();
-
- // Define the periodic cube
- P3DT3 pdt(PK::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max));
- // Heuristic for inserting large point sets (if pts is reasonably large)
- pdt.insert(lp.begin(), lp.end(), true);
- // As pdt won't be modified anymore switch to 1-sheeted cover if possible
- if (pdt.is_triangulation_in_1_sheet()) {
- pdt.convert_to_1_sheeted_covering();
- } else {
- std::cerr << "ERROR: we were not able to construct a triangulation within a single periodic domain." << std::endl;
- exit(-1);
- }
- std::cout << "Periodic Delaunay computed." << std::endl;
-
- // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. This is the default mode
- // Maybe need to set it to GENERAL mode
- Alpha_shape_3 as(pdt, 0, Alpha_shape_3::GENERAL);
-
- // filtration with alpha values from alpha shape
- std::vector<Object> the_objects;
- std::vector<Alpha_value_type> the_alpha_values;
-
- Dispatch disp = CGAL::dispatch_output<Object, Alpha_value_type>(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<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin();
- for (auto object_iterator : the_objects) {
- // Retrieve Alpha shape vertex list from object
- if (const Cell_handle *cell = CGAL::object_cast<Cell_handle>(&object_iterator)) {
- vertex_list = from_cell<Vertex_list, Cell_handle>(*cell);
- count_cells++;
- } else if (const Facet *facet = CGAL::object_cast<Facet>(&object_iterator)) {
- vertex_list = from_facet<Vertex_list, Facet>(*facet);
- count_facets++;
- } else if (const Edge_3 *edge = CGAL::object_cast<Edge_3>(&object_iterator)) {
- vertex_list = from_edge<Vertex_list, Edge_3>(*edge);
- count_edges++;
- } else if (const Vertex_handle *vertex = CGAL::object_cast<Vertex_handle>(&object_iterator)) {
- count_vertices++;
- vertex_list = from_vertex<Vertex_list, Vertex_handle>(*vertex);
- }
- // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex
- Simplex_tree_vector_vertex the_simplex;
- 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.push_back(vertex);
- map_cgal_simplex_tree.emplace(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.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
- simplex_tree.insert_simplex(the_simplex, filtr);
- if (the_alpha_value_iterator != the_alpha_values.end())
- ++the_alpha_value_iterator;
- else
- std::cout << "This shall not happen" << std::endl;
- }
-
-#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() << " ";
-#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 pcoh(simplex_tree, true);
- // initializes the coefficient field for homology
- pcoh.init_coefficients(coeff_field_characteristic);
-
- pcoh.compute_persistent_cohomology(min_persistence);
-
- // Output the diagram in filediag
- if (output_file_diag.empty()) {
- pcoh.output_diagram();
- } else {
- std::cout << "Result in file: " << output_file_diag << std::endl;
- std::ofstream out(output_file_diag);
- pcoh.output_diagram(out);
- out.close();
- }
-
- return 0;
-}
-
-void program_options(int argc, char *argv[], std::string &off_file_points, std::string &cuboid_file,
- std::string &output_file_diag, 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<std::string>(&off_file_points),
- "Name of file containing a point set. Format is one point per line: X1 ... Xd ")(
- "cuboid-file", po::value<std::string>(&cuboid_file),
- "Name of file describing the periodic domain. Format is: min_hx min_hy min_hz\nmax_hx max_hy max_hz");
-
- po::options_description visible("Allowed options", 100);
- visible.add_options()("help,h", "produce help message")(
- "output-file,o", po::value<std::string>(&output_file_diag)->default_value(std::string()),
- "Name of file in which the persistence diagram is written. Default print in std::cout")(
- "field-charac,p", po::value<int>(&coeff_field_characteristic)->default_value(11),
- "Characteristic p of the coefficient field Z/pZ for computing homology.")(
- "min-persistence,m", po::value<Filtration_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);
- pos.add("cuboid-file", 2);
-
- 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") || !vm.count("cuboid-file")) {
- std::cout << std::endl;
- std::cout << "Compute the persistent homology with coefficient field Z/pZ \n";
- std::cout << "of a periodic 3D 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 cuboid-file" << std::endl << std::endl;
- std::cout << visible << std::endl;
- exit(-1);
- }
-}
diff --git a/src/Alpha_complex/utilities/weighted_alpha_complex_3d_persistence.cpp b/src/Alpha_complex/utilities/weighted_alpha_complex_3d_persistence.cpp
deleted file mode 100644
index aa7ddee2..00000000
--- a/src/Alpha_complex/utilities/weighted_alpha_complex_3d_persistence.cpp
+++ /dev/null
@@ -1,316 +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
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#include <boost/program_options.hpp>
-#include <boost/variant.hpp>
-
-#include <gudhi/Simplex_tree.h>
-#include <gudhi/Persistent_cohomology.h>
-#include <gudhi/Points_3D_off_io.h>
-
-#include <CGAL/config.h>
-#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
-#include <CGAL/Regular_triangulation_3.h>
-#include <CGAL/Alpha_shape_3.h>
-#include <CGAL/Alpha_shape_cell_base_3.h>
-#include <CGAL/Alpha_shape_vertex_base_3.h>
-#include <CGAL/iterator.h>
-
-// For CGAL < 4.11
-#if CGAL_VERSION_NR < 1041100000
-#include <CGAL/Regular_triangulation_euclidean_traits_3.h>
-#endif // CGAL_VERSION_NR < 1041100000
-
-#include <fstream>
-#include <cmath>
-#include <string>
-#include <tuple>
-#include <map>
-#include <utility>
-#include <vector>
-#include <cstdlib>
-
-#include "alpha_complex_3d_helper.h"
-
-// Alpha_shape_3 templates type definitions
-using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
-
-// For CGAL < 4.11
-#if CGAL_VERSION_NR < 1041100000
-using Gt = CGAL::Regular_triangulation_euclidean_traits_3<Kernel>;
-using Vb = CGAL::Alpha_shape_vertex_base_3<Gt>;
-using Fb = CGAL::Alpha_shape_cell_base_3<Gt>;
-using Tds = CGAL::Triangulation_data_structure_3<Vb, Fb>;
-using Triangulation_3 = CGAL::Regular_triangulation_3<Gt, Tds>;
-
-// From file type definition
-using Point_3 = Gt::Bare_point;
-using Weighted_point_3 = Gt::Weighted_point;
-
-// For CGAL >= 4.11
-#else // CGAL_VERSION_NR < 1041100000
-using Rvb = CGAL::Regular_triangulation_vertex_base_3<Kernel>;
-using Vb = CGAL::Alpha_shape_vertex_base_3<Kernel, Rvb>;
-using Rcb = CGAL::Regular_triangulation_cell_base_3<Kernel>;
-using Cb = CGAL::Alpha_shape_cell_base_3<Kernel, Rcb>;
-using Tds = CGAL::Triangulation_data_structure_3<Vb, Cb>;
-using Triangulation_3 = CGAL::Regular_triangulation_3<Kernel, Tds>;
-
-// From file type definition
-using Point_3 = Triangulation_3::Bare_point;
-using Weighted_point_3 = Triangulation_3::Weighted_point;
-#endif // CGAL_VERSION_NR < 1041100000
-
-using Alpha_shape_3 = CGAL::Alpha_shape_3<Triangulation_3>;
-
-// filtration with alpha values needed type definition
-using Alpha_value_type = Alpha_shape_3::FT;
-using Object = CGAL::Object;
-using Dispatch =
- CGAL::Dispatch_output_iterator<CGAL::cpp11::tuple<Object, Alpha_value_type>,
- CGAL::cpp11::tuple<std::back_insert_iterator<std::vector<Object> >,
- std::back_insert_iterator<std::vector<Alpha_value_type> > > >;
-using Cell_handle = Alpha_shape_3::Cell_handle;
-using Facet = Alpha_shape_3::Facet;
-using Edge_3 = Alpha_shape_3::Edge;
-using Vertex_handle = Alpha_shape_3::Vertex_handle;
-using Vertex_list = std::vector<Alpha_shape_3::Vertex_handle>;
-
-// gudhi type definition
-using ST = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
-using Filtration_value = ST::Filtration_value;
-using Simplex_tree_vertex = ST::Vertex_handle;
-using Alpha_shape_simplex_tree_map = std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex>;
-using Simplex_tree_vector_vertex = std::vector<Simplex_tree_vertex>;
-using Persistent_cohomology =
- Gudhi::persistent_cohomology::Persistent_cohomology<ST, Gudhi::persistent_cohomology::Field_Zp>;
-
-void program_options(int argc, char *argv[], std::string &off_file_points, std::string &weight_file,
- std::string &output_file_diag, int &coeff_field_characteristic, Filtration_value &min_persistence);
-
-int main(int argc, char **argv) {
- std::string off_file_points;
- std::string weight_file;
- std::string output_file_diag;
- int coeff_field_characteristic;
- Filtration_value min_persistence;
-
- program_options(argc, argv, off_file_points, weight_file, output_file_diag, coeff_field_characteristic,
- min_persistence);
-
- // Read the OFF file (input file name given as parameter) and triangulate points
- Gudhi::Points_3D_off_reader<Point_3> off_reader(off_file_points);
- // Check the read operation was correct
- if (!off_reader.is_valid()) {
- std::cerr << "Unable to read OFF file " << off_file_points << std::endl;
- exit(-1);
- }
-
- // Retrieve the points
- std::vector<Point_3> lp = off_reader.get_point_cloud();
-
- // Read weights information from file
- std::ifstream weights_ifstr(weight_file);
- std::vector<Weighted_point_3> wp;
- if (weights_ifstr.good()) {
- double weight = 0.0;
- std::size_t index = 0;
- wp.reserve(lp.size());
- // Attempt read the weight in a double format, return false if it fails
- while ((weights_ifstr >> weight) && (index < lp.size())) {
- wp.push_back(Weighted_point_3(lp[index], weight));
- index++;
- }
- if (index != lp.size()) {
- std::cerr << "Bad number of weights in file " << weight_file << std::endl;
- exit(-1);
- }
- } else {
- std::cerr << "Unable to read weights file " << weight_file << std::endl;
- exit(-1);
- }
-
- // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode.
- Alpha_shape_3 as(wp.begin(), wp.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<Object> the_objects;
- std::vector<Alpha_value_type> the_alpha_values;
-
- Dispatch disp = CGAL::dispatch_output<Object, Alpha_value_type>(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<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin();
- for (auto object_iterator : the_objects) {
- // Retrieve Alpha shape vertex list from object
- if (const Cell_handle *cell = CGAL::object_cast<Cell_handle>(&object_iterator)) {
- vertex_list = from_cell<Vertex_list, Cell_handle>(*cell);
- count_cells++;
- } else if (const Facet *facet = CGAL::object_cast<Facet>(&object_iterator)) {
- vertex_list = from_facet<Vertex_list, Facet>(*facet);
- count_facets++;
- } else if (const Edge_3 *edge = CGAL::object_cast<Edge_3>(&object_iterator)) {
- vertex_list = from_edge<Vertex_list, Edge_3>(*edge);
- count_edges++;
- } else if (const Vertex_handle *vertex = CGAL::object_cast<Vertex_handle>(&object_iterator)) {
- count_vertices++;
- vertex_list = from_vertex<Vertex_list, Vertex_handle>(*vertex);
- }
- // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex
- Simplex_tree_vector_vertex the_simplex;
- 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.push_back(vertex);
- map_cgal_simplex_tree.emplace(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.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
- simplex_tree.insert_simplex(the_simplex, filtr);
- if (the_alpha_value_iterator != the_alpha_values.end())
- ++the_alpha_value_iterator;
- else
- std::cout << "This shall not happen" << std::endl;
- }
-
-#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() << " ";
-#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 pcoh(simplex_tree, true);
- // initializes the coefficient field for homology
- pcoh.init_coefficients(coeff_field_characteristic);
-
- pcoh.compute_persistent_cohomology(min_persistence);
-
- // Output the diagram in filediag
- if (output_file_diag.empty()) {
- pcoh.output_diagram();
- } else {
- std::cout << "Result in file: " << output_file_diag << std::endl;
- std::ofstream out(output_file_diag);
- pcoh.output_diagram(out);
- out.close();
- }
-
- return 0;
-}
-
-void program_options(int argc, char *argv[], std::string &off_file_points, std::string &weight_file,
- std::string &output_file_diag, 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<std::string>(&off_file_points),
- "Name of file containing a point set. Format is one point per line: X1 ... Xd ")(
- "weight-file", po::value<std::string>(&weight_file),
- "Name of file containing a point weights. Format is one weigt per line: W1\n...\nWn ");
-
- po::options_description visible("Allowed options", 100);
- visible.add_options()("help,h", "produce help message")(
- "output-file,o", po::value<std::string>(&output_file_diag)->default_value(std::string()),
- "Name of file in which the persistence diagram is written. Default print in std::cout")(
- "field-charac,p", po::value<int>(&coeff_field_characteristic)->default_value(11),
- "Characteristic p of the coefficient field Z/pZ for computing homology.")(
- "min-persistence,m", po::value<Filtration_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);
- pos.add("weight-file", 2);
-
- 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") || !vm.count("weight-file")) {
- std::cout << std::endl;
- std::cout << "Compute the persistent homology with coefficient field Z/pZ \n";
- std::cout << "of a weighted 3D 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 weight-file" << std::endl << std::endl;
- std::cout << visible << std::endl;
- exit(-1);
- }
-}
diff --git a/src/Alpha_complex/utilities/weighted_periodic_alpha_complex_3d_persistence.cpp b/src/Alpha_complex/utilities/weighted_periodic_alpha_complex_3d_persistence.cpp
deleted file mode 100644
index d030c88c..00000000
--- a/src/Alpha_complex/utilities/weighted_periodic_alpha_complex_3d_persistence.cpp
+++ /dev/null
@@ -1,288 +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
- * Pawel Dlotko - 2017 - Swansea University, UK
- *
- * Copyright (C) 2014 Inria
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <boost/variant.hpp>
-
-#include <gudhi/Simplex_tree.h>
-#include <gudhi/Persistent_cohomology.h>
-#include <gudhi/Points_3D_off_io.h>
-
-#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
-#include <CGAL/Periodic_3_regular_triangulation_traits_3.h>
-#include <CGAL/Periodic_3_regular_triangulation_3.h>
-#include <CGAL/Alpha_shape_3.h>
-#include <CGAL/Alpha_shape_cell_base_3.h>
-#include <CGAL/Alpha_shape_vertex_base_3.h>
-#include <CGAL/iterator.h>
-
-#include <fstream>
-#include <cmath>
-#include <string>
-#include <tuple>
-#include <map>
-#include <utility>
-#include <vector>
-#include <cstdlib>
-
-#include "alpha_complex_3d_helper.h"
-
-// Traits
-using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
-using PK = CGAL::Periodic_3_regular_triangulation_traits_3<Kernel>;
-
-// Vertex type
-using DsVb = CGAL::Periodic_3_triangulation_ds_vertex_base_3<>;
-using Vb = CGAL::Regular_triangulation_vertex_base_3<PK, DsVb>;
-using AsVb = CGAL::Alpha_shape_vertex_base_3<PK, Vb>;
-// Cell type
-using DsCb = CGAL::Periodic_3_triangulation_ds_cell_base_3<>;
-using Cb = CGAL::Regular_triangulation_cell_base_3<PK, DsCb>;
-using AsCb = CGAL::Alpha_shape_cell_base_3<PK, Cb>;
-using Tds = CGAL::Triangulation_data_structure_3<AsVb, AsCb>;
-using P3RT3 = CGAL::Periodic_3_regular_triangulation_3<PK, Tds>;
-using Alpha_shape_3 = CGAL::Alpha_shape_3<P3RT3>;
-
-using Point_3 = P3RT3::Bare_point;
-using Weighted_point_3 = P3RT3::Weighted_point;
-
-// filtration with alpha values needed type definition
-using Alpha_value_type = Alpha_shape_3::FT;
-using Object = CGAL::Object;
-using Dispatch =
- CGAL::Dispatch_output_iterator<CGAL::cpp11::tuple<Object, Alpha_value_type>,
- CGAL::cpp11::tuple<std::back_insert_iterator<std::vector<Object> >,
- std::back_insert_iterator<std::vector<Alpha_value_type> > > >;
-using Cell_handle = Alpha_shape_3::Cell_handle;
-using Facet = Alpha_shape_3::Facet;
-using Edge_3 = Alpha_shape_3::Edge;
-using Vertex_handle = Alpha_shape_3::Vertex_handle;
-using Vertex_list = std::vector<Alpha_shape_3::Vertex_handle>;
-
-// gudhi type definition
-using ST = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
-using Filtration_value = ST::Filtration_value;
-using Simplex_tree_vertex = ST::Vertex_handle;
-using Alpha_shape_simplex_tree_map = std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex>;
-using Simplex_tree_vector_vertex = std::vector<Simplex_tree_vertex>;
-using Persistent_cohomology =
- Gudhi::persistent_cohomology::Persistent_cohomology<ST, Gudhi::persistent_cohomology::Field_Zp>;
-
-void usage(const std::string& progName) {
- std::cerr << "Usage: " << progName << " path_to_the_OFF_file path_to_weight_file path_to_the_cuboid_file "
- "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 != 6) {
- std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n";
- usage(argv[0]);
- }
-
- int coeff_field_characteristic = atoi(argv[4]);
- Filtration_value min_persistence = strtof(argv[5], nullptr);
-
- // Read points from file
- std::string offInputFile(argv[1]);
- // Read the OFF file (input file name given as parameter) and triangulate points
- Gudhi::Points_3D_off_reader<Point_3> off_reader(offInputFile);
- // Check the read operation was correct
- if (!off_reader.is_valid()) {
- std::cerr << "Unable to read file " << offInputFile << std::endl;
- usage(argv[0]);
- }
-
- // Retrieve the points
- std::vector<Point_3> lp = off_reader.get_point_cloud();
-
- // Read iso_cuboid_3 information from file
- std::ifstream iso_cuboid_str(argv[3]);
- double x_min, y_min, z_min, x_max, y_max, z_max;
- if (iso_cuboid_str.is_open()) {
- if (!(iso_cuboid_str >> x_min >> y_min >> z_min >> x_max >> y_max >> z_max)) {
- std::cerr << argv[3] << " - Bad file format." << std::endl;
- usage(argv[0]);
- }
-
- } else {
- std::cerr << "Unable to read file " << argv[3] << std::endl;
- usage(argv[0]);
- }
- // Checking if the cuboid is the same in x,y and z direction. If not, CGAL will not process it.
- if ((x_max - x_min != y_max - y_min) || (x_max - x_min != z_max - z_min) || (z_max - z_min != y_max - y_min)) {
- std::cerr << "The size of the cuboid in every directions is not the same." << std::endl;
- exit(-1);
- }
-
- double maximal_possible_weight = 0.015625 * (x_max - x_min) * (x_max - x_min);
-
- // Read weights information from file
- std::ifstream weights_ifstr(argv[2]);
- std::vector<Weighted_point_3> wp;
- if (weights_ifstr.is_open()) {
- double weight = 0.0;
- std::size_t index = 0;
- wp.reserve(lp.size());
- // Attempt read the weight in a double format, return false if it fails
- while ((weights_ifstr >> weight) && (index < lp.size())) {
- if ((weight >= maximal_possible_weight) || (weight < 0)) {
- std::cerr << "At line " << (index + 1) << ", the weight (" << weight
- << ") is negative or more than or equal to maximal possible weight (" << maximal_possible_weight
- << ") = 1/64*cuboid length squared, which is not an acceptable input." << std::endl;
- exit(-1);
- }
-
- wp.push_back(Weighted_point_3(lp[index], weight));
- index++;
- }
- if (index != lp.size()) {
- std::cerr << "Bad number of weights in file " << argv[2] << std::endl;
- usage(argv[0]);
- }
- } else {
- std::cerr << "Unable to read file " << argv[2] << std::endl;
- usage(argv[0]);
- }
-
- // Define the periodic cube
- P3RT3 prt(PK::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max));
- // Heuristic for inserting large point sets (if pts is reasonably large)
- prt.insert(wp.begin(), wp.end(), true);
- // As prt won't be modified anymore switch to 1-sheeted cover if possible
- if (prt.is_triangulation_in_1_sheet()) {
- prt.convert_to_1_sheeted_covering();
- } else {
- std::cerr << "ERROR: we were not able to construct a triangulation within a single periodic domain." << std::endl;
- exit(-1);
- }
- std::cout << "Weighted Periodic Delaunay computed." << std::endl;
-
- // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. This is the default mode
- // Maybe need to set it to GENERAL mode
- Alpha_shape_3 as(prt, 0, Alpha_shape_3::GENERAL);
-
- // filtration with alpha values from alpha shape
- std::vector<Object> the_objects;
- std::vector<Alpha_value_type> the_alpha_values;
-
- Dispatch disp = CGAL::dispatch_output<Object, Alpha_value_type>(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<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin();
- for (auto object_iterator : the_objects) {
- // Retrieve Alpha shape vertex list from object
- if (const Cell_handle* cell = CGAL::object_cast<Cell_handle>(&object_iterator)) {
- vertex_list = from_cell<Vertex_list, Cell_handle>(*cell);
- count_cells++;
- } else if (const Facet* facet = CGAL::object_cast<Facet>(&object_iterator)) {
- vertex_list = from_facet<Vertex_list, Facet>(*facet);
- count_facets++;
- } else if (const Edge_3* edge = CGAL::object_cast<Edge_3>(&object_iterator)) {
- vertex_list = from_edge<Vertex_list, Edge_3>(*edge);
- count_edges++;
- } else if (const Vertex_handle* vertex = CGAL::object_cast<Vertex_handle>(&object_iterator)) {
- count_vertices++;
- vertex_list = from_vertex<Vertex_list, Vertex_handle>(*vertex);
- }
- // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex
- Simplex_tree_vector_vertex the_simplex;
- 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.push_back(vertex);
- map_cgal_simplex_tree.emplace(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.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
- simplex_tree.insert_simplex(the_simplex, filtr);
- if (the_alpha_value_iterator != the_alpha_values.end())
- ++the_alpha_value_iterator;
- else
- std::cout << "This shall not happen" << std::endl;
- }
-
-#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() << " ";
-#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 pcoh(simplex_tree, true);
- // 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/Bottleneck_distance/utilities/bottleneckdistance.md b/src/Bottleneck_distance/utilities/bottleneckdistance.md
index 939eb911..a81426cf 100644
--- a/src/Bottleneck_distance/utilities/bottleneckdistance.md
+++ b/src/Bottleneck_distance/utilities/bottleneckdistance.md
@@ -22,5 +22,5 @@ This program computes the Bottleneck distance between two persistence diagram fi
where
-* `<file_1.pers>` and `<file_2.pers>` must be in the format described [here](/doc/latest/fileformats.html#FileFormatsPers).
+* `<file_1.pers>` and `<file_2.pers>` must be in the format described [here]({{ site.officialurl }}/doc/latest/fileformats.html#FileFormatsPers).
* `<tolerance>` is an error bound on the bottleneck distance (set by default to the smallest positive double value).
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6c446104..b40d506a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -6,6 +6,9 @@ include(CMakeGUDHIVersion.txt)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/")
+set(GUDHI_MODULES "" CACHE INTERNAL "GUDHI_MODULES")
+set(GUDHI_MISSING_MODULES "" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+
# This variable is used by Cython CMakeLists.txt and by GUDHI_third_party_libraries to know its path
set(GUDHI_CYTHON_PATH "cython")
@@ -35,8 +38,6 @@ add_gudhi_module(Tangential_complex)
add_gudhi_module(Witness_complex)
add_gudhi_module(Nerve_GIC)
-message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"")
-
# For "make doxygen" - Requires GUDHI_USER_VERSION_DIR to be set
set(GUDHI_USER_VERSION_DIR ${CMAKE_SOURCE_DIR})
include(GUDHI_doxygen_target)
@@ -60,7 +61,14 @@ add_subdirectory(GudhUI)
if (WITH_GUDHI_PYTHON)
# specific for cython module
add_subdirectory(${GUDHI_CYTHON_PATH})
+else()
+ message("++ Python module will not be compiled because WITH_GUDHI_PYTHON is set to OFF")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python")
endif()
+
+message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"")
+message("++ GUDHI_MISSING_MODULES list is:\"${GUDHI_MISSING_MODULES}\"")
+
#---------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------
diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt
index b357b8f7..0945e758 100644
--- a/src/GudhUI/CMakeLists.txt
+++ b/src/GudhUI/CMakeLists.txt
@@ -1,40 +1,55 @@
project(GudhUI)
# Need to find OpenGL first as find_package(Qt5) tries to #include"GL/gl.h" on some platforms
-find_package(OpenGL)
+find_package(OpenGL QUIET)
if (OPENGL_FOUND)
- find_package(Qt5 COMPONENTS Widgets Xml OpenGL)
- find_package(QGLViewer)
-
- if ( CGAL_FOUND AND Qt5_FOUND AND QGLVIEWER_FOUND AND NOT CGAL_VERSION VERSION_EQUAL 4.8.0)
-
- set(CMAKE_AUTOMOC ON)
- set(CMAKE_AUTOUIC ON)
- set(CMAKE_INCLUDE_CURRENT_DIR ON)
-
- SET(Boost_USE_STATIC_LIBS ON)
- SET(Boost_USE_MULTITHREAD OFF)
- include_directories (${QGLVIEWER_INCLUDE_DIR})
-
- add_executable ( GudhUI
- gui/gudhui.cpp
- gui/MainWindow.cpp
- gui/Menu_k_nearest_neighbors.cpp
- gui/Menu_uniform_neighbors.cpp
- gui/Menu_edge_contraction.cpp
- gui/Menu_persistence.cpp
- view/Viewer_instructor.cpp
- view/Viewer.cpp
- )
- target_link_libraries( GudhUI Qt5::Widgets Qt5::Xml Qt5::OpenGL )
- target_link_libraries( GudhUI ${QGLVIEWER_LIBRARIES} )
- target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} )
- if (TBB_FOUND)
- target_link_libraries( GudhUI ${TBB_LIBRARIES})
+ find_package(Qt5 COMPONENTS Widgets Xml OpenGL QUIET)
+ if (Qt5_FOUND)
+ find_package(QGLViewer QUIET)
+ if ( QGLVIEWER_FOUND)
+
+ if ( CGAL_FOUND AND NOT CGAL_VERSION VERSION_EQUAL 4.8.0)
+ set(CMAKE_AUTOMOC ON)
+ set(CMAKE_AUTOUIC ON)
+ set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+ SET(Boost_USE_STATIC_LIBS ON)
+ SET(Boost_USE_MULTITHREAD OFF)
+ include_directories (${QGLVIEWER_INCLUDE_DIR})
+
+ add_executable ( GudhUI
+ gui/gudhui.cpp
+ gui/MainWindow.cpp
+ gui/Menu_k_nearest_neighbors.cpp
+ gui/Menu_uniform_neighbors.cpp
+ gui/Menu_edge_contraction.cpp
+ gui/Menu_persistence.cpp
+ view/Viewer_instructor.cpp
+ view/Viewer.cpp
+ )
+ target_link_libraries( GudhUI Qt5::Widgets Qt5::Xml Qt5::OpenGL )
+ target_link_libraries( GudhUI ${QGLVIEWER_LIBRARIES} )
+ target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} )
+ if (TBB_FOUND)
+ target_link_libraries( GudhUI ${TBB_LIBRARIES})
+ endif()
+
+ install(TARGETS GudhUI DESTINATION bin)
+ set(GUDHI_MODULES ${GUDHI_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MODULES")
+ else()
+ message("++ GudhUI will not be compiled because CGAL < 4.8.0 or not found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+ endif()
+ else()
+ message("++ GudhUI will not be compiled because QGLViewer is not found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MISSING_MODULES")
endif()
-
- install(TARGETS GudhUI DESTINATION bin)
-
+ else()
+ message("++ GudhUI will not be compiled because Qt5 COMPONENTS Widgets Xml OpenGL are not found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MISSING_MODULES")
endif()
-endif(OPENGL_FOUND)
+else()
+ message("++ GudhUI will not be compiled because OpenGL is not found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "GudhUI" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+endif()
diff --git a/src/Nerve_GIC/include/gudhi/GIC.h b/src/Nerve_GIC/include/gudhi/GIC.h
index fea0b861..30f89d65 100644
--- a/src/Nerve_GIC/include/gudhi/GIC.h
+++ b/src/Nerve_GIC/include/gudhi/GIC.h
@@ -226,7 +226,25 @@ class Cover_complex {
void set_mask(int nodemask) { mask = nodemask; }
public:
- /** \brief Reads and stores the input point cloud.
+
+
+ /** \brief Reads and stores the input point cloud from vector stored in memory.
+ *
+ * @param[in] cloud input vector representing the point cloud. Each row is a point and each coordinate is a vector.
+ *
+ */
+ template <class InputRange>
+ void set_point_cloud_from_range(InputRange const & cloud) {
+ n = cloud.size(); data_dimension = cloud[0].size(); point_cloud_name = "matrix";
+ for(int i = 0; i < n; i++){
+ point_cloud.emplace_back(cloud[i].begin(), cloud[i].begin() + data_dimension);
+ boost::add_vertex(one_skeleton_OFF);
+ vertices.push_back(boost::add_vertex(one_skeleton));
+ cover.emplace_back();
+ }
+ }
+
+ /** \brief Reads and stores the input point cloud from .(n)OFF file.
*
* @param[in] off_file_name name of the input .OFF or .nOFF file.
*
@@ -371,6 +389,28 @@ class Cover_complex {
distances[index[boost::source(*ei, one_skeleton)]][index[boost::target(*ei, one_skeleton)]]);
}
+ public:
+ /** \brief Reads and stores the distance matrices from vector stored in memory.
+ *
+ * @param[in] distance_matrix input vector representing the distance matrix.
+ *
+ */
+ template <class InputRange>
+ void set_distances_from_range(InputRange const & distance_matrix) {
+ if(point_cloud.size() == 0){
+ n = distance_matrix.size();
+ point_cloud_name = "matrix";
+ data_dimension = 0;
+ for(int i = 0; i < n; i++){
+ point_cloud.emplace_back();
+ boost::add_vertex(one_skeleton_OFF);
+ vertices.push_back(boost::add_vertex(one_skeleton));
+ cover.emplace_back();
+ }
+ }
+ distances = distance_matrix;
+ }
+
public: // Pairwise distances.
/** \private \brief Computes all pairwise distances.
*/
@@ -500,9 +540,17 @@ class Cover_complex {
*
*/
void set_function_from_coordinate(int k) {
- for (int i = 0; i < n; i++) func.push_back(point_cloud[i][k]);
- functional_cover = true;
- cover_name = "coordinate " + std::to_string(k);
+ if(point_cloud[0].size() > 0){
+ for (int i = 0; i < n; i++) func.push_back(point_cloud[i][k]);
+ functional_cover = true;
+ cover_name = "coordinate " + std::to_string(k);
+ }
+ else{
+ std::cout << "Only pairwise distances provided---cannot access " << k << "th coordinate; returning null vector instead" << std::endl;
+ for (int i = 0; i < n; i++) func.push_back(0.0);
+ functional_cover = true;
+ cover_name = "null";
+ }
}
public: // Set function from vector.
@@ -953,9 +1001,17 @@ class Cover_complex {
*
*/
void set_color_from_coordinate(int k = 0) {
- for (int i = 0; i < n; i++) func_color.push_back(point_cloud[i][k]);
- color_name = "coordinate ";
- color_name.append(std::to_string(k));
+ if(point_cloud[0].size() > 0){
+ for (int i = 0; i < n; i++) func_color.push_back(point_cloud[i][k]);
+ color_name = "coordinate ";
+ color_name.append(std::to_string(k));
+ }
+ else{
+ std::cout << "Only pairwise distances provided---cannot access " << k << "th coordinate; returning null vector instead" << std::endl;
+ for (int i = 0; i < n; i++) func.push_back(0.0);
+ functional_cover = true;
+ cover_name = "null";
+ }
}
public: // Set color from vector.
@@ -964,7 +1020,7 @@ class Cover_complex {
* @param[in] color input vector of values.
*
*/
- void set_color_from_vector(std::vector<double> color) {
+ void set_color_from_range(std::vector<double> color) {
for (unsigned int i = 0; i < color.size(); i++) func_color.push_back(color[i]);
}
@@ -1108,7 +1164,7 @@ class Cover_complex {
/** \brief Computes the extended persistence diagram of the complex.
*
*/
- void compute_PD() {
+ Persistence_diagram compute_PD() {
Simplex_tree st;
// Compute max and min
@@ -1121,15 +1177,18 @@ class Cover_complex {
// Build filtration
for (auto const& simplex : simplices) {
- std::vector<int> splx = simplex; splx.push_back(-2);
+ std::vector<int> splx = simplex;
+ splx.push_back(-2);
st.insert_simplex_and_subfaces(splx, -3);
}
for (std::map<int, double>::iterator it = cover_std.begin(); it != cover_std.end(); it++) {
int vertex = it->first; float val = it->second;
int vert[] = {vertex}; int edge[] = {vertex, -2};
- st.assign_filtration(st.find(vert), -2 + (val - minf)/(maxf - minf));
- st.assign_filtration(st.find(edge), 2 - (val - minf)/(maxf - minf));
+ if(st.find(vert) != st.null_simplex()){
+ st.assign_filtration(st.find(vert), -2 + (val - minf)/(maxf - minf));
+ st.assign_filtration(st.find(edge), 2 - (val - minf)/(maxf - minf));
+ }
}
st.make_filtration_non_decreasing();
@@ -1159,6 +1218,7 @@ class Cover_complex {
if (verbose) std::cout << " [" << birth << ", " << death << "]" << std::endl;
}
}
+ return PD;
}
public:
@@ -1184,7 +1244,7 @@ class Cover_complex {
Cboot.point_cloud.push_back(this->point_cloud[id]); Cboot.cover.emplace_back(); Cboot.func.push_back(this->func[id]);
boost::add_vertex(Cboot.one_skeleton_OFF); Cboot.vertices.push_back(boost::add_vertex(Cboot.one_skeleton));
}
- Cboot.set_color_from_vector(Cboot.func);
+ Cboot.set_color_from_range(Cboot.func);
for (int j = 0; j < n; j++) {
std::vector<double> dist(n);
@@ -1230,7 +1290,7 @@ class Cover_complex {
unsigned int N = distribution.size();
double level = 1;
for (unsigned int i = 0; i < N; i++)
- if (distribution[i] > d){ level = i * 1.0 / N; break; }
+ if (distribution[i] >= d){ level = i * 1.0 / N; break; }
if (verbose) std::cout << "Confidence level of distance " << d << " is " << level << std::endl;
return level;
}
diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h
index 712d3b6e..a2537036 100644
--- a/src/Rips_complex/doc/Intro_rips_complex.h
+++ b/src/Rips_complex/doc/Intro_rips_complex.h
@@ -39,7 +39,7 @@ namespace rips_complex {
* <a target="_blank" href="https://en.wikipedia.org/wiki/Vietoris%E2%80%93Rips_complex">(Wikipedia)</a>
* is an abstract simplicial complex
* defined on a finite metric space, where each simplex corresponds to a subset
- * of point whose diameter is smaller that some given threshold.
+ * of points whose diameter is smaller that some given threshold.
* Varying the threshold, we can also see the Rips complex as a filtration of
* the \f$(n-1)-\f$dimensional simplex, where the filtration value of each
* simplex is the diameter of the corresponding subset of points.
@@ -53,7 +53,10 @@ namespace rips_complex {
* The number of simplices in the full Rips complex is exponential in the
* number of vertices, it is thus usually restricted, by excluding all the
* simplices with filtration value larger than some threshold, and keeping only
- * the dim_max-skeleton.
+ * the dim_max-skeleton. It may also be a good idea to start by making the
+ * point set sparser, for instance with
+ * `Gudhi::subsampling::sparsify_point_set()`, since small clusters of points
+ * have a disproportionate cost without affecting the persistence diagram much.
*
* In order to build this complex, the algorithm first builds the graph.
* The filtration value of each edge is computed from a user-given distance
diff --git a/src/Rips_complex/utilities/ripscomplex.md b/src/Rips_complex/utilities/ripscomplex.md
index 6df49310..108cdd50 100644
--- a/src/Rips_complex/utilities/ripscomplex.md
+++ b/src/Rips_complex/utilities/ripscomplex.md
@@ -85,7 +85,7 @@ properly, this is a known issue.
## sparse_rips_persistence ##
This program computes the persistent homology with coefficient field *Z/pZ*
-of a sparse (1+epsilon)-approximation of the Rips complex defined on a set of input Euclidean points. The output diagram contains one bar per line, written with the convention:
+of a sparse (1+epsilon)/(1-epsilon)-approximation of the Rips complex defined on a set of input Euclidean points. The output diagram contains one bar per line, written with the convention:
`p dim birth death`
@@ -99,7 +99,7 @@ where `dim` is the dimension of the homological feature, `birth` and `death` are
* `-h [ --help ]` Produce help message
* `-o [ --output-file ]` Name of file in which the persistence diagram is written. Default print in standard output.
-* `-e [ --approximation ]` (default = .5) Epsilon, where the sparse Rips complex is a (1+epsilon)-approximation of the Rips complex.
+* `-e [ --approximation ]` (default = .5) Epsilon, where the sparse Rips complex is a (1+epsilon)/(1-epsilon)-approximation of the Rips complex.
* `-d [ --cpx-dimension ]` (default = 1) Maximal dimension of the Rips complex we want to compute.
* `-p [ --field-charac ]` (default = 11) Characteristic p of the coefficient field Z/pZ for computing homology.
* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals.
diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h
index 3ab23c12..78697ea2 100644
--- a/src/Simplex_tree/include/gudhi/Simplex_tree.h
+++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h
@@ -296,12 +296,79 @@ class Simplex_tree {
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_),
- root_(nullptr, null_vertex_ , simplex_source.root_.members_),
- filtration_vect_(),
- dimension_(simplex_source.dimension_) {
- auto root_source = simplex_source.root_;
+ Simplex_tree(const Simplex_tree& complex_source) {
+#ifdef DEBUG_TRACES
+ std::cout << "Simplex_tree copy constructor" << std::endl;
+#endif // DEBUG_TRACES
+ copy_from(complex_source);
+ }
+
+ /** \brief User-defined move constructor relocates the whole tree structure.
+ * \exception std::invalid_argument In debug mode, if the complex_source is invalid.
+ */
+ Simplex_tree(Simplex_tree && complex_source) {
+#ifdef DEBUG_TRACES
+ std::cout << "Simplex_tree move constructor" << std::endl;
+#endif // DEBUG_TRACES
+ move_from(complex_source);
+
+ // just need to set dimension_ on source to make it available again
+ // (filtration_vect_ and members are already set from the move)
+ complex_source.dimension_ = -1;
+ }
+
+ /** \brief Destructor; deallocates the whole tree structure. */
+ ~Simplex_tree() {
+ root_members_recursive_deletion();
+ }
+
+ /** \brief User-defined copy assignment reproduces the whole tree structure. */
+ Simplex_tree& operator= (const Simplex_tree& complex_source) {
+#ifdef DEBUG_TRACES
+ std::cout << "Simplex_tree copy assignment" << std::endl;
+#endif // DEBUG_TRACES
+ // Self-assignment detection
+ if (&complex_source != this) {
+ // We start by deleting root_ if not empty
+ root_members_recursive_deletion();
+
+ copy_from(complex_source);
+ }
+ return *this;
+ }
+
+ /** \brief User-defined move assignment relocates the whole tree structure.
+ * \exception std::invalid_argument In debug mode, if the complex_source is invalid.
+ */
+ Simplex_tree& operator=(Simplex_tree&& complex_source) {
+#ifdef DEBUG_TRACES
+ std::cout << "Simplex_tree move assignment" << std::endl;
+#endif // DEBUG_TRACES
+ // Self-assignment detection
+ if (&complex_source != this) {
+ // root_ deletion in case it was not empty
+ root_members_recursive_deletion();
+
+ move_from(complex_source);
+ }
+ return *this;
+ }
+ /** @} */ // end constructor/destructor
+
+ private:
+ // Copy from complex_source to "this"
+ void copy_from(const Simplex_tree& complex_source) {
+ null_vertex_ = complex_source.null_vertex_;
+ filtration_vect_.clear();
+ dimension_ = complex_source.dimension_;
+ auto root_source = complex_source.root_;
+
+ // root members copy
+ root_.members() = Dictionary(boost::container::ordered_unique_range, root_source.members().begin(), root_source.members().end());
+ // Needs to reassign children
+ for (auto& map_el : root_.members()) {
+ map_el.second.assign_children(&root_);
+ }
rec_copy(&root_, &root_source);
}
@@ -320,26 +387,38 @@ class Simplex_tree {
}
}
- /** \brief User-defined move constructor moves the whole tree structure. */
- Simplex_tree(Simplex_tree && old)
- : null_vertex_(std::move(old.null_vertex_)),
- root_(std::move(old.root_)),
- filtration_vect_(std::move(old.filtration_vect_)),
- dimension_(std::move(old.dimension_)) {
- old.dimension_ = -1;
- old.root_ = Siblings(nullptr, null_vertex_);
+ // Move from complex_source to "this"
+ void move_from(Simplex_tree& complex_source) {
+ null_vertex_ = std::move(complex_source.null_vertex_);
+ root_ = std::move(complex_source.root_);
+ filtration_vect_ = std::move(complex_source.filtration_vect_);
+ dimension_ = std::move(complex_source.dimension_);
+
+ // Need to update root members (children->oncles and children need to point on the new root pointer)
+ for (auto& map_el : root_.members()) {
+ if (map_el.second.children() != &(complex_source.root_)) {
+ // reset children->oncles with the moved root_ pointer value
+ map_el.second.children()->oncles_ = &root_;
+ } else {
+ // if simplex is of dimension 0, oncles_ shall be nullptr
+ GUDHI_CHECK(map_el.second.children()->oncles_ == nullptr,
+ std::invalid_argument("Simplex_tree move constructor from an invalid Simplex_tree"));
+ // and children points on root_ - to be moved
+ map_el.second.assign_children(&root_);
+ }
+ }
}
- /** \brief Destructor; deallocates the whole tree structure. */
- ~Simplex_tree() {
+ // delete all root_.members() recursively
+ void root_members_recursive_deletion() {
for (auto sh = root_.members().begin(); sh != root_.members().end(); ++sh) {
if (has_children(sh)) {
rec_delete(sh->second.children());
}
}
+ root_.members().clear();
}
- /** @} */ // end constructor/destructor
- private:
+
// Recursive deletion
void rec_delete(Siblings * sib) {
for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) {
@@ -1035,6 +1114,7 @@ class Simplex_tree {
* The Simplex_tree must contain no simplex of dimension bigger than
* 1 when calling the method. */
void expansion(int max_dim) {
+ if (max_dim <= 1) return;
dimension_ = max_dim;
for (Dictionary_it root_it = root_.members_.begin();
root_it != root_.members_.end(); ++root_it) {
diff --git a/src/Simplex_tree/test/CMakeLists.txt b/src/Simplex_tree/test/CMakeLists.txt
index c63d8532..5bea3938 100644
--- a/src/Simplex_tree/test/CMakeLists.txt
+++ b/src/Simplex_tree/test/CMakeLists.txt
@@ -28,3 +28,11 @@ if (TBB_FOUND)
endif()
gudhi_add_coverage_test(Simplex_tree_iostream_operator_test_unit)
+
+add_executable ( Simplex_tree_ctor_and_move_test_unit simplex_tree_ctor_and_move_unit_test.cpp )
+target_link_libraries(Simplex_tree_ctor_and_move_test_unit ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+if (TBB_FOUND)
+ target_link_libraries(Simplex_tree_ctor_and_move_test_unit ${TBB_LIBRARIES})
+endif()
+
+gudhi_add_coverage_test(Simplex_tree_ctor_and_move_test_unit)
diff --git a/src/Simplex_tree/test/simplex_tree_ctor_and_move_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_ctor_and_move_unit_test.cpp
new file mode 100644
index 00000000..e729cf00
--- /dev/null
+++ b/src/Simplex_tree/test/simplex_tree_ctor_and_move_unit_test.cpp
@@ -0,0 +1,137 @@
+#include <iostream>
+#include <vector>
+#include <string>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "simplex_tree_constructor_and_move"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+// ^
+// /!\ Nothing else from Simplex_tree shall be included to test includes are well defined.
+#include "gudhi/Simplex_tree.h"
+
+using namespace Gudhi;
+
+typedef boost::mpl::list<Simplex_tree<>, Simplex_tree<Simplex_tree_options_fast_persistence>> list_of_tested_variants;
+
+template<typename Simplex_tree>
+void print_simplex_filtration(Simplex_tree& st, const std::string& msg) {
+ // Required before browsing through filtration values
+ st.initialize_filtration();
+
+ std::cout << "********************************************************************\n";
+ std::cout << "* " << msg << "\n";
+ std::cout << "* The complex contains " << st.num_simplices() << " simplices";
+ std::cout << " - dimension " << st.dimension() << "\n";
+ std::cout << "* Iterator on Simplices in the filtration, with [filtration value]:\n";
+ 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 << "(" << vertex << ")";
+ std::cout << std::endl;
+ }
+
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_copy_constructor, Simplex_tree, list_of_tested_variants) {
+ Simplex_tree st;
+
+ st.insert_simplex_and_subfaces({2, 1, 0}, 3.0);
+ st.insert_simplex_and_subfaces({0, 1, 6, 7}, 4.0);
+ st.insert_simplex_and_subfaces({3, 0}, 2.0);
+ st.insert_simplex_and_subfaces({3, 4, 5}, 3.0);
+ st.insert_simplex_and_subfaces({8}, 1.0);
+ /* Inserted simplex: */
+ /* 1 6 */
+ /* o---o */
+ /* /X\7/ */
+ /* o---o---o---o o */
+ /* 2 0 3\X/4 8 */
+ /* o */
+ /* 5 */
+ /* */
+ /* In other words: */
+ /* A facet [2,1,0] */
+ /* An edge [0,3] */
+ /* A facet [3,4,5] */
+ /* A cell [0,1,6,7] */
+ /* A vertex [8] */
+
+ print_simplex_filtration(st, "Default Simplex_tree is initialized");
+
+ std::cout << "********************************************************************" << std::endl;
+ std::cout << "TEST OF COPY CONSTRUCTOR" << std::endl;
+
+ Simplex_tree st1(st);
+ Simplex_tree st2(st);
+ print_simplex_filtration(st1, "First copy constructor from the default Simplex_tree");
+ print_simplex_filtration(st2, "Second copy constructor from the default Simplex_tree");
+ // Cross check
+ BOOST_CHECK(st1 == st2);
+ BOOST_CHECK(st == st2);
+ BOOST_CHECK(st1 == st);
+
+ std::cout << "********************************************************************" << std::endl;
+ std::cout << "TEST OF COPY ASSIGNMENT" << std::endl;
+ Simplex_tree st3;
+ // To check there is no memory leak
+ st3.insert_simplex_and_subfaces({9, 10, 11}, 200.0);
+ st3 = st;
+ print_simplex_filtration(st3, "First copy assignment from the default Simplex_tree");
+ Simplex_tree st4;
+ st4 = st;
+ print_simplex_filtration(st4, "Second copy assignment from the default Simplex_tree");
+
+ // Cross check
+ BOOST_CHECK(st3 == st4);
+ BOOST_CHECK(st == st4);
+ BOOST_CHECK(st3 == st);
+
+ st = st;
+ print_simplex_filtration(st4, "Third self copy assignment from the default Simplex_tree");
+
+ BOOST_CHECK(st3 == st);
+
+ std::cout << "********************************************************************" << std::endl;
+ std::cout << "TEST OF MOVE CONSTRUCTOR" << std::endl;
+ Simplex_tree st5(std::move(st1));
+ print_simplex_filtration(st5, "First move constructor from the default Simplex_tree");
+ print_simplex_filtration(st1, "First moved Simplex_tree shall be empty");
+ Simplex_tree st6(std::move(st2));
+ print_simplex_filtration(st6, "Second move constructor from the default Simplex_tree");
+ print_simplex_filtration(st2, "Second moved Simplex_tree shall be empty");
+
+ // Cross check
+ BOOST_CHECK(st5 == st6);
+ BOOST_CHECK(st == st6);
+ BOOST_CHECK(st5 == st);
+
+ Simplex_tree empty_st;
+ BOOST_CHECK(st1 == st2);
+ BOOST_CHECK(empty_st == st2);
+ BOOST_CHECK(st1 == empty_st);
+
+ std::cout << "********************************************************************" << std::endl;
+ std::cout << "TEST OF MOVE ASSIGNMENT" << std::endl;
+
+ Simplex_tree st7;
+ // To check there is no memory leak
+ st7.insert_simplex_and_subfaces({9, 10, 11}, 200.0);
+ st7 = std::move(st3);
+ print_simplex_filtration(st7, "First move assignment from the default Simplex_tree");
+ Simplex_tree st8;
+ st8 = std::move(st4);
+ print_simplex_filtration(st8, "Second move assignment from the default Simplex_tree");
+
+ // Cross check
+ BOOST_CHECK(st7 == st8);
+ BOOST_CHECK(st == st8);
+ BOOST_CHECK(st7 == st);
+
+ st = std::move(st);
+ print_simplex_filtration(st, "Third self move assignment from the default Simplex_tree");
+
+ BOOST_CHECK(st7 == st);
+
+}
diff --git a/src/Tangential_complex/include/gudhi/Tangential_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex.h
index d1c846cf..37cdf1b4 100644
--- a/src/Tangential_complex/include/gudhi/Tangential_complex.h
+++ b/src/Tangential_complex/include/gudhi/Tangential_complex.h
@@ -30,6 +30,7 @@
#include <gudhi/console_color.h>
#include <gudhi/Clock.h>
#include <gudhi/Simplex_tree.h>
+#include <gudhi/Debug_utils.h>
#include <CGAL/Default.h>
#include <CGAL/Dimension.h>
@@ -356,7 +357,7 @@ class Tangential_complex {
tbb::parallel_for(tbb::blocked_range<size_t>(0, m_points.size()), Compute_tangent_triangulation(*this));
} else {
#endif // GUDHI_USE_TBB
- // Sequential
+ // Sequential
for (std::size_t i = 0; i < m_points.size(); ++i) compute_tangent_triangulation(i);
#ifdef GUDHI_USE_TBB
}
@@ -629,12 +630,12 @@ class Tangential_complex {
// Don't export infinite cells
if (!export_infinite_simplices && is_infinite(c)) continue;
- if (!export_inconsistent_simplices && !is_simplex_consistent(c)) continue;
-
if (static_cast<int>(c.size()) > max_dim) max_dim = static_cast<int>(c.size());
// Add the missing center vertex
c.insert(idx);
+ if (!export_inconsistent_simplices && !is_simplex_consistent(c)) continue;
+
// Try to insert the simplex
bool inserted = tree.insert_simplex_and_subfaces(c).second;
@@ -689,6 +690,10 @@ class Tangential_complex {
// Don't export infinite cells
if (!export_infinite_simplices && is_infinite(c)) continue;
+ if (static_cast<int>(c.size()) > max_dim) max_dim = static_cast<int>(c.size());
+ // Add the missing center vertex
+ c.insert(idx);
+
if (!export_inconsistent_simplices && !is_simplex_consistent(c)) continue;
// Unusual simplex dim?
@@ -701,10 +706,6 @@ class Tangential_complex {
check_lower_and_higher_dim_simplices = 1;
}
- if (static_cast<int>(c.size()) > max_dim) max_dim = static_cast<int>(c.size());
- // Add the missing center vertex
- c.insert(idx);
-
// Try to insert the simplex
bool added = complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1);
@@ -800,7 +801,7 @@ class Tangential_complex {
tbb::parallel_for(tbb::blocked_range<size_t>(0, m_points.size()), Compute_tangent_triangulation(*this));
} else {
#endif // GUDHI_USE_TBB
- // Sequential
+ // Sequential
for (std::size_t i = 0; i < m_points.size(); ++i) compute_tangent_triangulation(i);
#ifdef GUDHI_USE_TBB
}
@@ -835,7 +836,7 @@ class Tangential_complex {
Refresh_tangent_triangulation(*this, updated_pts_ds));
} else {
#endif // GUDHI_USE_TBB
- // Sequential
+ // Sequential
for (std::size_t i = 0; i < m_points.size(); ++i) refresh_tangent_triangulation(i, updated_pts_ds);
#ifdef GUDHI_USE_TBB
}
@@ -983,10 +984,9 @@ class Tangential_complex {
// of the sphere "star sphere" centered at "center_vertex"
// and which contains all the
// circumspheres of the star of "center_vertex"
- boost::optional<FT> squared_star_sphere_radius_plus_margin = boost::make_optional(false, FT());
- // This is the strange way boost is recommending to get rid of "may be used uninitialized in this function".
- // Former code was :
- // boost::optional<FT> squared_star_sphere_radius_plus_margin;
+ // If th the m_max_squared_edge_length is set the maximal radius of the "star sphere"
+ // is at most square root of m_max_squared_edge_length
+ boost::optional<FT> squared_star_sphere_radius_plus_margin = m_max_squared_edge_length;
// Insert points until we find a point which is outside "star sphere"
for (auto nn_it = ins_range.begin(); nn_it != ins_range.end(); ++nn_it) {
@@ -999,10 +999,16 @@ class Tangential_complex {
Point neighbor_pt;
FT neighbor_weight;
compute_perturbed_weighted_point(neighbor_point_idx, neighbor_pt, neighbor_weight);
-
+ GUDHI_CHECK(!m_max_squared_edge_length ||
+ squared_star_sphere_radius_plus_margin.value() <= m_max_squared_edge_length.value(),
+ std::invalid_argument("Tangential_complex::compute_star - set a bigger value with set_max_squared_edge_length."));
if (squared_star_sphere_radius_plus_margin &&
- k_sqdist(center_pt, neighbor_pt) > *squared_star_sphere_radius_plus_margin)
+ k_sqdist(center_pt, neighbor_pt) > squared_star_sphere_radius_plus_margin.value()) {
+ GUDHI_CHECK(triangulation.current_dimension() >= tangent_space_dim,
+ std::invalid_argument("Tangential_complex::compute_star - Dimension of the star is only " + \
+ std::to_string(triangulation.current_dimension())));
break;
+ }
Tr_point proj_pt = project_point_and_compute_weight(neighbor_pt, neighbor_weight, tsb, local_tr_traits);
@@ -1044,7 +1050,7 @@ class Tangential_complex {
FT sq_power_sphere_diam = 4 * point_weight(c);
if (!squared_star_sphere_radius_plus_margin ||
- sq_power_sphere_diam > *squared_star_sphere_radius_plus_margin) {
+ sq_power_sphere_diam > squared_star_sphere_radius_plus_margin.value()) {
squared_star_sphere_radius_plus_margin = sq_power_sphere_diam;
}
}
@@ -1055,12 +1061,22 @@ class Tangential_complex {
if (squared_star_sphere_radius_plus_margin) {
// "2*m_last_max_perturb" because both points can be perturbed
squared_star_sphere_radius_plus_margin =
- CGAL::square(std::sqrt(*squared_star_sphere_radius_plus_margin) + 2 * m_last_max_perturb);
+ CGAL::square(std::sqrt(squared_star_sphere_radius_plus_margin.value()) + 2 * m_last_max_perturb);
+
+ // Reduce the square radius to m_max_squared_edge_length if necessary
+ if (m_max_squared_edge_length && squared_star_sphere_radius_plus_margin.value() > m_max_squared_edge_length.value()) {
+ squared_star_sphere_radius_plus_margin = m_max_squared_edge_length.value();
+ }
// Save it in `m_squared_star_spheres_radii_incl_margin`
- m_squared_star_spheres_radii_incl_margin[i] = *squared_star_sphere_radius_plus_margin;
+ m_squared_star_spheres_radii_incl_margin[i] = squared_star_sphere_radius_plus_margin.value();
} else {
- m_squared_star_spheres_radii_incl_margin[i] = FT(-1);
+ if (m_max_squared_edge_length) {
+ squared_star_sphere_radius_plus_margin = m_max_squared_edge_length.value();
+ m_squared_star_spheres_radii_incl_margin[i] = m_max_squared_edge_length.value();
+ } else {
+ m_squared_star_spheres_radii_incl_margin[i] = FT(-1);
+ }
}
}
}
@@ -1968,6 +1984,8 @@ class Tangential_complex {
return os;
}
+ void set_max_squared_edge_length(FT max_squared_edge_length) { m_max_squared_edge_length = max_squared_edge_length; }
+
private:
const K m_k;
const int m_intrinsic_dim;
@@ -1993,6 +2011,7 @@ class Tangential_complex {
// and their center vertex
Stars_container m_stars;
std::vector<FT> m_squared_star_spheres_radii_incl_margin;
+ boost::optional<FT> m_max_squared_edge_length;
#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
Points m_points_for_tse;
diff --git a/src/Witness_complex/utilities/witnesscomplex.md b/src/Witness_complex/utilities/witnesscomplex.md
index da453cce..7ea397b9 100644
--- a/src/Witness_complex/utilities/witnesscomplex.md
+++ b/src/Witness_complex/utilities/witnesscomplex.md
@@ -10,7 +10,7 @@ Leave the lines above as it is required by the web site generator 'Jekyll'
{:/comment}
-For more details about the witness complex, please read the [user manual of the package](/doc/latest/group__witness__complex.html).
+For more details about the witness complex, please read the [user manual of the package]({{ site.officialurl }}/doc/latest/group__witness__complex.html).
## weak_witness_persistence ##
This program computes the persistent homology with coefficient field *Z/pZ* of a Weak witness complex defined on a set of input points.
diff --git a/src/cmake/modules/GUDHI_compilation_flags.cmake b/src/cmake/modules/GUDHI_compilation_flags.cmake
index a01d6e13..86cd531b 100644
--- a/src/cmake/modules/GUDHI_compilation_flags.cmake
+++ b/src/cmake/modules/GUDHI_compilation_flags.cmake
@@ -5,7 +5,7 @@ include(CheckCXXSourceCompiles)
# add a compiler flag only if it is accepted
macro(add_cxx_compiler_flag _flag)
- string(REPLACE "-" "_" _flag_var ${_flag})
+ string(REPLACE "-" "_" "/" _flag_var ${_flag})
check_cxx_accepts_flag("${_flag}" CXX_COMPILER_${_flag_var}_OK)
if(CXX_COMPILER_${_flag_var}_OK)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_flag}")
@@ -43,12 +43,15 @@ set (CMAKE_CXX_STANDARD 11)
enable_testing()
if(MSVC)
- # Turn off some VC++ warnings
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4668 /wd4311 /wd4800 /wd4820 /wd4503 /wd4244 /wd4345 /wd4996 /wd4396 /wd4018")
+ add_cxx_compiler_flag("/W3")
+else()
+ add_cxx_compiler_flag("-Wall")
+ # Only for dev version
+ if(PROJECT_NAME STREQUAL "GUDHIdev")
+ add_cxx_compiler_flag("-pedantic")
+ endif()
endif()
-add_cxx_compiler_flag("-Wall")
-
if (DEBUG_TRACES)
# For programs to be more verbose
message(STATUS "DEBUG_TRACES are activated")
diff --git a/src/cmake/modules/GUDHI_doxygen_target.cmake b/src/cmake/modules/GUDHI_doxygen_target.cmake
index 9e10e566..7a84c4e0 100644
--- a/src/cmake/modules/GUDHI_doxygen_target.cmake
+++ b/src/cmake/modules/GUDHI_doxygen_target.cmake
@@ -1,7 +1,7 @@
# add a target to generate API documentation with Doxygen
-find_package(Doxygen)
+find_package(Doxygen QUIET)
if(DOXYGEN_FOUND)
- # configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
+ set(GUDHI_MODULES ${GUDHI_MODULES} "cpp-documentation" CACHE INTERNAL "GUDHI_MODULES")
# starting from cmake 3.9 the usage of DOXYGEN_EXECUTABLE is deprecated
if(TARGET Doxygen::doxygen)
@@ -16,4 +16,6 @@ if(DOXYGEN_FOUND)
# In dev version, doxygen target depends on user_version target. Not existing in user version
add_dependencies(doxygen user_version)
endif()
-endif(DOXYGEN_FOUND)
+else()
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "cpp-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+endif()
diff --git a/src/cmake/modules/GUDHI_modules.cmake b/src/cmake/modules/GUDHI_modules.cmake
index f95d0c34..aab1dd08 100644
--- a/src/cmake/modules/GUDHI_modules.cmake
+++ b/src/cmake/modules/GUDHI_modules.cmake
@@ -1,11 +1,12 @@
# A function to add a new module in GUDHI
-set(GUDHI_MODULES "")
set(GUDHI_MODULES_FULL_LIST "")
function(add_gudhi_module file_path)
option("WITH_MODULE_GUDHI_${file_path}" "Activate/desactivate ${file_path} compilation and installation" ON)
if (WITH_MODULE_GUDHI_${file_path})
- set(GUDHI_MODULES ${GUDHI_MODULES} ${file_path} PARENT_SCOPE)
+ set(GUDHI_MODULES ${GUDHI_MODULES} ${file_path} CACHE INTERNAL "GUDHI_MODULES")
+ else()
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} ${file_path} CACHE INTERNAL "GUDHI_MISSING_MODULES")
endif()
# Required by user_version
set(GUDHI_MODULES_FULL_LIST ${GUDHI_MODULES_FULL_LIST} ${file_path} PARENT_SCOPE)
diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake
index f03c2177..cde3725c 100644
--- a/src/cmake/modules/GUDHI_third_party_libraries.cmake
+++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake
@@ -1,6 +1,6 @@
# This files manage third party libraries required by GUDHI
-find_package(Boost 1.48.0 REQUIRED COMPONENTS system filesystem unit_test_framework program_options thread)
+find_package(Boost 1.56.0 REQUIRED COMPONENTS system filesystem unit_test_framework program_options thread)
if(NOT Boost_FOUND)
message(FATAL_ERROR "NOTICE: This program requires Boost and will not be compiled.")
@@ -21,11 +21,11 @@ endif()
# 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.
-find_package(CGAL)
+find_package(CGAL QUIET)
# Only CGAL versions > 4.4 supports what Gudhi uses from CGAL
if (CGAL_VERSION VERSION_LESS 4.4.0)
- message("CGAL version ${CGAL_VERSION} is considered too old to be used by Gudhi.")
+ message("++ CGAL version ${CGAL_VERSION} is considered too old to be used by Gudhi.")
unset(CGAL_FOUND)
endif()
if(CGAL_FOUND)
@@ -127,6 +127,10 @@ function( find_python_module PYTHON_MODULE_NAME )
RESULT_VARIABLE PYTHON_MODULE_RESULT
OUTPUT_VARIABLE PYTHON_MODULE_VERSION
ERROR_VARIABLE PYTHON_MODULE_ERROR)
+ message ("PYTHON_MODULE_NAME = ${PYTHON_MODULE_NAME}
+ - PYTHON_MODULE_RESULT = ${PYTHON_MODULE_RESULT}
+ - PYTHON_MODULE_VERSION = ${PYTHON_MODULE_VERSION}
+ - PYTHON_MODULE_ERROR = ${PYTHON_MODULE_ERROR}")
if(PYTHON_MODULE_RESULT EQUAL 0)
# Remove carriage return
string(STRIP ${PYTHON_MODULE_VERSION} PYTHON_MODULE_VERSION)
@@ -143,6 +147,7 @@ if( PYTHONINTERP_FOUND )
find_python_module("pytest")
find_python_module("matplotlib")
find_python_module("numpy")
+ find_python_module("scipy")
endif()
if(NOT GUDHI_CYTHON_PATH)
diff --git a/src/common/doc/examples.h b/src/common/doc/examples.h
index 40f202c7..c19b3444 100644
--- a/src/common/doc/examples.h
+++ b/src/common/doc/examples.h
@@ -53,10 +53,7 @@
* @example Spatial_searching/example_spatial_searching.cpp
* @example Alpha_complex/alpha_complex_3d_persistence.cpp
* @example Alpha_complex/alpha_complex_persistence.cpp
- * @example Alpha_complex/weighted_periodic_alpha_complex_3d_persistence.cpp
- * @example Alpha_complex/weighted_alpha_complex_3d_persistence.cpp
- * @example Alpha_complex/periodic_alpha_complex_3d_persistence.cpp
- * @example Alpha_complex/exact_alpha_complex_3d_persistence.cpp
+ * @example Alpha_complex/Weighted_alpha_complex_3d_from_points.cpp
* @example Bottleneck_distance/bottleneck_distance.cpp
* @example Witness_complex/weak_witness_persistence.cpp
* @example Witness_complex/strong_witness_persistence.cpp
diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h
index c27e4f56..8fb8b330 100644
--- a/src/common/doc/installation.h
+++ b/src/common/doc/installation.h
@@ -5,7 +5,7 @@
* Examples of GUDHI headers inclusion can be found in \ref utilities.
*
* \section compiling Compiling
- * The library uses c++11 and requires <a target="_blank" href="http://www.boost.org/">Boost</a> &ge; 1.48.0
+ * The library uses c++11 and requires <a target="_blank" href="http://www.boost.org/">Boost</a> &ge; 1.56.0
* and <a target="_blank" href="https://www.cmake.org/">CMake</a> &ge; 3.1.
* It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015.
*
@@ -18,7 +18,7 @@ cmake ..
make \endverbatim
* By default, examples are disabled. You can activate their compilation with
* <a href="https://cmake.org/cmake/help/v3.0/manual/ccmake.1.html">ccmake</a> (on Linux and Mac OSX),
- * <a href="https://cmake.org/cmake/help/v3.0/manual/cmake-gui.1.html">cmake-gui</a> (on Windows) or y mofifying the
+ * <a href="https://cmake.org/cmake/help/v3.0/manual/cmake-gui.1.html">cmake-gui</a> (on Windows) or by modifying the
* cmake command as follows :
\verbatim cmake -DWITH_GUDHI_EXAMPLE=ON ..
make \endverbatim
@@ -72,12 +72,6 @@ make doxygen
*
* The following examples/utilities require the <a target="_blank" href="http://www.cgal.org/">Computational Geometry Algorithms
* Library</a> (CGAL \cite cgal:eb-15b) and will not be built if CGAL is not installed:
- * \li <a href="_alpha_complex_2alpha_complex_3d_persistence_8cpp-example.html">
- * Alpha_complex/alpha_complex_3d_persistence.cpp</a>
- * \li <a href="_alpha_complex_2exact_alpha_complex_3d_persistence_8cpp-example.html">
- * Alpha_complex/exact_alpha_complex_3d_persistence.cpp</a>
- * \li <a href="_alpha_complex_2weighted_alpha_complex_3d_persistence_8cpp-example.html">
- * Alpha_complex/weighted_alpha_complex_3d_persistence.cpp</a>
* \li <a href="_simplex_tree_2example_alpha_shapes_3_simplex_tree_from_off_file_8cpp-example.html">
* Simplex_tree/example_alpha_shapes_3_simplex_tree_from_off_file.cpp</a>
*
@@ -100,8 +94,6 @@ make doxygen
* Alpha_complex/Alpha_complex_from_points.cpp</a>
* \li <a href="_alpha_complex_2alpha_complex_persistence_8cpp-example.html">
* Alpha_complex/alpha_complex_persistence.cpp</a>
- * \li <a href="_alpha_complex_2periodic_alpha_complex_3d_persistence_8cpp-example.html">
- * Alpha_complex/periodic_alpha_complex_3d_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2custom_persistence_sort_8cpp-example.html">
* Persistent_cohomology/custom_persistence_sort.cpp</a>
*
@@ -135,6 +127,12 @@ make doxygen
* \li <a href="_tangential_complex_2example_with_perturb_8cpp-example.html">
* Tangential_complex/example_with_perturb.cpp</a>
*
+ * The following example requires CGAL version &ge; 4.11.0:
+ * \li <a href="_alpha_complex_2_weighted_alpha_complex_3d_from_points_8cpp-example.html">
+ * Alpha_complex/Weighted_alpha_complex_3d_from_points.cpp</a>
+ * \li <a href="_alpha_complex_2alpha_complex_3d_persistence_8cpp-example.html">
+ * Alpha_complex/alpha_complex_3d_persistence.cpp</a>
+ *
* \subsection eigen3 Eigen3
* The \ref alpha_complex data structure and few examples requires
* <a target="_blank" href="http://eigen.tuxfamily.org/">Eigen3</a> is a C++ template library for linear algebra:
@@ -148,8 +146,10 @@ make doxygen
* Alpha_complex/Alpha_complex_from_points.cpp</a>
* \li <a href="_alpha_complex_2alpha_complex_persistence_8cpp-example.html">
* Alpha_complex/alpha_complex_persistence.cpp</a>
- * \li <a href="_alpha_complex_2periodic_alpha_complex_3d_persistence_8cpp-example.html">
- * Alpha_complex/periodic_alpha_complex_3d_persistence.cpp</a>
+ * \li <a href="_alpha_complex_2alpha_complex_3d_persistence_8cpp-example.html">
+ * Alpha_complex/alpha_complex_3d_persistence.cpp</a>
+ * \li <a href="_alpha_complex_2_weighted_alpha_complex_3d_from_points_8cpp-example.html">
+ * Alpha_complex/Weighted_alpha_complex_3d_from_points.cpp</a>
* \li <a href="_bottleneck_distance_2alpha_rips_persistence_bottleneck_distance_8cpp-example.html">
* Bottleneck_distance/alpha_rips_persistence_bottleneck_distance.cpp.cpp</a>
* \li <a href="_persistent_cohomology_2custom_persistence_sort_8cpp-example.html">
@@ -195,12 +195,6 @@ make doxygen
* Alpha_complex/alpha_complex_3d_persistence.cpp</a>
* \li <a href="_alpha_complex_2alpha_complex_persistence_8cpp-example.html">
* Alpha_complex/alpha_complex_persistence.cpp</a>
- * \li <a href="_alpha_complex_2exact_alpha_complex_3d_persistence_8cpp-example.html">
- * Alpha_complex/exact_alpha_complex_3d_persistence.cpp</a>
- * \li <a href="_alpha_complex_2periodic_alpha_complex_3d_persistence_8cpp-example.html">
- * Alpha_complex/periodic_alpha_complex_3d_persistence.cpp</a>
- * \li <a href="_alpha_complex_2weighted_alpha_complex_3d_persistence_8cpp-example.html">
- * Alpha_complex/weighted_alpha_complex_3d_persistence.cpp</a>
* \li <a href="_bitmap_cubical_complex_2_bitmap_cubical_complex_8cpp-example.html">
* Bitmap_cubical_complex/cubical_complex_persistence.cpp</a>
* \li <a href="_bitmap_cubical_complex_2_bitmap_cubical_complex_periodic_boundary_conditions_8cpp-example.html">
@@ -239,10 +233,6 @@ make doxygen
* Persistent_cohomology/rips_multifield_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2rips_persistence_step_by_step_8cpp-example.html">
* Persistent_cohomology/rips_persistence_step_by_step.cpp</a>
- * \li <a href="_persistent_cohomology_2exact_alpha_complex_3d_persistence_8cpp-example.html">
- * Persistent_cohomology/exact_alpha_complex_3d_persistence.cpp</a>
- * \li <a href="_persistent_cohomology_2weighted_alpha_complex_3d_persistence_8cpp-example.html">
- * Persistent_cohomology/weighted_alpha_complex_3d_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2custom_persistence_sort_8cpp-example.html">
* Persistent_cohomology/custom_persistence_sort.cpp</a>
* \li <a href="_rips_complex_2example_one_skeleton_rips_from_points_8cpp-example.html">
diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h
index db1e80ce..b33a95a1 100644
--- a/src/common/doc/main_page.h
+++ b/src/common/doc/main_page.h
@@ -29,7 +29,9 @@
<b>Author:</b> Vincent Rouvreau<br>
<b>Introduced in:</b> GUDHI 1.3.0<br>
<b>Copyright:</b> GPL v3<br>
- <b>Requires:</b> \ref cgal &ge; 4.7.0 and \ref eigen3
+ <b>Requires:</b> \ref eigen3 and<br>
+ \ref cgal &ge; 4.7.0 for Alpha_complex<br>
+ \ref cgal &ge; 4.11.0 for Alpha_complex_3d
</td>
<td width="75%">
Alpha_complex is a simplicial complex constructed from the finite cells of a Delaunay Triangulation.<br>
@@ -38,7 +40,8 @@
values of the codimension 1 cofaces that make it not Gabriel otherwise.
All simplices that have a filtration value strictly greater than a given alpha squared value are not inserted into
the complex.<br>
- <b>User manual:</b> \ref alpha_complex - <b>Reference manual:</b> Gudhi::alpha_complex::Alpha_complex
+ <b>User manual:</b> \ref alpha_complex - <b>Reference manual:</b> Gudhi::alpha_complex::Alpha_complex and
+ Gudhi::alpha_complex::Alpha_complex_3d
</td>
</tr>
</table>
diff --git a/src/common/include/gudhi/Unitary_tests_utils.h b/src/common/include/gudhi/Unitary_tests_utils.h
index e07c8d42..22f00212 100644
--- a/src/common/include/gudhi/Unitary_tests_utils.h
+++ b/src/common/include/gudhi/Unitary_tests_utils.h
@@ -34,7 +34,7 @@ void GUDHI_TEST_FLOAT_EQUALITY_CHECK(FloatingType a, FloatingType b,
std::cout << "GUDHI_TEST_FLOAT_EQUALITY_CHECK - " << a << " versus " << b
<< " | diff = " << std::fabs(a - b) << " - epsilon = " << epsilon << std::endl;
#endif
- BOOST_CHECK(std::fabs(a - b) < epsilon);
+ BOOST_CHECK(std::fabs(a - b) <= epsilon);
}
#endif // UNITARY_TESTS_UTILS_H_
diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt
index 09ea28f1..dc2e9278 100644
--- a/src/cython/CMakeLists.txt
+++ b/src/cython/CMakeLists.txt
@@ -31,375 +31,414 @@ function( add_gudhi_debug_info DEBUG_INFO )
set(GUDHI_CYTHON_DEBUG_INFO "${GUDHI_CYTHON_DEBUG_INFO} \"${DEBUG_INFO}\\n\" \\\n" PARENT_SCOPE)
endfunction( add_gudhi_debug_info )
-
-if(CYTHON_FOUND)
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}off_reader;")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}simplex_tree;")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}rips_complex;")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}cubical_complex;")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}periodic_cubical_complex;")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}reader_utils;")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}witness_complex;")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}strong_witness_complex;")
-
- add_gudhi_debug_info("Python version ${PYTHON_VERSION_STRING}")
- add_gudhi_debug_info("Cython version ${CYTHON_VERSION}")
- if(PYTEST_FOUND)
- add_gudhi_debug_info("Pytest version ${PYTEST_VERSION}")
- endif()
- if(MATPLOTLIB_FOUND)
- add_gudhi_debug_info("Matplotlib version ${MATPLOTLIB_VERSION}")
- endif()
- if(NUMPY_FOUND)
- add_gudhi_debug_info("Numpy version ${NUMPY_VERSION}")
- endif()
- if(MATPLOTLIB_FOUND AND NUMPY_FOUND)
+if(PYTHONINTERP_FOUND)
+ if(CYTHON_FOUND)
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}off_reader;")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}simplex_tree;")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}rips_complex;")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}cubical_complex;")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}periodic_cubical_complex;")
set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;")
- else()
- set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;")
- endif()
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}reader_utils;")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}witness_complex;")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}strong_witness_complex;")
+
+ add_gudhi_debug_info("Python version ${PYTHON_VERSION_STRING}")
+ add_gudhi_debug_info("Cython version ${CYTHON_VERSION}")
+ if(PYTEST_FOUND)
+ add_gudhi_debug_info("Pytest version ${PYTEST_VERSION}")
+ endif()
+ if(MATPLOTLIB_FOUND)
+ add_gudhi_debug_info("Matplotlib version ${MATPLOTLIB_VERSION}")
+ endif()
+ if(NUMPY_FOUND)
+ add_gudhi_debug_info("Numpy version ${NUMPY_VERSION}")
+ endif()
+ if(SCIPY_FOUND)
+ add_gudhi_debug_info("Scipy version ${SCIPY_VERSION}")
+ endif()
+ if(MATPLOTLIB_FOUND AND NUMPY_FOUND AND SCIPY_FOUND)
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;")
+ else()
+ set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MODULES}persistence_graphical_tools;")
+ endif()
- message("++ ${PYTHON_EXECUTABLE} v.${PYTHON_VERSION_STRING} - Cython is ${CYTHON_VERSION} - Sphinx is ${SPHINX_PATH}")
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ")
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ")
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_SYSTEM_NO_DEPRECATED', ")
-
- # Gudhi and CGAL compilation option
- if(MSVC)
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'/fp:strict', ")
- else(MSVC)
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-std=c++11', ")
- endif(MSVC)
- if(CMAKE_COMPILER_IS_GNUCXX)
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ")
- endif(CMAKE_COMPILER_IS_GNUCXX)
- if (CMAKE_CXX_COMPILER_ID MATCHES Intel)
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ")
- endif(CMAKE_CXX_COMPILER_ID MATCHES Intel)
- if (DEBUG_TRACES)
- # For programs to be more verbose
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ")
- endif()
+ message("++ ${PYTHON_EXECUTABLE} v.${PYTHON_VERSION_STRING} - Cython is ${CYTHON_VERSION} - Sphinx is ${SPHINX_PATH}")
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ")
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ")
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_SYSTEM_NO_DEPRECATED', ")
+
+ # Gudhi and CGAL compilation option
+ if(MSVC)
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'/fp:strict', ")
+ else(MSVC)
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-std=c++11', ")
+ endif(MSVC)
+ if(CMAKE_COMPILER_IS_GNUCXX)
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ")
+ endif(CMAKE_COMPILER_IS_GNUCXX)
+ if (CMAKE_CXX_COMPILER_ID MATCHES Intel)
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ")
+ endif(CMAKE_CXX_COMPILER_ID MATCHES Intel)
+ if (DEBUG_TRACES)
+ # For programs to be more verbose
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ")
+ endif()
- if (EIGEN3_FOUND)
- add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION}")
- # No problem, even if no CGAL found
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ")
- endif (EIGEN3_FOUND)
-
- if (NOT CGAL_VERSION VERSION_LESS 4.8.1)
- set(GUDHI_CYTHON_BOTTLENECK_DISTANCE "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/bottleneck_distance.pyx'")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}bottleneck_distance;")
- set(GUDHI_CYTHON_NERVE_GIC "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/nerve_gic.pyx'")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}nerve_gic;")
- else()
- set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}bottleneck_distance;")
- set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}nerve_gic;")
- endif ()
- if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
- set(GUDHI_CYTHON_SUBSAMPLING "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/subsampling.pyx'")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}subsampling;")
- set(GUDHI_CYTHON_TANGENTIAL_COMPLEX "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/tangential_complex.pyx'")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}tangential_complex;")
- else()
- set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}subsampling;")
- set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}tangential_complex;")
- endif ()
- if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
- set(GUDHI_CYTHON_ALPHA_COMPLEX "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/alpha_complex.pyx'")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}alpha_complex;")
- else()
- set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}alpha_complex;")
- endif ()
- if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0)
- set(GUDHI_CYTHON_EUCLIDEAN_WITNESS_COMPLEX
- "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/euclidean_witness_complex.pyx'\ninclude '${CMAKE_CURRENT_SOURCE_DIR}/cython/euclidean_strong_witness_complex.pyx'\n")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}euclidean_witness_complex;")
- set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}euclidean_strong_witness_complex;")
- else()
- set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}euclidean_witness_complex;")
- set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}euclidean_strong_witness_complex;")
- endif ()
-
- add_gudhi_debug_info("Installed modules are: ${GUDHI_CYTHON_MODULES}")
- if(GUDHI_CYTHON_MISSING_MODULES)
- add_gudhi_debug_info("Missing modules are: ${GUDHI_CYTHON_MISSING_MODULES}")
- endif()
+ if (EIGEN3_FOUND)
+ add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION}")
+ # No problem, even if no CGAL found
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ")
+ endif (EIGEN3_FOUND)
+
+ if (NOT CGAL_VERSION VERSION_LESS 4.8.1)
+ set(GUDHI_CYTHON_BOTTLENECK_DISTANCE "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/bottleneck_distance.pyx'")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}bottleneck_distance;")
+ set(GUDHI_CYTHON_NERVE_GIC "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/nerve_gic.pyx'")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}nerve_gic;")
+ else()
+ set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}bottleneck_distance;")
+ set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}nerve_gic;")
+ endif ()
+ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
+ set(GUDHI_CYTHON_SUBSAMPLING "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/subsampling.pyx'")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}subsampling;")
+ set(GUDHI_CYTHON_TANGENTIAL_COMPLEX "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/tangential_complex.pyx'")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}tangential_complex;")
+ else()
+ set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}subsampling;")
+ set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}tangential_complex;")
+ endif ()
+ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
+ set(GUDHI_CYTHON_ALPHA_COMPLEX "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/alpha_complex.pyx'")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}alpha_complex;")
+ else()
+ set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}alpha_complex;")
+ endif ()
+ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0)
+ set(GUDHI_CYTHON_EUCLIDEAN_WITNESS_COMPLEX
+ "include '${CMAKE_CURRENT_SOURCE_DIR}/cython/euclidean_witness_complex.pyx'\ninclude '${CMAKE_CURRENT_SOURCE_DIR}/cython/euclidean_strong_witness_complex.pyx'\n")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}euclidean_witness_complex;")
+ set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}euclidean_strong_witness_complex;")
+ else()
+ set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}euclidean_witness_complex;")
+ set(GUDHI_CYTHON_MISSING_MODULES "${GUDHI_CYTHON_MISSING_MODULES}euclidean_strong_witness_complex;")
+ endif ()
- if(CGAL_FOUND)
- can_cgal_use_cxx11_thread_local()
- if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT)
- if(CMAKE_BUILD_TYPE MATCHES Debug)
- add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_DEBUG}")
- else()
- add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}")
- endif()
- set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ")
+ add_gudhi_debug_info("Installed modules are: ${GUDHI_CYTHON_MODULES}")
+ if(GUDHI_CYTHON_MISSING_MODULES)
+ add_gudhi_debug_info("Missing modules are: ${GUDHI_CYTHON_MISSING_MODULES}")
endif()
- # Add CGAL compilation args
- if(CGAL_HEADER_ONLY)
- add_gudhi_debug_info("CGAL header only version ${CGAL_VERSION}")
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ")
- else(CGAL_HEADER_ONLY)
- add_gudhi_debug_info("CGAL version ${CGAL_VERSION}")
- add_gudhi_cython_lib("${CGAL_LIBRARY}")
- set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ")
- # If CGAL is not header only, CGAL library may link with boost system,
+
+ if(CGAL_FOUND)
+ can_cgal_use_cxx11_thread_local()
+ if (NOT CGAL_CAN_USE_CXX11_THREAD_LOCAL_RESULT)
+ if(CMAKE_BUILD_TYPE MATCHES Debug)
+ add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_DEBUG}")
+ else()
+ add_gudhi_cython_lib("${Boost_THREAD_LIBRARY_RELEASE}")
+ endif()
+ set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ")
+ endif()
+ # Add CGAL compilation args
+ if(CGAL_HEADER_ONLY)
+ add_gudhi_debug_info("CGAL header only version ${CGAL_VERSION}")
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ")
+ else(CGAL_HEADER_ONLY)
+ add_gudhi_debug_info("CGAL version ${CGAL_VERSION}")
+ add_gudhi_cython_lib("${CGAL_LIBRARY}")
+ set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ")
+ # If CGAL is not header only, CGAL library may link with boost system,
+ if(CMAKE_BUILD_TYPE MATCHES Debug)
+ add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_DEBUG}")
+ else()
+ add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}")
+ endif()
+ set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ")
+ endif(CGAL_HEADER_ONLY)
+ # GMP and GMPXX are not required, but if present, CGAL will link with them.
+ if(GMP_FOUND)
+ add_gudhi_debug_info("GMP_LIBRARIES = ${GMP_LIBRARIES}")
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ")
+ add_gudhi_cython_lib("${GMP_LIBRARIES}")
+ set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMP_LIBRARIES_DIR}', ")
+ if(GMPXX_FOUND)
+ add_gudhi_debug_info("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}")
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ")
+ add_gudhi_cython_lib("${GMPXX_LIBRARIES}")
+ set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMPXX_LIBRARIES_DIR}', ")
+ endif(GMPXX_FOUND)
+ endif(GMP_FOUND)
+ endif(CGAL_FOUND)
+
+ # Specific for Mac
+ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-mmacosx-version-min=10.12', ")
+ set(GUDHI_CYTHON_EXTRA_LINK_ARGS "${GUDHI_CYTHON_EXTRA_LINK_ARGS}'-mmacosx-version-min=10.12', ")
+ endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+
+ # Loop on INCLUDE_DIRECTORIES PROPERTY
+ get_property(GUDHI_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
+ foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES})
+ set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${GUDHI_INCLUDE_DIRECTORY}', ")
+ endforeach()
+ set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${CMAKE_SOURCE_DIR}/${GUDHI_CYTHON_PATH}/include', ")
+
+ if (TBB_FOUND AND WITH_GUDHI_USE_TBB)
+ add_gudhi_debug_info("TBB version ${TBB_INTERFACE_VERSION} found and used")
+ set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_TBB', ")
if(CMAKE_BUILD_TYPE MATCHES Debug)
- add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_DEBUG}")
+ add_gudhi_cython_lib("${TBB_DEBUG_LIBRARY}")
+ add_gudhi_cython_lib("${TBB_MALLOC_DEBUG_LIBRARY}")
else()
- add_gudhi_cython_lib("${Boost_SYSTEM_LIBRARY_RELEASE}")
+ add_gudhi_cython_lib("${TBB_RELEASE_LIBRARY}")
+ add_gudhi_cython_lib("${TBB_MALLOC_RELEASE_LIBRARY}")
endif()
- set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ")
- endif(CGAL_HEADER_ONLY)
- # GMP and GMPXX are not required, but if present, CGAL will link with them.
- if(GMP_FOUND)
- add_gudhi_debug_info("GMP_LIBRARIES = ${GMP_LIBRARIES}")
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ")
- add_gudhi_cython_lib("${GMP_LIBRARIES}")
- set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMP_LIBRARIES_DIR}', ")
- if(GMPXX_FOUND)
- add_gudhi_debug_info("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}")
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ")
- add_gudhi_cython_lib("${GMPXX_LIBRARIES}")
- set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMPXX_LIBRARIES_DIR}', ")
- endif(GMPXX_FOUND)
- endif(GMP_FOUND)
- endif(CGAL_FOUND)
-
- # Specific for Mac
- if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-mmacosx-version-min=10.12', ")
- set(GUDHI_CYTHON_EXTRA_LINK_ARGS "${GUDHI_CYTHON_EXTRA_LINK_ARGS}'-mmacosx-version-min=10.12', ")
- endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-
- # Loop on INCLUDE_DIRECTORIES PROPERTY
- get_property(GUDHI_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
- foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES})
- set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${GUDHI_INCLUDE_DIRECTORY}', ")
- endforeach()
- set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${CMAKE_SOURCE_DIR}/${GUDHI_CYTHON_PATH}/include', ")
-
- if (TBB_FOUND AND WITH_GUDHI_USE_TBB)
- add_gudhi_debug_info("TBB version ${TBB_INTERFACE_VERSION} found and used")
- set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_TBB', ")
- if(CMAKE_BUILD_TYPE MATCHES Debug)
- add_gudhi_cython_lib("${TBB_DEBUG_LIBRARY}")
- add_gudhi_cython_lib("${TBB_MALLOC_DEBUG_LIBRARY}")
- else()
- add_gudhi_cython_lib("${TBB_RELEASE_LIBRARY}")
- add_gudhi_cython_lib("${TBB_MALLOC_RELEASE_LIBRARY}")
+ set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${TBB_LIBRARY_DIRS}', ")
+ set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ")
endif()
- set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${TBB_LIBRARY_DIRS}', ")
- set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ")
- endif()
- if(UNIX)
- set( GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}")
- endif(UNIX)
-
- # Generate setup.py file to cythonize Gudhi - This file must be named setup.py by convention
- configure_file(setup.py.in "${CMAKE_CURRENT_BINARY_DIR}/setup.py" @ONLY)
- # Generate gudhi.pyx - Gudhi cython file
- configure_file(gudhi.pyx.in "${CMAKE_CURRENT_BINARY_DIR}/gudhi.pyx" @ONLY)
-
- add_custom_command(
- OUTPUT gudhi.so
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/setup.py" "build_ext" "--inplace")
-
- add_custom_target(cython ALL DEPENDS gudhi.so
- COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/ to your PYTHONPATH before using examples or tests")
-
- # For installation purpose
- # TODO(VR) : files matching pattern mechanism is copying all cython directory
- install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DESTINATION "${PYTHON_SITE_PACKAGES}/" FILES_MATCHING
- PATTERN "*.so"
- PATTERN "*.dylib"
- PATTERN "*.pyd")
-
- # Test examples
- if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
- # Bottleneck and Alpha
- add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py"
- -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3)
+ if(UNIX)
+ set( GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}")
+ endif(UNIX)
+
+ # Generate setup.py file to cythonize Gudhi - This file must be named setup.py by convention
+ configure_file(setup.py.in "${CMAKE_CURRENT_BINARY_DIR}/setup.py" @ONLY)
+ # Generate gudhi.pyx - Gudhi cython file
+ configure_file(gudhi.pyx.in "${CMAKE_CURRENT_BINARY_DIR}/gudhi.pyx" @ONLY)
+
+ add_custom_command(
+ OUTPUT gudhi.so
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/setup.py" "build_ext" "--inplace")
+
+ add_custom_target(cython ALL DEPENDS gudhi.so
+ COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/ to your PYTHONPATH before using examples or tests")
+
+ # For installation purpose
+ # TODO(VR) : files matching pattern mechanism is copying all cython directory
+ install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DESTINATION "${PYTHON_SITE_PACKAGES}/" FILES_MATCHING
+ PATTERN "*.so"
+ PATTERN "*.dylib"
+ PATTERN "*.pyd")
+
+ # Test examples
+ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
+ # Bottleneck and Alpha
+ add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py"
+ -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3)
+
+ if(MATPLOTLIB_FOUND AND NUMPY_FOUND)
+ # Tangential
+ add_test(NAME tangential_complex_plain_homology_from_off_file_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/tangential_complex_plain_homology_from_off_file_example.py"
+ --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off)
+
+ add_gudhi_py_test(test_tangential_complex)
+
+ # Witness complex AND Subsampling
+ add_test(NAME euclidean_strong_witness_complex_diagram_persistence_from_off_file_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py"
+ --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2)
+
+ add_test(NAME euclidean_witness_complex_diagram_persistence_from_off_file_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py"
+ --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2)
+ endif()
- if(MATPLOTLIB_FOUND AND NUMPY_FOUND)
- # Tangential
- add_test(NAME tangential_complex_plain_homology_from_off_file_example_py_test
+ # Subsampling
+ add_gudhi_py_test(test_subsampling)
+
+ endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
+ if (NOT CGAL_VERSION VERSION_LESS 4.8.1)
+ # Bottleneck
+ add_test(NAME bottleneck_basic_example_py_test
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/tangential_complex_plain_homology_from_off_file_example.py"
- --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off)
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/bottleneck_basic_example.py")
- add_gudhi_py_test(test_tangential_complex)
+ add_gudhi_py_test(test_bottleneck_distance)
- # Witness complex AND Subsampling
- add_test(NAME euclidean_strong_witness_complex_diagram_persistence_from_off_file_example_py_test
+ # Cover complex
+ file(COPY ${CMAKE_SOURCE_DIR}/data/points/human.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+ file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+ file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat_PCA1 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+ add_test(NAME cover_complex_nerve_example_py_test
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py"
- --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2)
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/nerve_of_a_covering.py"
+ -f human.off -c 2 -r 10 -g 0.3)
- add_test(NAME euclidean_witness_complex_diagram_persistence_from_off_file_example_py_test
+ add_test(NAME cover_complex_coordinate_gic_example_py_test
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py"
- --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2)
- endif()
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/coordinate_graph_induced_complex.py"
+ -f human.off -c 0 -v)
- # Subsampling
- add_gudhi_py_test(test_subsampling)
+ add_test(NAME cover_complex_functional_gic_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/functional_graph_induced_complex.py"
+ -o lucky_cat.off
+ -f lucky_cat_PCA1 -v)
- endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
- if (NOT CGAL_VERSION VERSION_LESS 4.8.1)
- # Bottleneck
- add_test(NAME bottleneck_basic_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/bottleneck_basic_example.py")
+ add_test(NAME cover_complex_voronoi_gic_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/voronoi_graph_induced_complex.py"
+ -f human.off -n 700 -v)
- add_gudhi_py_test(test_bottleneck_distance)
+ add_gudhi_py_test(test_cover_complex)
+ endif (NOT CGAL_VERSION VERSION_LESS 4.8.1)
- # Cover complex
- file(COPY ${CMAKE_SOURCE_DIR}/data/points/human.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
- file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
- file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat_PCA1 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
- add_test(NAME cover_complex_nerve_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/nerve_of_a_covering.py"
- -f human.off -c 2 -r 10 -g 0.3)
+ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
+ # Alpha
+ add_test(NAME alpha_complex_from_points_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py")
- add_test(NAME cover_complex_coordinate_gic_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/coordinate_graph_induced_complex.py"
- -f human.off -c 0 -v)
+ if(MATPLOTLIB_FOUND AND NUMPY_FOUND)
+ add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py"
+ --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 0.6)
+ endif()
- add_test(NAME cover_complex_functional_gic_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/functional_graph_induced_complex.py"
- -o lucky_cat.off
- -f lucky_cat_PCA1 -v)
+ add_gudhi_py_test(test_alpha_complex)
- add_test(NAME cover_complex_voronoi_gic_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/voronoi_graph_induced_complex.py"
- -f human.off -n 700 -v)
+ endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
- add_gudhi_py_test(test_cover_complex)
- endif (NOT CGAL_VERSION VERSION_LESS 4.8.1)
+ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0)
+ # Euclidean witness
+ add_gudhi_py_test(test_euclidean_witness_complex)
- if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
- # Alpha
- add_test(NAME alpha_complex_from_points_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py")
+ endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0)
- if(MATPLOTLIB_FOUND AND NUMPY_FOUND)
- add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test
+ # Cubical
+ add_test(NAME periodic_cubical_complex_barcode_persistence_from_perseus_file_example_py_test
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py"
- --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 0.6)
- endif()
-
- add_gudhi_py_test(test_alpha_complex)
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py"
+ --no-barcode -f ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt)
- endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.7.0)
+ if(NUMPY_FOUND)
+ add_test(NAME random_cubical_complex_persistence_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/random_cubical_complex_persistence_example.py"
+ 10 10 10)
+ endif()
- if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0)
- # Euclidean witness
- add_gudhi_py_test(test_euclidean_witness_complex)
+ add_gudhi_py_test(test_cubical_complex)
- endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.6.0)
+ # Rips
+ if(MATPLOTLIB_FOUND AND NUMPY_FOUND)
+ add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_file_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py"
+ --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3)
- # Cubical
- add_test(NAME periodic_cubical_complex_barcode_persistence_from_perseus_file_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py"
- --no-barcode -f ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt)
+ add_test(NAME rips_complex_diagram_persistence_from_off_file_example_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_off_file_example.py
+ --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3)
+ endif()
- if(NUMPY_FOUND)
- add_test(NAME random_cubical_complex_persistence_example_py_test
+ add_test(NAME rips_complex_from_points_example_py_test
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/random_cubical_complex_persistence_example.py"
- 10 10 10)
- endif()
+ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_from_points_example.py)
- add_gudhi_py_test(test_cubical_complex)
+ add_gudhi_py_test(test_rips_complex)
- # Rips
- if(MATPLOTLIB_FOUND AND NUMPY_FOUND)
- add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_file_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py"
- --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3)
-
- add_test(NAME rips_complex_diagram_persistence_from_off_file_example_py_test
+ # Simplex tree
+ add_test(NAME simplex_tree_example_py_test
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_off_file_example.py
- --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3)
- endif()
-
- add_test(NAME rips_complex_from_points_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_from_points_example.py)
-
- add_gudhi_py_test(test_rips_complex)
-
- # Simplex tree
- add_test(NAME simplex_tree_example_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/simplex_tree_example.py)
-
- add_gudhi_py_test(test_simplex_tree)
+ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/simplex_tree_example.py)
- # Witness
- add_test(NAME witness_complex_from_nearest_landmark_table_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/witness_complex_from_nearest_landmark_table.py)
+ add_gudhi_py_test(test_simplex_tree)
- add_gudhi_py_test(test_witness_complex)
-
- # Reader utils
- add_gudhi_py_test(test_reader_utils)
-
- # Documentation generation is available through sphinx - requires all modules
- if(SPHINX_PATH AND MATPLOTLIB_FOUND AND NUMPY_FOUND AND NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
- set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/")
- # User warning - Sphinx is a static pages generator, and configured to work fine with user_version
- # Images and biblio warnings because not found on developper version
- if (GUDHI_CYTHON_PATH STREQUAL "src/cython")
- set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developper version. Images and biblio will miss")
- endif()
- # sphinx target requires gudhi.so, because conf.py reads gudhi version from it
- add_custom_target(sphinx
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx
- DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so"
- COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM)
-
- add_test(NAME sphinx_py_test
+ # Witness
+ add_test(NAME witness_complex_from_nearest_landmark_table_py_test
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest)
-
- endif()
-endif(CYTHON_FOUND)
+ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/witness_complex_from_nearest_landmark_table.py)
+
+ add_gudhi_py_test(test_witness_complex)
+
+ # Reader utils
+ add_gudhi_py_test(test_reader_utils)
+
+ # Documentation generation is available through sphinx - requires all modules
+ if(SPHINX_PATH)
+ if(MATPLOTLIB_FOUND)
+ if(NUMPY_FOUND)
+ if(SCIPY_FOUND)
+ if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
+ set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/")
+ # User warning - Sphinx is a static pages generator, and configured to work fine with user_version
+ # Images and biblio warnings because not found on developper version
+ if (GUDHI_CYTHON_PATH STREQUAL "src/cython")
+ set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developper version. Images and biblio will miss")
+ endif()
+ # sphinx target requires gudhi.so, because conf.py reads gudhi version from it
+ add_custom_target(sphinx
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx
+ DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so"
+ COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM)
+
+ add_test(NAME sphinx_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest)
+
+ # Set missing or not modules
+ set(GUDHI_MODULES ${GUDHI_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MODULES")
+ else(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
+ message("++ Python documentation module will not be compiled because it requires a CGAL with Eigen3 version greater or equal than 4.8.1")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+ endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1)
+ else(SCIPY_FOUND)
+ message("++ Python documentation module will not be compiled because scipy was not found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+ endif(SCIPY_FOUND)
+ else(NUMPY_FOUND)
+ message("++ Python documentation module will not be compiled because numpy was not found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+ endif(NUMPY_FOUND)
+ else(MATPLOTLIB_FOUND)
+ message("++ Python documentation module will not be compiled because matplotlib was not found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+ endif(MATPLOTLIB_FOUND)
+ else(SPHINX_PATH)
+ message("++ Python documentation module will not be compiled because sphinx and sphinxcontrib-bibtex were not found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+ endif(SPHINX_PATH)
+
+
+ # Set missing or not modules
+ set(GUDHI_MODULES ${GUDHI_MODULES} "python" CACHE INTERNAL "GUDHI_MODULES")
+ else(CYTHON_FOUND)
+ message("++ Python module will not be compiled because cython was not found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+ endif(CYTHON_FOUND)
+else(PYTHONINTERP_FOUND)
+ message("++ Python module will not be compiled because no Python interpreter was found")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+endif(PYTHONINTERP_FOUND)
diff --git a/src/cython/cython/nerve_gic.pyx b/src/cython/cython/nerve_gic.pyx
index 30a14d3b..5f01b379 100644
--- a/src/cython/cython/nerve_gic.pyx
+++ b/src/cython/cython/nerve_gic.pyx
@@ -38,14 +38,14 @@ cdef extern from "Nerve_gic_interface.h" namespace "Gudhi":
double compute_distance_from_confidence_level(double alpha)
void compute_distribution(int N)
double compute_p_value()
- void compute_PD()
+ vector[pair[double, double]] compute_PD()
void find_simplices()
void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree)
bool read_point_cloud(string off_file_name)
double set_automatic_resolution()
void set_color_from_coordinate(int k)
void set_color_from_file(string color_file_name)
- void set_color_from_vector(vector[double] color)
+ void set_color_from_range(vector[double] color)
void set_cover_from_file(string cover_file_name)
void set_cover_from_function()
void set_cover_from_Euclidean_Voronoi(int m)
@@ -67,6 +67,8 @@ cdef extern from "Nerve_gic_interface.h" namespace "Gudhi":
void write_info()
void plot_DOT()
void plot_OFF()
+ void set_point_cloud_from_range(vector[vector[double]] cloud)
+ void set_distances_from_range(vector[vector[double]] distance_matrix)
# CoverComplex python interface
cdef class CoverComplex:
@@ -102,6 +104,22 @@ cdef class CoverComplex:
"""
return self.thisptr != NULL
+ def set_point_cloud_from_range(self, cloud):
+ """ Reads and stores the input point cloud from a vector stored in memory.
+
+ :param cloud: Input vector containing the point cloud.
+ :type cloud: vector[vector[double]]
+ """
+ return self.thisptr.set_point_cloud_from_range(cloud)
+
+ def set_distances_from_range(self, distance_matrix):
+ """ Reads and stores the input distance matrix from a vector stored in memory.
+
+ :param distance_matrix: Input vector containing the distance matrix.
+ :type distance_matrix: vector[vector[double]]
+ """
+ return self.thisptr.set_distances_from_range(distance_matrix)
+
def compute_confidence_level_from_distance(self, distance):
"""Computes the confidence level of a specific bottleneck distance
threshold.
@@ -145,7 +163,7 @@ cdef class CoverComplex:
def compute_PD(self):
"""Computes the extended persistence diagram of the complex.
"""
- self.thisptr.compute_PD()
+ return self.thisptr.compute_PD()
def create_simplex_tree(self):
"""
@@ -162,7 +180,7 @@ cdef class CoverComplex:
self.thisptr.find_simplices()
def read_point_cloud(self, off_file):
- """Reads and stores the input point cloud.
+ """Reads and stores the input point cloud from .(n)OFF file.
:param off_file: Name of the input .OFF or .nOFF file.
:type off_file: string
@@ -206,14 +224,14 @@ cdef class CoverComplex:
else:
print("file " + color_file_name + " not found.")
- def set_color_from_vector(self, color):
+ def set_color_from_range(self, color):
"""Computes the function used to color the nodes of the simplicial
complex from a vector stored in memory.
:param color: Input vector of values.
:type color: vector[double]
"""
- self.thisptr.set_color_from_vector(color)
+ self.thisptr.set_color_from_range(color)
def set_cover_from_file(self, cover_file_name):
"""Creates the cover C from a file containing the cover elements of
diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py
index 314bd6db..d7be936f 100755..100644
--- a/src/cython/cython/persistence_graphical_tools.py
+++ b/src/cython/cython/persistence_graphical_tools.py
@@ -24,65 +24,70 @@ __author__ = "Vincent Rouvreau, Bertrand Michel"
__copyright__ = "Copyright (C) 2016 Inria"
__license__ = "GPL v3"
-try:
- import matplotlib.pyplot as plt
- import matplotlib.patches as mpatches
- import numpy as np
- import os
-
- def __min_birth_max_death(persistence, band=0.):
- """This function returns (min_birth, max_death) from the persistence.
-
- :param persistence: The persistence to plot.
- :type persistence: list of tuples(dimension, tuple(birth, death)).
- :param band: band
- :type band: float.
- :returns: (float, float) -- (min_birth, max_death).
- """
- # Look for minimum birth date and maximum death date for plot optimisation
- max_death = 0
- min_birth = persistence[0][1][0]
- for interval in reversed(persistence):
- if float(interval[1][1]) != float('inf'):
- if float(interval[1][1]) > max_death:
- max_death = float(interval[1][1])
- if float(interval[1][0]) > max_death:
- max_death = float(interval[1][0])
- if float(interval[1][0]) < min_birth:
- min_birth = float(interval[1][0])
- if band > 0.:
- max_death += band
- return (min_birth, max_death)
+def __min_birth_max_death(persistence, band=0.):
+ """This function returns (min_birth, max_death) from the persistence.
+ :param persistence: The persistence to plot.
+ :type persistence: list of tuples(dimension, tuple(birth, death)).
+ :param band: band
+ :type band: float.
+ :returns: (float, float) -- (min_birth, max_death).
"""
- Only 13 colors for the palette
+ # Look for minimum birth date and maximum death date for plot optimisation
+ max_death = 0
+ min_birth = persistence[0][1][0]
+ for interval in reversed(persistence):
+ if float(interval[1][1]) != float('inf'):
+ if float(interval[1][1]) > max_death:
+ max_death = float(interval[1][1])
+ if float(interval[1][0]) > max_death:
+ max_death = float(interval[1][0])
+ if float(interval[1][0]) < min_birth:
+ min_birth = float(interval[1][0])
+ if band > 0.:
+ max_death += band
+ return (min_birth, max_death)
+
+"""
+Only 13 colors for the palette
+"""
+palette = ['#ff0000', '#00ff00', '#0000ff', '#00ffff', '#ff00ff', '#ffff00',
+ '#000000', '#880000', '#008800', '#000088', '#888800', '#880088',
+ '#008888']
+
+def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6,
+ max_intervals=1000, max_barcodes=1000,
+ inf_delta=0.1, legend=False):
+ """This function plots the persistence bar code from persistence values list
+ or from a :doc:`persistence file <fileformats>`.
+
+ :param persistence: Persistence intervals values list grouped by dimension.
+ :type persistence: list of tuples(dimension, tuple(birth, death)).
+ :param persistence_file: A :doc:`persistence file <fileformats>` style name
+ (reset persistence if both are set).
+ :type persistence_file: string
+ :param alpha: barcode transparency value (0.0 transparent through 1.0
+ opaque - default is 0.6).
+ :type alpha: float.
+ :param max_intervals: maximal number of intervals to display.
+ Selected intervals are those with the longest life time. Set it
+ to 0 to see all. Default value is 1000.
+ :type max_intervals: int.
+ :param inf_delta: Infinity is placed at :code:`((max_death - min_birth) x
+ inf_delta)` above :code:`max_death` value. A reasonable value is
+ between 0.05 and 0.5 - default is 0.1.
+ :type inf_delta: float.
+ :param legend: Display the dimension color legend (default is False).
+ :type legend: boolean.
+ :returns: A matplotlib object containing horizontal bar plot of persistence
+ (launch `show()` method on it to display it).
"""
- palette = ['#ff0000', '#00ff00', '#0000ff', '#00ffff', '#ff00ff', '#ffff00',
- '#000000', '#880000', '#008800', '#000088', '#888800', '#880088',
- '#008888']
-
- def plot_persistence_barcode(persistence=[], persistence_file='', alpha=0.6,
- max_barcodes=1000, inf_delta=0.1, legend=False):
- """This function plots the persistence bar code from persistence values list
- or from a :doc:`persistence file <fileformats>`.
-
- :param persistence: Persistence values list.
- :type persistence: list of tuples(dimension, tuple(birth, death)).
- :param persistence_file: A :doc:`persistence file <fileformats>` style name
- (reset persistence if both are set).
- :type persistence_file: string
- :param alpha: barcode transparency value (0.0 transparent through 1.0 opaque - default is 0.6).
- :type alpha: float.
- :param max_barcodes: number of maximal barcodes to be displayed.
- Set it to 0 to see all, Default value is 1000.
- (persistence will be sorted by life time if max_barcodes is set)
- :type max_barcodes: int.
- :param inf_delta: Infinity is placed at ((max_death - min_birth) x inf_delta).
- A reasonable value is between 0.05 and 0.5 - default is 0.1.
- :type inf_delta: float.
- :returns: A matplotlib object containing horizontal bar plot of persistence
- (launch `show()` method on it to display it).
- """
+ try:
+ import matplotlib.pyplot as plt
+ import matplotlib.patches as mpatches
+ import numpy as np
+ import os
+
if persistence_file is not '':
if os.path.isfile(persistence_file):
# Reset persistence
@@ -95,9 +100,13 @@ try:
print("file " + persistence_file + " not found.")
return None
- if max_barcodes > 0 and max_barcodes < len(persistence):
- # Sort by life time, then takes only the max_plots elements
- persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_barcodes]
+ if max_barcodes is not 1000:
+ print('Deprecated parameter. It has been replaced by max_intervals')
+ max_intervals = max_barcodes
+
+ if max_intervals > 0 and max_intervals < len(persistence):
+ # Sort by life time, then takes only the max_intervals elements
+ persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_intervals]
persistence = sorted(persistence, key=lambda birth: birth[1][0])
@@ -134,30 +143,43 @@ try:
plt.axis([axis_start, infinity, 0, ind])
return plt
- def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6,
- band=0., max_plots=1000, inf_delta=0.1, legend=False):
- """This function plots the persistence diagram from persistence values list
- or from a :doc:`persistence file <fileformats>`.
-
- :param persistence: Persistence values list.
- :type persistence: list of tuples(dimension, tuple(birth, death)).
- :param persistence_file: A :doc:`persistence file <fileformats>` style name
- (reset persistence if both are set).
- :type persistence_file: string
- :param alpha: plot transparency value (0.0 transparent through 1.0 opaque - default is 0.6).
- :type alpha: float.
- :param band: band (not displayed if :math:`\leq` 0. - default is 0.)
- :type band: float.
- :param max_plots: number of maximal plots to be displayed
- Set it to 0 to see all, Default value is 1000.
- (persistence will be sorted by life time if max_plots is set)
- :type max_plots: int.
- :param inf_delta: Infinity is placed at ((max_death - min_birth) x inf_delta).
- A reasonable value is between 0.05 and 0.5 - default is 0.1.
- :type inf_delta: float.
- :returns: A matplotlib object containing diagram plot of persistence
- (launch `show()` method on it to display it).
- """
+ except ImportError:
+ print("This function is not available, you may be missing numpy and/or matplotlib.")
+
+def plot_persistence_diagram(persistence=[], persistence_file='', alpha=0.6,
+ band=0., max_intervals=1000, max_plots=1000, inf_delta=0.1, legend=False):
+ """This function plots the persistence diagram from persistence values
+ list or from a :doc:`persistence file <fileformats>`.
+
+ :param persistence: Persistence intervals values list grouped by dimension.
+ :type persistence: list of tuples(dimension, tuple(birth, death)).
+ :param persistence_file: A :doc:`persistence file <fileformats>` style name
+ (reset persistence if both are set).
+ :type persistence_file: string
+ :param alpha: plot transparency value (0.0 transparent through 1.0
+ opaque - default is 0.6).
+ :type alpha: float.
+ :param band: band (not displayed if :math:`\leq` 0. - default is 0.)
+ :type band: float.
+ :param max_intervals: maximal number of intervals to display.
+ Selected intervals are those with the longest life time. Set it
+ to 0 to see all. Default value is 1000.
+ :type max_intervals: int.
+ :param inf_delta: Infinity is placed at :code:`((max_death - min_birth) x
+ inf_delta)` above :code:`max_death` value. A reasonable value is
+ between 0.05 and 0.5 - default is 0.1.
+ :type inf_delta: float.
+ :param legend: Display the dimension color legend (default is False).
+ :type legend: boolean.
+ :returns: A matplotlib object containing diagram plot of persistence
+ (launch `show()` method on it to display it).
+ """
+ try:
+ import matplotlib.pyplot as plt
+ import matplotlib.patches as mpatches
+ import numpy as np
+ import os
+
if persistence_file is not '':
if os.path.isfile(persistence_file):
# Reset persistence
@@ -170,12 +192,15 @@ try:
print("file " + persistence_file + " not found.")
return None
- if max_plots > 0 and max_plots < len(persistence):
- # Sort by life time, then takes only the max_plots elements
- persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_plots]
+ if max_plots is not 1000:
+ print('Deprecated parameter. It has been replaced by max_intervals')
+ max_intervals = max_plots
+
+ if max_intervals > 0 and max_intervals < len(persistence):
+ # Sort by life time, then takes only the max_intervals elements
+ persistence = sorted(persistence, key=lambda life_time: life_time[1][1]-life_time[1][0], reverse=True)[:max_intervals]
(min_birth, max_death) = __min_birth_max_death(persistence, band)
- ind = 0
delta = ((max_death - min_birth) * inf_delta)
# Replace infinity values with max_death + delta for diagram to be more
# readable
@@ -202,7 +227,6 @@ try:
# Infinite death case for diagram to be nicer
plt.scatter(interval[1][0], infinity, alpha=alpha,
color = palette[interval[0]])
- ind = ind + 1
if legend:
dimensions = list(set(item[0] for item in persistence))
@@ -215,6 +239,110 @@ try:
plt.axis([axis_start, infinity, axis_start, infinity + delta])
return plt
-except ImportError:
- # Continue in case of import error, functions won't be available
- pass
+ except ImportError:
+ print("This function is not available, you may be missing numpy and/or matplotlib.")
+
+def plot_persistence_density(persistence=[], persistence_file='',
+ nbins=300, bw_method=None,
+ max_intervals=1000, dimension=None,
+ cmap=None, legend=False):
+ """This function plots the persistence density from persistence
+ values list or from a :doc:`persistence file <fileformats>`. Be
+ aware that this function does not distinguish the dimension, it is
+ up to you to select the required one. This function also does not handle
+ degenerate data set (scipy correlation matrix inversion can fail).
+
+ :param persistence: Persistence intervals values list grouped by dimension.
+ :type persistence: list of tuples(dimension, tuple(birth, death)).
+ :param persistence_file: A :doc:`persistence file <fileformats>`
+ style name (reset persistence if both are set).
+ :type persistence_file: string
+ :param nbins: Evaluate a gaussian kde on a regular grid of nbins x
+ nbins over data extents (default is 300)
+ :type nbins: int.
+ :param bw_method: The method used to calculate the estimator
+ bandwidth. This can be 'scott', 'silverman', a scalar constant
+ or a callable. If a scalar, this will be used directly as
+ kde.factor. If a callable, it should take a gaussian_kde
+ instance as only parameter and return a scalar. If None
+ (default), 'scott' is used. See
+ `scipy.stats.gaussian_kde documentation
+ <http://scipy.github.io/devdocs/generated/scipy.stats.gaussian_kde.html>`_
+ for more details.
+ :type bw_method: str, scalar or callable, optional.
+ :param max_intervals: maximal number of points used in the density
+ estimation.
+ Selected intervals are those with the longest life time. Set it
+ to 0 to see all. Default value is 1000.
+ :type max_intervals: int.
+ :param dimension: the dimension to be selected in the intervals
+ (default is None to mix all dimensions).
+ :type dimension: int.
+ :param cmap: A matplotlib colormap (default is
+ matplotlib.pyplot.cm.hot_r).
+ :type cmap: cf. matplotlib colormap.
+ :param legend: Display the color bar values (default is False).
+ :type legend: boolean.
+ :returns: A matplotlib object containing diagram plot of persistence
+ (launch `show()` method on it to display it).
+ """
+ try:
+ import matplotlib.pyplot as plt
+ import numpy as np
+ from scipy.stats import kde
+ import os
+ import math
+
+ if persistence_file is not '':
+ if os.path.isfile(persistence_file):
+ # Reset persistence
+ persistence = []
+ diag = read_persistence_intervals_grouped_by_dimension(persistence_file=persistence_file)
+ for key in diag.keys():
+ for persistence_interval in diag[key]:
+ persistence.append((key, persistence_interval))
+ else:
+ print("file " + persistence_file + " not found.")
+ return None
+
+ persistence_dim = []
+ if dimension is not None:
+ persistence_dim = [(dim_interval) for dim_interval in persistence if (dim_interval[0] == dimension)]
+ else:
+ persistence_dim = persistence
+
+ if max_intervals > 0 and max_intervals < len(persistence_dim):
+ # Sort by life time, then takes only the max_intervals elements
+ persistence_dim = sorted(persistence_dim,
+ key=lambda life_time: life_time[1][1]-life_time[1][0],
+ reverse=True)[:max_intervals]
+
+ # Set as numpy array birth and death (remove undefined values - inf and NaN)
+ birth = np.asarray([(interval[1][0]) for interval in persistence_dim if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))])
+ death = np.asarray([(interval[1][1]) for interval in persistence_dim if (math.isfinite(interval[1][1]) and math.isfinite(interval[1][0]))])
+
+ # line display of equation : birth = death
+ x = np.linspace(death.min(), birth.max(), 1000)
+ plt.plot(x, x, color='k', linewidth=1.0)
+
+ # Evaluate a gaussian kde on a regular grid of nbins x nbins over data extents
+ k = kde.gaussian_kde([birth,death], bw_method=bw_method)
+ xi, yi = np.mgrid[birth.min():birth.max():nbins*1j, death.min():death.max():nbins*1j]
+ zi = k(np.vstack([xi.flatten(), yi.flatten()]))
+
+ # default cmap value cannot be done at argument definition level as matplotlib is not yet defined.
+ if cmap is None:
+ cmap = plt.cm.hot_r
+ # Make the plot
+ plt.pcolormesh(xi, yi, zi.reshape(xi.shape), cmap=cmap)
+
+ if legend:
+ plt.colorbar()
+
+ plt.title('Persistence density')
+ plt.xlabel('Birth')
+ plt.ylabel('Death')
+ return plt
+
+ except ImportError:
+ print("This function is not available, you may be missing numpy, matplotlib and/or scipy.")
diff --git a/src/cython/cython/rips_complex.pyx b/src/cython/cython/rips_complex.pyx
index 30ca4443..7c83241c 100644
--- a/src/cython/cython/rips_complex.pyx
+++ b/src/cython/cython/rips_complex.pyx
@@ -33,7 +33,11 @@ __license__ = "GPL v3"
cdef extern from "Rips_complex_interface.h" namespace "Gudhi":
cdef cppclass Rips_complex_interface "Gudhi::rips_complex::Rips_complex_interface":
- Rips_complex_interface(vector[vector[double]] values, double threshold, bool euclidean)
+ Rips_complex_interface()
+ void init_points(vector[vector[double]] values, double threshold)
+ void init_matrix(vector[vector[double]] values, double threshold)
+ void init_points_sparse(vector[vector[double]] values, double threshold, double sparse)
+ void init_matrix_sparse(vector[vector[double]] values, double threshold, double sparse)
void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, int dim_max)
# RipsComplex python interface
@@ -44,10 +48,11 @@ cdef class RipsComplex:
function, or a distance matrix.
"""
- cdef Rips_complex_interface * thisptr
+ cdef Rips_complex_interface thisref
# Fake constructor that does nothing but documenting the constructor
- def __init__(self, points=None, distance_matrix=None, max_edge_length=float('inf')):
+ def __init__(self, points=None, distance_matrix=None,
+ max_edge_length=float('inf'), sparse=None):
"""RipsComplex constructor.
:param max_edge_length: Rips value.
@@ -59,29 +64,38 @@ cdef class RipsComplex:
Or
:param distance_matrix: A distance matrix (full square or lower
- triangular).
+ triangular).
:type points: list of list of double
+
+ And in both cases
+
+ :param sparse: If this is not None, it switches to building a sparse
+ Rips and represents the approximation parameter epsilon.
+ :type sparse: float
"""
# The real cython constructor
- def __cinit__(self, points=None, distance_matrix=None, max_edge_length=float('inf')):
- if distance_matrix is not None:
- self.thisptr = new Rips_complex_interface(distance_matrix, max_edge_length, False)
+ def __cinit__(self, points=None, distance_matrix=None,
+ max_edge_length=float('inf'), sparse=None):
+ if sparse is not None:
+ if distance_matrix is not None:
+ self.thisref.init_matrix_sparse(distance_matrix,
+ max_edge_length,
+ sparse)
+ else:
+ if points is None:
+ # Empty Rips construction
+ points=[]
+ self.thisref.init_points_sparse(points, max_edge_length, sparse)
else:
- if points is None:
- # Empty Rips construction
- points=[]
- self.thisptr = new Rips_complex_interface(points, max_edge_length, True)
-
-
- def __dealloc__(self):
- if self.thisptr != NULL:
- del self.thisptr
+ if distance_matrix is not None:
+ self.thisref.init_matrix(distance_matrix, max_edge_length)
+ else:
+ if points is None:
+ # Empty Rips construction
+ points=[]
+ self.thisref.init_points(points, max_edge_length)
- def __is_defined(self):
- """Returns true if RipsComplex pointer is not NULL.
- """
- return self.thisptr != NULL
def create_simplex_tree(self, max_dimension=1):
"""
@@ -92,5 +106,5 @@ cdef class RipsComplex:
:rtype: SimplexTree
"""
simplex_tree = SimplexTree()
- self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_dimension)
+ self.thisref.create_simplex_tree(simplex_tree.thisptr, max_dimension)
return simplex_tree
diff --git a/src/cython/cython/simplex_tree.pyx b/src/cython/cython/simplex_tree.pyx
index e302486b..0ab97f80 100644
--- a/src/cython/cython/simplex_tree.pyx
+++ b/src/cython/cython/simplex_tree.pyx
@@ -44,8 +44,8 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi":
void set_dimension(int dimension)
int dimension()
int upper_bound_dimension()
- bint find_simplex(vector[int] simplex)
- bint insert_simplex_and_subfaces(vector[int] simplex,
+ bool find_simplex(vector[int] simplex)
+ bool insert_simplex_and_subfaces(vector[int] simplex,
double filtration)
vector[pair[vector[int], double]] get_filtration()
vector[pair[vector[int], double]] get_skeleton(int dimension)
@@ -355,7 +355,7 @@ cdef class SimplexTree:
:param filtration: Maximum threshold value.
:type filtration: float.
:returns: The filtration modification information.
- :rtype: bint
+ :rtype: bool
.. note::
@@ -406,7 +406,7 @@ cdef class SimplexTree:
value than its faces by increasing the filtration values.
:returns: The filtration modification information.
- :rtype: bint
+ :rtype: bool
.. note::
@@ -432,6 +432,10 @@ cdef class SimplexTree:
0.0.
Sets min_persistence to -1.0 to see all values.
:type min_persistence: float.
+ :param persistence_dim_max: If true, the persistent homology for the
+ maximal dimension in the complex is computed. If false, it is
+ ignored. Default is false.
+ :type persistence_dim_max: bool
:returns: The persistence of the simplicial complex.
:rtype: list of pairs(dimension, pair(birth, death))
"""
@@ -515,7 +519,7 @@ cdef class SimplexTree:
:returns: The persistence intervals.
:rtype: list of pair of list of int
- :note: intervals_in_dim function requires
+ :note: persistence_pairs function requires
:func:`persistence()<gudhi.SimplexTree.persistence>`
function to be launched first.
"""
diff --git a/src/cython/doc/examples.rst b/src/cython/doc/examples.rst
index 1f02f8a2..edbc2f72 100644
--- a/src/cython/doc/examples.rst
+++ b/src/cython/doc/examples.rst
@@ -22,6 +22,7 @@ Examples
* :download:`rips_complex_diagram_persistence_from_off_file_example.py <../example/rips_complex_diagram_persistence_from_off_file_example.py>`
* :download:`rips_complex_diagram_persistence_from_distance_matrix_file_example.py <../example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py>`
* :download:`rips_persistence_diagram.py <../example/rips_persistence_diagram.py>`
+ * :download:`sparse_rips_persistence_diagram.py <../example/sparse_rips_persistence_diagram.py>`
* :download:`random_cubical_complex_persistence_example.py <../example/random_cubical_complex_persistence_example.py>`
* :download:`coordinate_graph_induced_complex.py <../example/coordinate_graph_induced_complex.py>`
* :download:`functional_graph_induced_complex.py <../example/functional_graph_induced_complex.py>`
diff --git a/src/cython/doc/installation.rst b/src/cython/doc/installation.rst
index 43576ec9..040f6b4a 100644
--- a/src/cython/doc/installation.rst
+++ b/src/cython/doc/installation.rst
@@ -7,7 +7,7 @@ Installation
Compiling
*********
-The library uses c++11 and requires `Boost <https://www.boost.org/>`_ ≥ 1.48.0
+The library uses c++11 and requires `Boost <https://www.boost.org/>`_ ≥ 1.56.0
and `CMake <https://www.cmake.org/>`_ ≥ 3.1.
It is a multi-platform library and compiles on Linux, Mac OSX and Visual
Studio 2015.
@@ -195,7 +195,7 @@ The following examples require the `Matplotlib <http://matplotlib.org>`_:
* :download:`euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py>`
* :download:`euclidean_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py>`
-Numpy
+NumPy
=====
The :doc:`persistence graphical tools </persistence_graphical_tools_user>`
@@ -216,6 +216,13 @@ The following examples require the `NumPy <http://numpy.org>`_:
* :download:`euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py>`
* :download:`euclidean_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py>`
+SciPy
+=====
+
+The :doc:`persistence graphical tools </persistence_graphical_tools_user>`
+module requires `SciPy <http://scipy.org>`_, a Python-based ecosystem of
+open-source software for mathematics, science, and engineering.
+
Threading Building Blocks
=========================
diff --git a/src/cython/doc/nerve_gic_complex_sum.rst b/src/cython/doc/nerve_gic_complex_sum.rst
index 72782c7a..523c119f 100644
--- a/src/cython/doc/nerve_gic_complex_sum.rst
+++ b/src/cython/doc/nerve_gic_complex_sum.rst
@@ -1,5 +1,5 @@
================================================================= =================================== ===================================
-:Author: Mathieu Carrière :Introduced in: GUDHI 2.1.0 :Copyright: GPL v3
+:Author: Mathieu Carrière :Introduced in: GUDHI 2.3.0 :Copyright: GPL v3
:Requires: CGAL :math:`\geq` 4.8.1
================================================================= =================================== ===================================
diff --git a/src/cython/doc/persistence_graphical_tools_ref.rst b/src/cython/doc/persistence_graphical_tools_ref.rst
index a2c6bcef..54aff4bc 100644
--- a/src/cython/doc/persistence_graphical_tools_ref.rst
+++ b/src/cython/doc/persistence_graphical_tools_ref.rst
@@ -9,3 +9,4 @@ Persistence graphical tools reference manual
.. autofunction:: gudhi.__min_birth_max_death
.. autofunction:: gudhi.plot_persistence_barcode
.. autofunction:: gudhi.plot_persistence_diagram
+.. autofunction:: gudhi.plot_persistence_density
diff --git a/src/cython/doc/persistence_graphical_tools_sum.inc b/src/cython/doc/persistence_graphical_tools_sum.inc
index d602daa7..5577cf99 100644
--- a/src/cython/doc/persistence_graphical_tools_sum.inc
+++ b/src/cython/doc/persistence_graphical_tools_sum.inc
@@ -1,11 +1,11 @@
================================================================= =================================== ===================================
:Author: Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3
-:Requires: Matplotlib Numpy
+:Requires: matplotlib numpy scipy
================================================================= =================================== ===================================
+-----------------------------------------------------------------+-----------------------------------------------------------------------+
| .. figure:: | These graphical tools comes on top of persistence results and allows |
-| img/graphical_tools_representation.png | the user to build easily barcode and persistence diagram. |
+| img/graphical_tools_representation.png | the user to build easily persistence barcode, diagram or density. |
| | |
+-----------------------------------------------------------------+-----------------------------------------------------------------------+
| :doc:`persistence_graphical_tools_user` | :doc:`persistence_graphical_tools_ref` |
diff --git a/src/cython/doc/persistence_graphical_tools_user.rst b/src/cython/doc/persistence_graphical_tools_user.rst
index 292915eb..b2124fdd 100644
--- a/src/cython/doc/persistence_graphical_tools_user.rst
+++ b/src/cython/doc/persistence_graphical_tools_user.rst
@@ -12,6 +12,9 @@ Definition
Show persistence as a barcode
-----------------------------
+.. note::
+ this function requires matplotlib and numpy to be available
+
This function can display the persistence result as a barcode:
.. plot::
@@ -19,16 +22,22 @@ This function can display the persistence result as a barcode:
import gudhi
- perseus_file = gudhi.__root_source_dir__ + '/data/bitmap/3d_torus.txt'
- periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file=perseus_file)
- diag = periodic_cc.persistence()
- print("diag = ", diag)
- plt = gudhi.plot_persistence_barcode(diag)
- plt.show()
+ off_file = gudhi.__root_source_dir__ + '/data/points/tore3D_300.off'
+ point_cloud = gudhi.read_off(off_file=off_file)
+
+ rips_complex = gudhi.RipsComplex(points=point_cloud, max_edge_length=0.7)
+ simplex_tree = rips_complex.create_simplex_tree(max_dimension=3)
+ diag = simplex_tree.persistence(min_persistence=0.4)
+
+ plot = gudhi.plot_persistence_barcode(diag)
+ plot.show()
Show persistence as a diagram
-----------------------------
+.. note::
+ this function requires matplotlib and numpy to be available
+
This function can display the persistence result as a diagram:
.. plot::
@@ -43,6 +52,12 @@ This function can display the persistence result as a diagram:
legend=True)
plt.show()
+Persistence density
+-------------------
+
+.. note::
+ this function requires matplotlib, numpy and scipy to be available
+
If you want more information on a specific dimension, for instance:
.. plot::
@@ -50,13 +65,9 @@ If you want more information on a specific dimension, for instance:
import gudhi
+ # rips_on_tore3D_1307.pers obtained from write_persistence_diagram method
persistence_file=gudhi.__root_source_dir__ + \
'/data/persistence_diagram/rips_on_tore3D_1307.pers'
- diag = \
- gudhi.read_persistence_intervals_grouped_by_dimension(persistence_file=\
- persistence_file)
- dim = 1
- # Display all points with some transparency
- plt = gudhi.plot_persistence_diagram([(dim,interval) for interval in diag[dim]],
- max_plots=0, alpha=0.1)
+ plt = gudhi.plot_persistence_density(persistence_file=persistence_file,
+ max_intervals=0, dimension=1, legend=True)
plt.show()
diff --git a/src/cython/doc/persistent_cohomology_user.rst b/src/cython/doc/persistent_cohomology_user.rst
index ce7fc685..de83cda1 100644
--- a/src/cython/doc/persistent_cohomology_user.rst
+++ b/src/cython/doc/persistent_cohomology_user.rst
@@ -10,12 +10,14 @@ Definition
:Author: Clément Maria :Introduced in: GUDHI PYTHON 2.0.0 :Copyright: GPL v3
===================================== ===================================== =====================================
-+---------------------------------------------+----------------------------------------------------------------------+
-| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence |
-| | feature for reference: |
-| | |
-| | * :doc:`simplex_tree_ref` |
-+---------------------------------------------+----------------------------------------------------------------------+
++-----------------------------------------------------------------+-----------------------------------------------------------------------+
+| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence |
+| | feature for reference: |
+| | |
+| | * :doc:`simplex_tree_ref` |
+| | * :doc:`cubical_complex_ref` |
+| | * :doc:`periodic_cubical_complex_ref` |
++-----------------------------------------------------------------+-----------------------------------------------------------------------+
Computation of persistent cohomology using the algorithm of :cite:`DBLP:journals/dcg/SilvaMV11` and
diff --git a/src/cython/doc/rips_complex_sum.inc b/src/cython/doc/rips_complex_sum.inc
index 5616bfa9..ea26769a 100644
--- a/src/cython/doc/rips_complex_sum.inc
+++ b/src/cython/doc/rips_complex_sum.inc
@@ -1,6 +1,6 @@
-================================================================= =================================== ===================================
-:Author: Clément Maria, Pawel Dlotko, Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3
-================================================================= =================================== ===================================
+===================================================================== =========================== ===================================
+:Author: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3
+===================================================================== =========================== ===================================
+----------------------------------------------------------------+------------------------------------------------------------------------+
| .. figure:: | Rips complex is a simplicial complex constructed from a one skeleton |
diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst
index a8c06cf9..e814b4c3 100644
--- a/src/cython/doc/rips_complex_user.rst
+++ b/src/cython/doc/rips_complex_user.rst
@@ -7,27 +7,27 @@ Rips complex user manual
Definition
----------
-======================================================= ===================================== =====================================
-:Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3
-======================================================= ===================================== =====================================
+==================================================================== ================================ ======================
+:Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3
+==================================================================== ================================ ======================
+-------------------------------------------+----------------------------------------------------------------------+
| :doc:`rips_complex_user` | :doc:`rips_complex_ref` |
+-------------------------------------------+----------------------------------------------------------------------+
-`Rips complex <https://en.wikipedia.org/wiki/Vietoris%E2%80%93Rips_complex>`_ is a one skeleton graph that allows to
-construct a simplicial complex from it. The input can be a point cloud with a given distance function, or a distance
-matrix.
+The `Rips complex <https://en.wikipedia.org/wiki/Vietoris%E2%80%93Rips_complex>`_ is a simplicial complex that
+generalizes proximity (:math:`\varepsilon`-ball) graphs to higher dimensions. The vertices correspond to the input
+points, and a simplex is present if and only if its diameter is smaller than some parameter α. Considering all
+parameters α defines a filtered simplicial complex, where the filtration value of a simplex is its diameter.
+The filtration can be restricted to values α smaller than some threshold, to reduce its size.
-The filtration value of each edge is computed from a user-given distance function, or directly from the distance
-matrix.
+The input discrete metric space can be provided as a point cloud plus a distance function, or as a distance matrix.
-All edges that have a filtration value strictly greater than a given threshold value are not inserted into the complex.
+When creating a simplicial complex from the graph, :doc:`RipsComplex <rips_complex_ref>` first builds the graph and
+inserts it into the data structure. It then expands the simplicial complex (adds the simplices corresponding to cliques)
+when required. The expansion can be stopped at dimension `max_dimension`, by default 1.
-When creating a simplicial complex from this one skeleton graph, Rips inserts the one skeleton graph into the data
-structure, and then expands the simplicial complex when required.
-
-Vertex name correspond to the index of the point in the given range (aka. the point cloud).
+A vertex name corresponds to the index of the point in the given range (aka. the point cloud).
.. figure::
../../doc/Rips_complex/rips_complex_representation.png
@@ -38,8 +38,27 @@ Vertex name correspond to the index of the point in the given range (aka. the po
On this example, as edges (4,5), (4,6) and (5,6) are in the complex, simplex (4,5,6) is added with the filtration value
set with :math:`max(filtration(4,5), filtration(4,6), filtration(5,6))`. And so on for simplex (0,1,2,3).
-If the Rips_complex interfaces are not detailed enough for your need, please refer to rips_persistence_step_by_step.cpp
-example, where the graph construction over the Simplex_tree is more detailed.
+If the `RipsComplex` interfaces are not detailed enough for your need, please refer to rips_persistence_step_by_step.cpp
+C++ example, where the graph construction over the Simplex_tree is more detailed.
+
+A Rips complex can easily become huge, even if we limit the length of the edges
+and the dimension of the simplices. One easy trick, before building a Rips
+complex on a point cloud, is to call `sparsify_point_set` which removes points
+that are too close to each other. This does not change its persistence diagram
+by more than the length used to define "too close".
+
+A more general technique is to use a sparse approximation of the Rips
+introduced by Don Sheehy :cite:`sheehy13linear`. We are using the version
+described in :cite:`buchet16efficient` (except that we multiply all filtration
+values by 2, to match the usual Rips complex), which proves a
+:math:`\frac{1+\varepsilon}{1-\varepsilon}`-interleaving, although in practice the
+error is usually smaller. A more intuitive presentation of the idea is
+available in :cite:`cavanna15geometric`, and in a video
+:cite:`cavanna15visualizing`. Passing an extra argument `sparse=0.3` at the
+construction of a `RipsComplex` object asks it to build a sparse Rips with
+parameter :math:`\varepsilon=0.3`, while the default `sparse=None` builds the
+regular Rips complex.
+
Point cloud
-----------
@@ -47,7 +66,7 @@ Point cloud
Example from a point cloud
^^^^^^^^^^^^^^^^^^^^^^^^^^
-This example builds the one skeleton graph from the given points, and max_edge_length value.
+This example builds the neighborhood graph from the given points, up to max_edge_length.
Then it creates a :doc:`Simplex_tree <simplex_tree_ref>` with it.
Finally, it is asked to display information about the simplicial complex.
@@ -56,7 +75,7 @@ Finally, it is asked to display information about the simplicial complex.
import gudhi
rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]],
- max_edge_length=12.0)
+ max_edge_length=12.0)
simplex_tree = rips_complex.create_simplex_tree(max_dimension=1)
result_str = 'Rips complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \
@@ -92,10 +111,20 @@ until dimension 1 - one skeleton graph in other words), the output is:
[4, 6] -> 9.49
[3, 6] -> 11.00
+Notice that if we use
+
+.. code-block:: python
+
+ rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]],
+ max_edge_length=12.0, sparse=2)
+
+asking for a very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`),
+2 to 5 edges disappear, depending on the random vertex used to start the sparsification.
+
Example from OFF file
^^^^^^^^^^^^^^^^^^^^^
-This example builds the :doc:`Rips_complex <rips_complex_ref>` from the given
+This example builds the :doc:`RipsComplex <rips_complex_ref>` from the given
points in an OFF file, and max_edge_length value.
Then it creates a :doc:`Simplex_tree <simplex_tree_ref>` with it.
@@ -200,7 +229,7 @@ until dimension 1 - one skeleton graph in other words), the output is:
Example from csv file
^^^^^^^^^^^^^^^^^^^^^
-This example builds the :doc:`Rips_complex <rips_complex_ref>` from the given
+This example builds the :doc:`RipsComplex <rips_complex_ref>` from the given
distance matrix in a csv file, and max_edge_length value.
Then it creates a :doc:`Simplex_tree <simplex_tree_ref>` with it.
diff --git a/src/cython/example/sparse_rips_persistence_diagram.py b/src/cython/example/sparse_rips_persistence_diagram.py
new file mode 100755
index 00000000..d58c244c
--- /dev/null
+++ b/src/cython/example/sparse_rips_persistence_diagram.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+import gudhi
+
+"""This file is part of the Gudhi Library. The Gudhi library
+ (Geometric Understanding in Higher Dimensions) is a generic C++
+ library for computational topology.
+
+ Author(s): Marc Glisse
+
+ Copyright (C) 2018 Inria
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+__author__ = "Marc Glisse"
+__copyright__ = "Copyright (C) 2018 Inria"
+__license__ = "GPL v3"
+
+print("#####################################################################")
+print("Sparse RipsComplex creation from points")
+rips = gudhi.RipsComplex(points=[[0, 0], [0, 0.1], [1, 0], [0, 1], [1, 1]],
+ max_edge_length=42, sparse=.5)
+
+simplex_tree = rips.create_simplex_tree(max_dimension=2)
+
+
+diag = simplex_tree.persistence(homology_coeff_field=2, min_persistence=0)
+print("diag=", diag)
+
+pplot = gudhi.plot_persistence_diagram(diag)
+pplot.show()
diff --git a/src/cython/include/Alpha_complex_interface.h b/src/cython/include/Alpha_complex_interface.h
index 8cf527fc..faa059d1 100644
--- a/src/cython/include/Alpha_complex_interface.h
+++ b/src/cython/include/Alpha_complex_interface.h
@@ -60,7 +60,7 @@ class Alpha_complex_interface {
Point_d ph = alpha_complex_->get_point(vh);
for (auto coord = ph.cartesian_begin(); coord < ph.cartesian_end(); coord++)
vd.push_back(*coord);
- } catch (std::out_of_range outofrange) {
+ } catch (std::out_of_range const&) {
// std::out_of_range is thrown in case not found. Other exceptions must be re-thrown
}
return vd;
diff --git a/src/cython/include/Rips_complex_interface.h b/src/cython/include/Rips_complex_interface.h
index 8b6c9c35..1a6e2477 100644
--- a/src/cython/include/Rips_complex_interface.h
+++ b/src/cython/include/Rips_complex_interface.h
@@ -25,8 +25,11 @@
#include <gudhi/Simplex_tree.h>
#include <gudhi/Rips_complex.h>
+#include <gudhi/Sparse_rips_complex.h>
#include <gudhi/distance_functions.h>
+#include <boost/optional.hpp>
+
#include "Simplex_tree_interface.h"
#include <iostream>
@@ -43,28 +46,40 @@ class Rips_complex_interface {
using Distance_matrix = std::vector<std::vector<Simplex_tree_interface<>::Filtration_value>>;
public:
- Rips_complex_interface(const std::vector<std::vector<double>>& values, double threshold, bool euclidean) {
- if (euclidean) {
- // Rips construction where values is a vector of points
- rips_complex_ = new Rips_complex<Simplex_tree_interface<>::Filtration_value>(values, threshold,
- Gudhi::Euclidean_distance());
- } else {
- // Rips construction where values is a distance matrix
- rips_complex_ = new Rips_complex<Simplex_tree_interface<>::Filtration_value>(values, threshold);
- }
+ void init_points(const std::vector<std::vector<double>>& points, double threshold) {
+ rips_complex_.emplace(points, threshold, Gudhi::Euclidean_distance());
+ }
+ void init_matrix(const std::vector<std::vector<double>>& matrix, double threshold) {
+ rips_complex_.emplace(matrix, threshold);
}
- ~Rips_complex_interface() {
- delete rips_complex_;
+ void init_points_sparse(const std::vector<std::vector<double>>& points, double threshold, double epsilon) {
+ sparse_rips_complex_.emplace(points, Gudhi::Euclidean_distance(), epsilon);
+ threshold_ = threshold;
+ }
+ void init_matrix_sparse(const std::vector<std::vector<double>>& matrix, double threshold, double epsilon) {
+ sparse_rips_complex_.emplace(matrix, epsilon);
+ threshold_ = threshold;
}
void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, int dim_max) {
- rips_complex_->create_complex(*simplex_tree, dim_max);
+ if (rips_complex_)
+ rips_complex_->create_complex(*simplex_tree, dim_max);
+ else {
+ sparse_rips_complex_->create_complex(*simplex_tree, dim_max);
+ // This pruning should be done much earlier! It isn't that useful for sparse Rips,
+ // but it would be inconsistent not to do it.
+ simplex_tree->prune_above_filtration(threshold_);
+ }
simplex_tree->initialize_filtration();
}
private:
- Rips_complex<Simplex_tree_interface<>::Filtration_value>* rips_complex_;
+ // std::variant would work, but we don't require C++17 yet, and boost::variant is not super convenient.
+ // Anyway, storing a graph would make more sense. Or changing the interface completely so there is no such storage.
+ boost::optional<Rips_complex<Simplex_tree_interface<>::Filtration_value>> rips_complex_;
+ boost::optional<Sparse_rips_complex<Simplex_tree_interface<>::Filtration_value>> sparse_rips_complex_;
+ double threshold_;
};
} // namespace rips_complex
diff --git a/src/cython/test/test_rips_complex.py b/src/cython/test/test_rips_complex.py
index c37b5400..05dfcaf7 100755
--- a/src/cython/test/test_rips_complex.py
+++ b/src/cython/test/test_rips_complex.py
@@ -30,7 +30,6 @@ __license__ = "GPL v3"
def test_empty_rips():
rips_complex = RipsComplex()
- assert rips_complex.__is_defined() == True
def test_rips_from_points():
point_list = [[0, 0], [1, 0], [0, 1], [1, 1]]
@@ -68,12 +67,26 @@ def test_filtered_rips_from_points():
assert simplex_tree.num_simplices() == 8
assert simplex_tree.num_vertices() == 4
+def test_sparse_filtered_rips_from_points():
+ point_list = [[0, 0], [1, 0], [0, 1], [1, 1]]
+ filtered_rips = RipsComplex(points=point_list, max_edge_length=1.0,
+ sparse=.001)
+
+ simplex_tree = filtered_rips.create_simplex_tree(max_dimension=1)
+
+ assert simplex_tree.__is_defined() == True
+ assert simplex_tree.__is_persistence_defined() == False
+
+ assert simplex_tree.num_simplices() == 8
+ assert simplex_tree.num_vertices() == 4
+
def test_rips_from_distance_matrix():
distance_matrix = [[0],
[1, 0],
[1, sqrt(2), 0],
[sqrt(2), 1, 1, 0]]
- rips_complex = RipsComplex(distance_matrix=distance_matrix, max_edge_length=42)
+ rips_complex = RipsComplex(distance_matrix=distance_matrix,
+ max_edge_length=42)
simplex_tree = rips_complex.create_simplex_tree(max_dimension=1)
@@ -100,7 +113,8 @@ def test_filtered_rips_from_distance_matrix():
[1, 0],
[1, sqrt(2), 0],
[sqrt(2), 1, 1, 0]]
- filtered_rips = RipsComplex(distance_matrix=distance_matrix, max_edge_length=1.0)
+ filtered_rips = RipsComplex(distance_matrix=distance_matrix,
+ max_edge_length=1.0)
simplex_tree = filtered_rips.create_simplex_tree(max_dimension=1)