summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/benchmark/CMakeLists.txt3
-rw-r--r--src/common/benchmark/Graph_simplicial_complex_benchmark.cpp138
-rw-r--r--src/common/doc/Gudhi_banner.pngbin0 -> 34877 bytes
-rw-r--r--src/common/doc/examples.h96
-rw-r--r--src/common/doc/file_formats.h143
-rw-r--r--src/common/doc/footer.html23
-rw-r--r--src/common/doc/header.html103
-rw-r--r--src/common/doc/installation.h262
-rw-r--r--src/common/doc/main_page.md391
-rw-r--r--src/common/doc/offline_header.html41
-rw-r--r--src/common/doc/stylesheet.css1367
-rw-r--r--src/common/example/CMakeLists.txt30
-rw-r--r--src/common/example/cgal3Doffreader_result.txt8
-rw-r--r--src/common/example/example_CGAL_3D_points_off_reader.cpp41
-rw-r--r--src/common/example/example_CGAL_points_off_reader.cpp46
-rw-r--r--src/common/example/example_vector_double_points_off_reader.cpp43
-rw-r--r--src/common/example/vectordoubleoffreader_result.txt7
-rw-r--r--src/common/include/gudhi/Clock.h77
-rw-r--r--src/common/include/gudhi/Debug_utils.h45
-rw-r--r--src/common/include/gudhi/Null_output_iterator.h36
-rw-r--r--src/common/include/gudhi/Off_reader.h173
-rw-r--r--src/common/include/gudhi/Point.h157
-rw-r--r--src/common/include/gudhi/Points_3D_off_io.h190
-rw-r--r--src/common/include/gudhi/Points_off_io.h171
-rw-r--r--src/common/include/gudhi/Simple_object_pool.h69
-rw-r--r--src/common/include/gudhi/Unitary_tests_utils.h28
-rw-r--r--src/common/include/gudhi/allocator.h43
-rw-r--r--src/common/include/gudhi/console_color.h85
-rw-r--r--src/common/include/gudhi/distance_functions.h111
-rw-r--r--src/common/include/gudhi/graph_simplicial_complex.h99
-rw-r--r--src/common/include/gudhi/random_point_generators.h502
-rw-r--r--src/common/include/gudhi/reader_utils.h357
-rw-r--r--src/common/include/gudhi/writing_persistence_to_file.h105
-rw-r--r--src/common/test/CMakeLists.txt24
-rw-r--r--src/common/test/README14
-rw-r--r--src/common/test/dtoffrw_alphashapedoc_result.off7
-rw-r--r--src/common/test/persistence_intervals_with_dimension.pers5
-rw-r--r--src/common/test/persistence_intervals_with_field.pers4
-rw-r--r--src/common/test/persistence_intervals_without_dimension.pers7
-rw-r--r--src/common/test/test_distance_matrix_reader.cpp73
-rw-r--r--src/common/test/test_persistence_intervals_reader.cpp310
-rw-r--r--src/common/test/test_points_off_reader.cpp61
-rw-r--r--src/common/utilities/CMakeLists.txt16
-rw-r--r--src/common/utilities/off_file_from_shape_generator.cpp177
-rw-r--r--src/common/utilities/pointsetgenerator.md39
45 files changed, 5727 insertions, 0 deletions
diff --git a/src/common/benchmark/CMakeLists.txt b/src/common/benchmark/CMakeLists.txt
new file mode 100644
index 00000000..a3787d6e
--- /dev/null
+++ b/src/common/benchmark/CMakeLists.txt
@@ -0,0 +1,3 @@
+project(common_benchmark)
+
+add_executable(Graph_simplicial_complex_benchmark Graph_simplicial_complex_benchmark.cpp)
diff --git a/src/common/benchmark/Graph_simplicial_complex_benchmark.cpp b/src/common/benchmark/Graph_simplicial_complex_benchmark.cpp
new file mode 100644
index 00000000..0fc145fd
--- /dev/null
+++ b/src/common/benchmark/Graph_simplicial_complex_benchmark.cpp
@@ -0,0 +1,138 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Vincent Rouvreau
+ *
+ * Copyright (C) 2018 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/distance_functions.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Clock.h>
+#include <gudhi/Points_off_io.h>
+
+#include <boost/graph/adjacency_list.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <limits> // for numeric limits
+#include <fstream>
+#include <cassert>
+
+
+std::ofstream results_csv("results.csv");
+
+template< typename Adjacency_list, typename ForwardPointRange, typename Distance >
+Adjacency_list proximity_graph_computation(const ForwardPointRange& points, double threshold, Distance distance) {
+ std::vector<std::pair< int, int >> edges;
+ std::vector< double > edges_fil;
+ std::map< int, double > vertices;
+
+ int idx_u, idx_v;
+ double fil;
+ idx_u = 0;
+ for (auto it_u = points.begin(); it_u != points.end(); ++it_u) {
+ idx_v = idx_u + 1;
+ for (auto it_v = it_u + 1; it_v != points.end(); ++it_v, ++idx_v) {
+ fil = distance(*it_u, *it_v);
+ if (fil <= threshold) {
+ edges.emplace_back(idx_u, idx_v);
+ edges_fil.push_back(fil);
+ }
+ }
+ ++idx_u;
+ }
+
+ // Points are labeled from 0 to idx_u-1
+ Adjacency_list skel_graph(edges.begin(), edges.end(), edges_fil.begin(), idx_u);
+
+ auto vertex_prop = boost::get(Gudhi::vertex_filtration_t(), skel_graph);
+
+ typename boost::graph_traits<Adjacency_list>::vertex_iterator vi, vi_end;
+ for (std::tie(vi, vi_end) = boost::vertices(skel_graph);
+ vi != vi_end; ++vi) {
+ boost::put(vertex_prop, *vi, 0.);
+ }
+
+ return skel_graph;
+}
+
+template <typename Adjacency_list>
+void benchmark_proximity_graph(const std::string& msg, const std::string& off_file_name) {
+ Gudhi::Points_off_reader<std::vector<double>> off_reader(off_file_name);
+ assert(off_reader.is_valid());
+
+ std::cout << "+ " << msg << std::endl;
+
+ results_csv << "\"nb_points\";"
+ << "\"nb_simplices\";"
+ << "\"compute proximity graph(sec.)\";"
+ << "\"complex_creation_time(sec.)\";"
+ << "\"" << msg << "\";" << std::endl;
+
+ Gudhi::Clock pg_compute_proximity_graph(" benchmark_proximity_graph - compute proximity graph");
+ pg_compute_proximity_graph.begin();
+ // benchmark begin
+ Adjacency_list proximity_graph = proximity_graph_computation<Adjacency_list>(off_reader.get_point_cloud(),
+ std::numeric_limits<double>::infinity(),
+ Gudhi::Euclidean_distance());
+ // benchmark end
+ pg_compute_proximity_graph.end();
+ std::cout << pg_compute_proximity_graph;
+
+ Gudhi::Simplex_tree<> complex;
+ Gudhi::Clock st_create_clock(" benchmark_proximity_graph - complex creation");
+ st_create_clock.begin();
+ // benchmark begin
+ complex.insert_graph(proximity_graph);
+ // benchmark end
+ st_create_clock.end();
+ std::cout << st_create_clock;
+
+ results_csv << off_reader.get_point_cloud().size() << ";" << complex.num_simplices() << ";"
+ << pg_compute_proximity_graph.num_seconds() << ";"
+ << st_create_clock.num_seconds() << ";" << std::endl;
+
+ std::cout << " benchmark_proximity_graph - nb simplices = " << complex.num_simplices() << std::endl;
+}
+
+int main(int argc, char * const argv[]) {
+ std::string off_file_name(argv[1]);
+
+ // The fastest, the less memory used
+ using vecSdirectedS = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
+ boost::property<Gudhi::vertex_filtration_t, double>,
+ boost::property<Gudhi::edge_filtration_t, double>>;
+ benchmark_proximity_graph<vecSdirectedS>("vecSdirectedS", off_file_name);
+
+ using vecSundirectedS = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
+ boost::property<Gudhi::vertex_filtration_t, double>,
+ boost::property<Gudhi::edge_filtration_t, double>>;
+ benchmark_proximity_graph<vecSundirectedS>("vecSundirectedS", off_file_name);
+
+ using vecSbidirectionalS = boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
+ boost::property<Gudhi::vertex_filtration_t, double>,
+ boost::property<Gudhi::edge_filtration_t, double>>;
+ benchmark_proximity_graph<vecSbidirectionalS>("vecSbidirectionalS", off_file_name);
+
+ using setSdirectedS = boost::adjacency_list<boost::setS, boost::vecS, boost::directedS,
+ boost::property<Gudhi::vertex_filtration_t, double>,
+ boost::property<Gudhi::edge_filtration_t, double>>;
+ benchmark_proximity_graph<setSdirectedS>("setSdirectedS", off_file_name);
+
+ using setSundirectedS = boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS,
+ boost::property<Gudhi::vertex_filtration_t, double>,
+ boost::property<Gudhi::edge_filtration_t, double>>;
+ benchmark_proximity_graph<setSundirectedS>("setSundirectedS", off_file_name);
+
+ using setSbidirectionalS = boost::adjacency_list<boost::setS, boost::vecS, boost::bidirectionalS,
+ boost::property<Gudhi::vertex_filtration_t, double>,
+ boost::property<Gudhi::edge_filtration_t, double>>;
+ benchmark_proximity_graph<setSbidirectionalS>("setSbidirectionalS", off_file_name);
+
+ return 0;
+}
diff --git a/src/common/doc/Gudhi_banner.png b/src/common/doc/Gudhi_banner.png
new file mode 100644
index 00000000..18e8a672
--- /dev/null
+++ b/src/common/doc/Gudhi_banner.png
Binary files differ
diff --git a/src/common/doc/examples.h b/src/common/doc/examples.h
new file mode 100644
index 00000000..c19b3444
--- /dev/null
+++ b/src/common/doc/examples.h
@@ -0,0 +1,96 @@
+// List of GUDHI examples - Doxygen needs at least a file tag to analyse comments
+// In user_version, `find . -name "*.cpp"` in example and utilities folders
+/*! @file Examples
+ * @example Alpha_complex/Alpha_complex_from_off.cpp
+ * @example Alpha_complex/Alpha_complex_from_points.cpp
+ * @example Bottleneck_distance/bottleneck_basic_example.cpp
+ * @example Bottleneck_distance/alpha_rips_persistence_bottleneck_distance.cpp
+ * @example Witness_complex/example_nearest_landmark_table.cpp
+ * @example Witness_complex/example_witness_complex_off.cpp
+ * @example Witness_complex/example_witness_complex_sphere.cpp
+ * @example Witness_complex/example_strong_witness_complex_off.cpp
+ * @example Simplex_tree/mini_simplex_tree.cpp
+ * @example Simplex_tree/graph_expansion_with_blocker.cpp
+ * @example Simplex_tree/simple_simplex_tree.cpp
+ * @example Simplex_tree/simplex_tree_from_cliques_of_graph.cpp
+ * @example Simplex_tree/example_alpha_shapes_3_simplex_tree_from_off_file.cpp
+ * @example Simplex_tree/cech_complex_cgal_mini_sphere_3d.cpp
+ * @example Persistent_cohomology/plain_homology.cpp
+ * @example Persistent_cohomology/persistence_from_file.cpp
+ * @example Persistent_cohomology/rips_persistence_step_by_step.cpp
+ * @example Persistent_cohomology/rips_persistence_via_boundary_matrix.cpp
+ * @example Persistent_cohomology/custom_persistence_sort.cpp
+ * @example Persistent_cohomology/persistence_from_simple_simplex_tree.cpp
+ * @example Persistent_cohomology/rips_multifield_persistence.cpp
+ * @example Skeleton_blocker/Skeleton_blocker_from_simplices.cpp
+ * @example Skeleton_blocker/Skeleton_blocker_iteration.cpp
+ * @example Skeleton_blocker/Skeleton_blocker_link.cpp
+ * @example Contraction/Garland_heckbert.cpp
+ * @example Contraction/Rips_contraction.cpp
+ * @example Bitmap_cubical_complex/Random_bitmap_cubical_complex.cpp
+ * @example common/example_CGAL_3D_points_off_reader.cpp
+ * @example common/example_vector_double_points_off_reader.cpp
+ * @example common/example_CGAL_points_off_reader.cpp
+ * @example Rips_complex/example_one_skeleton_rips_from_distance_matrix.cpp
+ * @example Rips_complex/example_one_skeleton_rips_from_points.cpp
+ * @example Rips_complex/example_rips_complex_from_csv_distance_matrix_file.cpp
+ * @example Rips_complex/example_rips_complex_from_off_file.cpp
+ * @example Persistence_representations/persistence_intervals.cpp
+ * @example Persistence_representations/persistence_vectors.cpp
+ * @example Persistence_representations/persistence_heat_maps.cpp
+ * @example Persistence_representations/persistence_landscape_on_grid.cpp
+ * @example Persistence_representations/persistence_landscape.cpp
+ * @example Tangential_complex/example_basic.cpp
+ * @example Tangential_complex/example_with_perturb.cpp
+ * @example Subsampling/example_custom_kernel.cpp
+ * @example Subsampling/example_choose_n_farthest_points.cpp
+ * @example Subsampling/example_sparsify_point_set.cpp
+ * @example Subsampling/example_pick_n_random_points.cpp
+ * @example Nerve_GIC/CoordGIC.cpp
+ * @example Nerve_GIC/Nerve.cpp
+ * @example Nerve_GIC/FuncGIC.cpp
+ * @example Nerve_GIC/VoronoiGIC.cpp
+ * @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_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
+ * @example Bitmap_cubical_complex/cubical_complex_persistence.cpp
+ * @example Bitmap_cubical_complex/periodic_cubical_complex_persistence.cpp
+ * @example common/off_file_from_shape_generator.cpp
+ * @example Rips_complex/rips_distance_matrix_persistence.cpp
+ * @example Rips_complex/rips_persistence.cpp
+ * @example Persistence_representations/persistence_landscapes_on_grid/create_landscapes_on_grid.cpp
+ * @example Persistence_representations/persistence_landscapes_on_grid/plot_landscapes_on_grid.cpp
+ * @example Persistence_representations/persistence_landscapes_on_grid/compute_scalar_product_of_landscapes_on_grid.cpp
+ * @example Persistence_representations/persistence_landscapes_on_grid/compute_distance_of_landscapes_on_grid.cpp
+ * @example Persistence_representations/persistence_landscapes_on_grid/average_landscapes_on_grid.cpp
+ * @example Persistence_representations/persistence_intervals/compute_birth_death_range_in_persistence_diagram.cpp
+ * @example Persistence_representations/persistence_intervals/compute_number_of_dominant_intervals.cpp
+ * @example Persistence_representations/persistence_intervals/plot_persistence_Betti_numbers.cpp
+ * @example Persistence_representations/persistence_intervals/plot_persistence_intervals.cpp
+ * @example Persistence_representations/persistence_intervals/plot_histogram_of_intervals_lengths.cpp
+ * @example Persistence_representations/persistence_intervals/compute_bottleneck_distance.cpp
+ * @example Persistence_representations/persistence_heat_maps/create_pssk.cpp
+ * @example Persistence_representations/persistence_heat_maps/create_p_h_m_weighted_by_arctan_of_their_persistence.cpp
+ * @example Persistence_representations/persistence_heat_maps/create_p_h_m_weighted_by_squared_diag_distance.cpp
+ * @example Persistence_representations/persistence_heat_maps/compute_distance_of_persistence_heat_maps.cpp
+ * @example Persistence_representations/persistence_heat_maps/compute_scalar_product_of_persistence_heat_maps.cpp
+ * @example Persistence_representations/persistence_heat_maps/create_p_h_m_weighted_by_distance_from_diagonal.cpp
+ * @example Persistence_representations/persistence_heat_maps/average_persistence_heat_maps.cpp
+ * @example Persistence_representations/persistence_heat_maps/plot_persistence_heat_map.cpp
+ * @example Persistence_representations/persistence_heat_maps/create_persistence_heat_maps.cpp
+ * @example Persistence_representations/persistence_vectors/plot_persistence_vectors.cpp
+ * @example Persistence_representations/persistence_vectors/compute_distance_of_persistence_vectors.cpp
+ * @example Persistence_representations/persistence_vectors/average_persistence_vectors.cpp
+ * @example Persistence_representations/persistence_vectors/create_persistence_vectors.cpp
+ * @example Persistence_representations/persistence_vectors/compute_scalar_product_of_persistence_vectors.cpp
+ * @example Persistence_representations/persistence_landscapes/average_landscapes.cpp
+ * @example Persistence_representations/persistence_landscapes/compute_scalar_product_of_landscapes.cpp
+ * @example Persistence_representations/persistence_landscapes/create_landscapes.cpp
+ * @example Persistence_representations/persistence_landscapes/compute_distance_of_landscapes.cpp
+ * @example Persistence_representations/persistence_landscapes/plot_landscapes.cpp
+ */
+
diff --git a/src/common/doc/file_formats.h b/src/common/doc/file_formats.h
new file mode 100644
index 00000000..4af5d45c
--- /dev/null
+++ b/src/common/doc/file_formats.h
@@ -0,0 +1,143 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Clément Jamin
+ *
+ * Copyright (C) 2017 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef DOC_COMMON_FILE_FORMAT_H_
+#define DOC_COMMON_FILE_FORMAT_H_
+
+namespace Gudhi {
+
+/*! \page fileformats File formats
+
+ \tableofcontents
+
+ \section FileFormatsOFF OFF file format
+
+ OFF files must be conform to format described here: http://www.geomview.org/docs/html/OFF.html
+
+ OFF files are mainly used as point cloud inputs. Here is an example of 7 points in a 3-dimensional space. As edges and
+ faces are not used for point set, there is no need to specify them (just set their numbers to 0):
+
+ \include points/alphacomplexdoc.off
+
+ For dimensions bigger than 3, the dimension can be set like here:
+ \verbatim
+ # Dimension is no more 3
+ nOFF
+ # dimension 4 - 7 vertices - 0 face - 0 edge
+ 4 7 0 0
+ # Point set:
+ 1.0 1.0 0.0 0.0
+ 7.0 0.0 0.0 0.0
+ 4.0 6.0 0.0 0.0
+ 9.0 6.0 0.0 0.0
+ 0.0 14.0 0.0 0.0
+ 2.0 19.0 0.0 0.0
+ 9.0 17.0 0.0 0.0
+ \endverbatim
+
+
+ \section FileFormatsPers Persistence Diagram
+
+ Such a file, whose extension is usually `.pers`, contains a list of persistence intervals.<br>
+ Lines starting with `#` are ignored (comments).<br>
+ Other lines might contain 2, 3 or 4 values (the number of values on each line must be the same for all lines):
+ \verbatim
+ [[field] dimension] birth death
+ \endverbatim
+
+ Here is a simple sample file:
+ \verbatim
+ # Persistence diagram example
+ 2 2.7 3.7
+ 2 9.6 14.
+ # Some comments
+ 3 34.2 34.974
+ 4 3. inf
+ \endverbatim
+
+ Other sample files can be found in the `data/persistence_diagram` folder.
+
+ Such files can be generated with `Gudhi::persistent_cohomology::Persistent_cohomology::output_diagram()` and read with
+ `Gudhi::read_persistence_intervals_and_dimension()`, `Gudhi::read_persistence_intervals_grouped_by_dimension()` or
+ `Gudhi::read_persistence_intervals_in_dimension()`.
+
+
+ \section FileFormatsIsoCuboid Iso-cuboid
+
+ Such a file describes an iso-oriented cuboid with diagonal opposite vertices (min_x, min_y, min_z,...) and (max_x, max_y, max_z, ...). The format is:<br>
+ \verbatim
+ min_x min_y [min_z ...]
+ max_x max_y [max_z ...]
+ \endverbatim
+
+ Here is a simple sample file in the 3D case:
+ \verbatim
+ -1. -1. -1.
+ 1. 1. 1.
+ \endverbatim
+
+
+ \section FileFormatsPerseus Perseus
+
+ This file format is a format inspired from the Perseus software
+ (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda.
+ The first line contains a number d begin the dimension of the
+ bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each dimensions (3 and 3
+ in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8
+ 20 4 7 6 5 in the example below).
+
+ \image html "exampleBitmap.png" "Example of a input data."
+
+ The input file for the following complex is:
+ \verbatim
+ 2
+ 3
+ 3
+ 1
+ 4
+ 6
+ 8
+ 20
+ 4
+ 7
+ 6
+ 5
+ \endverbatim
+
+ To indicate periodic boundary conditions in a
+ given direction, then number of top dimensional cells in this direction have to be multiplied by -1. For instance:
+
+ \verbatim
+ 2
+ -3
+ 3
+ 1
+ 4
+ 6
+ 8
+ 20
+ 4
+ 7
+ 6
+ 5
+ \endverbatim
+
+ Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y.
+
+ Other sample files can be found in the `data/bitmap` folder.
+
+ \note Unlike in Perseus format the filtration on the maximal cubes can be any double precision number.
+ Consequently one cannot mark the cubes that are not present with `-1`'s. To do that please set their filtration value
+ to \f$+\infty\f$ (aka. `inf` in the file).
+
+*/
+} // namespace Gudhi
+
+#endif // DOC_COMMON_FILE_FORMAT_H_
diff --git a/src/common/doc/footer.html b/src/common/doc/footer.html
new file mode 100644
index 00000000..4168c6bc
--- /dev/null
+++ b/src/common/doc/footer.html
@@ -0,0 +1,23 @@
+<!-- HTML footer for doxygen 1.8.6-->
+<!-- start footer part -->
+<table style="width:100%">
+ <tr class="no-bullet shadow-black">
+ <td class="network-entypo">
+<!--BEGIN PROJECT_NAME--> $projectname
+<!--BEGIN PROJECT_NUMBER-->&#160;Version $projectnumber<!--END PROJECT_NUMBER-->
+<!--BEGIN PROJECT_BRIEF-->&#160;-&#160;$projectbrief<!--END PROJECT_BRIEF-->
+<!--BEGIN PROJECT_BRIEF-->&#160;-&#160;Copyright : MIT<!--END PROJECT_BRIEF-->
+<!--END PROJECT_NAME-->
+ </td>
+ <td class="network-entypo">
+<!--BEGIN GENERATE_TREEVIEW-->
+ $generatedby
+ <a href="http://www.doxygen.org/index.html">
+ Doxygen</a> $doxygenversion
+<!--END GENERATE_TREEVIEW-->
+ </td>
+ </tr>
+</table>
+
+</body>
+</html>
diff --git a/src/common/doc/header.html b/src/common/doc/header.html
new file mode 100644
index 00000000..9fdb2321
--- /dev/null
+++ b/src/common/doc/header.html
@@ -0,0 +1,103 @@
+<!-- HTML header for doxygen 1.8.6-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!-- GUDHI website : class="no-js" lang="en" is necessary -->
+<html xmlns="http://www.w3.org/1999/xhtml" class="no-js" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen $doxygenversion"/>
+<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
+<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
+<!-- GUDHI website css for header BEGIN -->
+<link rel="stylesheet" type="text/css" href="https://gudhi.inria.fr/assets/css/styles_feeling_responsive.css" />
+<!-- GUDHI website css for header END -->
+<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath^jquery.js"></script>
+<script type="text/javascript" src="$relpath^dynsections.js"></script>
+$treeview
+$search
+$mathjax
+<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
+$extrastylesheet
+</head>
+<body>
+
+<!-- GUDHI website header BEGIN -->
+<div id="navigation" class="sticky">
+ <nav class="top-bar" role="navigation" data-topbar>
+ <ul class="title-area">
+ <li class="name">
+ <h1 class="show-for-small-only"><a href="" class="icon-tree"> GUDHI library</a></h1>
+ </li>
+ <!-- Remove the class "menu-icon" to get rid of menu icon. Take out "Menu" to just have icon alone -->
+ <li class="toggle-topbar menu-icon"><a href="#"><span>Navigation</span></a></li>
+ </ul>
+ <section class="top-bar-section">
+ <ul class="right">
+ <li class="divider"></li>
+ <li><a href="/contact/">Contact</a></li>
+ </ul>
+ <ul class="left">
+ <li><a href="/"> <img src="/assets/img/home.png" alt="&nbsp;&nbsp;GUDHI">&nbsp;&nbsp;GUDHI </a></li>
+ <li class="divider"></li>
+ <li class="has-dropdown">
+ <a href="#">Project</a>
+ <ul class="dropdown">
+ <li><a href="/people/">People</a></li>
+ <li><a href="/keepintouch/">Keep in touch</a></li>
+ <li><a href="/partners/">Partners and Funding</a></li>
+ <li><a href="/relatedprojects/">Related projects</a></li>
+ <li><a href="/theyaretalkingaboutus/">They are talking about us</a></li>
+ <li><a href="/inaction/">GUDHI in action</a></li>
+ </ul>
+ </li>
+ <li class="divider"></li>
+ <li class="has-dropdown">
+ <a href="#">Download</a>
+ <ul class="dropdown">
+ <li><a href="/licensing/">Licensing</a></li>
+ <li><a href="https://gforge.inria.fr/frs/download.php/latestzip/5253/library-latest.zip" target="_blank">Get the latest sources</a></li>
+ <li><a href="/conda/">Conda package</a></li>
+ <li><a href="/dockerfile/">Dockerfile</a></li>
+ </ul>
+ </li>
+ <li class="divider"></li>
+ <li class="has-dropdown">
+ <a href="#">Documentation</a>
+ <ul class="dropdown">
+ <li><a href="/introduction/">Introduction</a></li>
+ <li><a href="https://gudhi.inria.fr/doc/latest/installation.html">C++ installation manual</a></li>
+ <li><a href="https://gudhi.inria.fr/doc/latest/">C++ documentation</a></li>
+ <li><a href="https://gudhi.inria.fr/python/latest/installation.html">Python installation manual</a></li>
+ <li><a href="https://gudhi.inria.fr/python/latest/">Python documentation</a></li>
+ <li><a href="/utils/">Utilities</a></li>
+ <li><a href="/tutorials/">Tutorials</a></li>
+ </ul>
+ </li>
+ <li class="divider"></li>
+ <li><a href="/interfaces/">Interfaces</a></li>
+ <li class="divider"></li>
+ </ul>
+ </section>
+ </nav>
+ </div><!-- /#navigation -->
+ <!-- GUDHI website header BEGIN -->
+
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+
+<!--BEGIN TITLEAREA-->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 30px;">
+ <!--BEGIN DISABLE_INDEX-->
+ <!--BEGIN SEARCHENGINE-->
+ <td>$searchbox</td>
+ <!--END SEARCHENGINE-->
+ <!--END DISABLE_INDEX-->
+ </tr>
+ </tbody>
+</table>
+</div>
+<!--END TITLEAREA-->
+<!-- end header part -->
diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h
new file mode 100644
index 00000000..2e64bef8
--- /dev/null
+++ b/src/common/doc/installation.h
@@ -0,0 +1,262 @@
+/*! \page installation GUDHI installation
+ * \tableofcontents
+ * As GUDHI is a header only library, there is no need to install the library.
+ *
+ * Examples of GUDHI headers inclusion can be found in \ref utilities.
+ *
+ * \section compiling Compiling
+ * The library uses c++14 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.
+ *
+ * \subsection utilities Utilities and examples
+ * To build the utilities, run the following commands in a terminal:
+\verbatim cd /path-to-gudhi/
+mkdir build
+cd build/
+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 by modifying the
+ * cmake command as follows :
+\verbatim cmake -DWITH_GUDHI_EXAMPLE=ON ..
+make \endverbatim
+ * A list of utilities and examples is available <a href="examples.html">here</a>.
+ *
+ * \subsection libraryinstallation Installation
+ * To install the library (headers and activated utilities), run the following command in a terminal:
+ * \verbatim make install \endverbatim
+ * This action may require to be in the sudoer or administrator of the machine in function of the operating system and
+ * of <a href="https://cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html">CMAKE_INSTALL_PREFIX</a>.
+ *
+ * \subsection testsuites Test suites
+ * To test your build, run the following command in a terminal:
+ * \verbatim make test \endverbatim
+ *
+ * \subsection documentationgeneration Documentation
+ * To generate the documentation, <a target="_blank" href="http://www.doxygen.org/">Doxygen</a> is required.
+ * Run the following command in a terminal:
+\verbatim
+make doxygen
+# Documentation will be generated in the folder YYYY-MM-DD-hh-mm-ss_GUDHI_X.Y.Z/doc/html/
+# You can customize the directory name by calling `cmake -DUSER_VERSION_DIR=/my/custom/folder`
+\endverbatim
+ *
+ * \subsection helloworld Hello world !
+ * The <a target="_blank" href="https://github.com/GUDHI/hello-gudhi-world">Hello world for GUDHI</a>
+ * project is an example to help developers to make their own C++ project on top of the GUDHI library.
+ *
+ * \section optionallibrary Optional third-party library
+ * \subsection gmp GMP
+ * The multi-field persistent homology algorithm requires GMP which is a free library for arbitrary-precision
+ * arithmetic, operating on signed integers, rational numbers, and floating point numbers.
+ *
+ * The following example requires the <a target="_blank" href="http://gmplib.org/">GNU Multiple Precision Arithmetic
+ * Library</a> (GMP) and will not be built if GMP is not installed:
+ * \li <a href="_persistent_cohomology_2rips_multifield_persistence_8cpp-example.html">
+ * Persistent_cohomology/rips_multifield_persistence.cpp</a>
+ *
+ * Having GMP version 4.2 or higher installed is recommended.
+ *
+ * \subsection cgal CGAL
+ * Some GUDHI modules (cf. \ref main_page "modules list"), and few examples require CGAL, a C++ library that provides
+ * easy access to efficient and reliable geometric algorithms.
+ *
+ * \note There is no need to install CGAL, you can just <CODE>cmake . && make</CODE> CGAL (or even
+ * <CODE>cmake -DCGAL_HEADER_ONLY=ON .</CODE>), thereafter you will be able to compile
+ * GUDHI by calling <CODE>cmake -DCGAL_DIR=/your/path/to/CGAL-X.Y .. && make</CODE>
+ *
+ * The procedure to install this library according to
+ * your operating system is detailed here http://doc.cgal.org/latest/Manual/installation.html
+ *
+ * The following examples/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 version 4.11.0 or higher is not installed:
+ * \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>
+ * \li <a href="_witness_complex_2strong_witness_persistence_8cpp-example.html">
+ * Witness_complex/strong_witness_persistence.cpp</a>
+ * \li <a href="_witness_complex_2weak_witness_persistence_8cpp-example.html">
+ * Witness_complex/weak_witness_persistence.cpp</a>
+ * \li <a href="_witness_complex_2example_strong_witness_complex_off_8cpp-example.html">
+ * Witness_complex/example_strong_witness_complex_off.cpp</a>
+ * \li <a href="_witness_complex_2example_witness_complex_off_8cpp-example.html">
+ * Witness_complex/example_witness_complex_off.cpp</a>
+ * \li <a href="_witness_complex_2example_witness_complex_sphere_8cpp-example.html">
+ * Witness_complex/example_witness_complex_sphere.cpp</a>
+ * \li <a href="_alpha_complex_2_alpha_complex_from_off_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_off.cpp</a>
+ * \li <a href="_alpha_complex_2_alpha_complex_from_points_8cpp-example.html">
+ * 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="_persistent_cohomology_2custom_persistence_sort_8cpp-example.html">
+ * Persistent_cohomology/custom_persistence_sort.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="_bottleneck_distance_2bottleneck_basic_example_8cpp-example.html">
+ * Bottleneck_distance/bottleneck_basic_example.cpp</a>
+ * \li <a href="_bottleneck_distance_2bottleneck_read_file_8cpp-example.html">
+ * Bottleneck_distance/bottleneck_distance.cpp</a>
+ * \li <a href="_nerve__g_i_c_2_coord_g_i_c_8cpp-example.html">
+ * Nerve_GIC/CoordGIC.cpp</a>
+ * \li <a href="_nerve__g_i_c_2_func_g_i_c_8cpp-example.html">
+ * Nerve_GIC/FuncGIC.cpp</a>
+ * \li <a href="_nerve__g_i_c_2_nerve_8cpp-example.html">
+ * Nerve_GIC/Nerve.cpp</a>
+ * \li <a href="_nerve__g_i_c_2_voronoi_g_i_c_8cpp-example.html">
+ * Nerve_GIC/VoronoiGIC.cpp</a>
+ * \li <a href="_spatial_searching_2example_spatial_searching_8cpp-example.html">
+ * Spatial_searching/example_spatial_searching.cpp</a>
+ * \li <a href="_subsampling_2example_choose_n_farthest_points_8cpp-example.html">
+ * Subsampling/example_choose_n_farthest_points.cpp</a>
+ * \li <a href="_subsampling_2example_custom_kernel_8cpp-example.html">
+ * Subsampling/example_custom_kernel.cpp</a>
+ * \li <a href="_subsampling_2example_pick_n_random_points_8cpp-example.html">
+ * Subsampling/example_pick_n_random_points.cpp</a>
+ * \li <a href="_subsampling_2example_sparsify_point_set_8cpp-example.html">
+ * Subsampling/example_sparsify_point_set.cpp</a>
+ * \li <a href="_tangential_complex_2example_basic_8cpp-example.html">
+ * Tangential_complex/example_basic.cpp</a>
+ * \li <a href="_tangential_complex_2example_with_perturb_8cpp-example.html">
+ * Tangential_complex/example_with_perturb.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="_alpha_complex_2alpha_complex_3d_persistence_8cpp-example.html">
+ * Alpha_complex/alpha_complex_3d_persistence.cpp</a>
+ *
+ * \subsection eigen Eigen
+ * Some GUDHI modules (cf. \ref main_page "modules list"), and few examples require
+ * <a target="_blank" href="http://eigen.tuxfamily.org/">Eigen</a> is a C++ template library for linear algebra:
+ * matrices, vectors, numerical solvers, and related algorithms.
+ *
+ * The following examples/utilities require the <a target="_blank" href="http://eigen.tuxfamily.org/">Eigen</a> and will not be
+ * built if Eigen is not installed:
+ * \li <a href="_alpha_complex_2_alpha_complex_from_off_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_off.cpp</a>
+ * \li <a href="_alpha_complex_2_alpha_complex_from_points_8cpp-example.html">
+ * 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_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">
+ * Persistent_cohomology/custom_persistence_sort.cpp</a>
+ * \li <a href="_spatial_searching_2example_spatial_searching_8cpp-example.html">
+ * Spatial_searching/example_spatial_searching.cpp</a>
+ * \li <a href="_subsampling_2example_choose_n_farthest_points_8cpp-example.html">
+ * Subsampling/example_choose_n_farthest_points.cpp</a>
+ * \li <a href="_subsampling_2example_custom_kernel_8cpp-example.html">
+ * Subsampling/example_custom_kernel.cpp</a>
+ * \li <a href="_subsampling_2example_pick_n_random_points_8cpp-example.html">
+ * Subsampling/example_pick_n_random_points.cpp</a>
+ * \li <a href="_subsampling_2example_sparsify_point_set_8cpp-example.html">
+ * Subsampling/example_sparsify_point_set.cpp</a>
+ * \li <a href="_tangential_complex_2example_basic_8cpp-example.html">
+ * Tangential_complex/example_basic.cpp</a>
+ * \li <a href="_tangential_complex_2example_with_perturb_8cpp-example.html">
+ * Tangential_complex/example_with_perturb.cpp</a>
+ * \li <a href="_witness_complex_2strong_witness_persistence_8cpp-example.html">
+ * Witness_complex/strong_witness_persistence.cpp</a>
+ * \li <a href="_witness_complex_2weak_witness_persistence_8cpp-example.html">
+ * Witness_complex/weak_witness_persistence.cpp</a>
+ * \li <a href="_witness_complex_2example_strong_witness_complex_off_8cpp-example.html">
+ * Witness_complex/example_strong_witness_complex_off.cpp</a>
+ * \li <a href="_witness_complex_2example_witness_complex_off_8cpp-example.html">
+ * Witness_complex/example_witness_complex_off.cpp</a>
+ * \li <a href="_witness_complex_2example_witness_complex_sphere_8cpp-example.html">
+ * Witness_complex/example_witness_complex_sphere.cpp</a>
+ *
+ * \subsection tbb Threading Building Blocks
+ * <a target="_blank" href="https://www.threadingbuildingblocks.org/">Intel&reg; TBB</a> lets you easily write parallel
+ * C++ programs that take full advantage of multicore performance, that are portable and composable, and that have
+ * future-proof scalability.
+ *
+ * Having Intel&reg; TBB installed is recommended to parallelize and accelerate some GUDHI computations.
+ *
+ * The following examples/utilities are using Intel&reg; TBB if installed:
+ * \li <a href="_alpha_complex_2_alpha_complex_from_off_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_off.cpp</a>
+ * \li <a href="_alpha_complex_2_alpha_complex_from_points_8cpp-example.html">
+ * Alpha_complex/Alpha_complex_from_points.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_2alpha_complex_persistence_8cpp-example.html">
+ * Alpha_complex/alpha_complex_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">
+ * Bitmap_cubical_complex/periodic_cubical_complex_persistence.cpp</a>
+ * \li <a href="_bitmap_cubical_complex_2_random_bitmap_cubical_complex_8cpp-example.html">
+ * Bitmap_cubical_complex/Random_bitmap_cubical_complex.cpp</a>
+ * \li <a href="_nerve__g_i_c_2_coord_g_i_c_8cpp-example.html">
+ * Nerve_GIC/CoordGIC.cpp</a>
+ * \li <a href="_nerve__g_i_c_2_func_g_i_c_8cpp-example.html">
+ * Nerve_GIC/FuncGIC.cpp</a>
+ * \li <a href="_nerve__g_i_c_2_nerve_8cpp-example.html">
+ * Nerve_GIC/Nerve.cpp</a>
+ * \li <a href="_nerve__g_i_c_2_voronoi_g_i_c_8cpp-example.html">
+ * Nerve_GIC/VoronoiGIC.cpp</a>
+ * \li <a href="_simplex_tree_2simple_simplex_tree_8cpp-example.html">
+ * Simplex_tree/simple_simplex_tree.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>
+ * \li <a href="_simplex_tree_2simplex_tree_from_cliques_of_graph_8cpp-example.html">
+ * Simplex_tree/simplex_tree_from_cliques_of_graph.cpp</a>
+ * \li <a href="_simplex_tree_2graph_expansion_with_blocker_8cpp-example.html">
+ * Simplex_tree/graph_expansion_with_blocker.cpp</a>
+ * \li <a href="_persistent_cohomology_2alpha_complex_3d_persistence_8cpp-example.html">
+ * Persistent_cohomology/alpha_complex_3d_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2alpha_complex_persistence_8cpp-example.html">
+ * Persistent_cohomology/alpha_complex_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2rips_persistence_via_boundary_matrix_8cpp-example.html">
+ * Persistent_cohomology/rips_persistence_via_boundary_matrix.cpp</a>
+ * \li <a href="_persistent_cohomology_2persistence_from_file_8cpp-example.html">
+ * Persistent_cohomology/persistence_from_file.cpp</a>
+ * \li <a href="_persistent_cohomology_2persistence_from_simple_simplex_tree_8cpp-example.html">
+ * Persistent_cohomology/persistence_from_simple_simplex_tree.cpp</a>
+ * \li <a href="_persistent_cohomology_2plain_homology_8cpp-example.html">
+ * Persistent_cohomology/plain_homology.cpp</a>
+ * \li <a href="_persistent_cohomology_2rips_multifield_persistence_8cpp-example.html">
+ * 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_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">
+ * Rips_complex/example_one_skeleton_rips_from_points.cpp</a>
+ * \li <a href="_rips_complex_2example_rips_complex_from_off_file_8cpp-example.html">
+ * Rips_complex/example_rips_complex_from_off_file.cpp</a>
+ * \li <a href="_rips_complex_2rips_distance_matrix_persistence_8cpp-example.html">
+ * Rips_complex/rips_distance_matrix_persistence.cpp</a>
+ * \li <a href="_rips_complex_2rips_persistence_8cpp-example.html">
+ * Rips_complex/rips_persistence.cpp</a>
+ * \li <a href="_witness_complex_2strong_witness_persistence_8cpp-example.html">
+ * Witness_complex/strong_witness_persistence.cpp</a>
+ * \li <a href="_witness_complex_2weak_witness_persistence_8cpp-example.html">
+ * Witness_complex/weak_witness_persistence.cpp</a>
+ * \li <a href="_witness_complex_2example_nearest_landmark_table_8cpp-example.html">
+ * Witness_complex/example_nearest_landmark_table.cpp</a>
+ *
+ * \section Contributions Bug reports and contributions
+ * Please help us improving the quality of the GUDHI library. You may report bugs or suggestions to:
+ * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim
+ *
+ * GUDHI is open to external contributions. If you want to join our development team, please contact us.
+ *
+*/
+
+/*! \page Citation Acknowledging the GUDHI library
+ * We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use
+ * of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages.
+ * Feel free to contact us in case you have any question or remark on this topic.
+ *
+ * We provide \ref GudhiBibtex entries for the modules of the User and Reference Manual, as well as for publications
+ * directly related to the GUDHI library.
+ * \section GudhiBibtex GUDHI bibtex
+ * \verbinclude biblio/how_to_cite_gudhi.bib
+*/
diff --git a/src/common/doc/main_page.md b/src/common/doc/main_page.md
new file mode 100644
index 00000000..d8cbf97f
--- /dev/null
+++ b/src/common/doc/main_page.md
@@ -0,0 +1,391 @@
+[TOC]
+
+# The C++ library {#main_page}
+\image html "Gudhi_banner.png"
+<br><br><br><br>
+
+## Complexes {#Complexes}
+### Cubical complex
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "Cubical_complex_representation.png"
+ </td>
+ <td width="50%">
+ The cubical complex is an example of a structured complex useful in computational mathematics (specially
+ rigorous numerics) and image analysis.<br>
+ </td>
+ <td width="15%">
+ <b>Author:</b> Pawel Dlotko<br>
+ <b>Introduced in:</b> GUDHI 1.3.0<br>
+ <b>Copyright:</b> MIT<br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref cubical_complex
+ </td>
+ </tr>
+</table>
+
+### Simplicial complex
+
+#### Alpha complex
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "alpha_complex_representation.png"
+ </td>
+ <td width="50%">
+ Alpha complex is a simplicial complex constructed from the finite cells of a Delaunay Triangulation.<br>
+ 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.<br>
+ </td>
+ <td width="15%">
+ <b>Author:</b> Vincent Rouvreau<br>
+ <b>Introduced in:</b> GUDHI 1.3.0<br>
+ <b>Copyright:</b> MIT [(GPL v3)](../../licensing/)<br>
+ <b>Requires:</b> \ref eigen &ge; 3.1.0 and \ref cgal &ge; 4.11.0
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref alpha_complex
+ </td>
+ </tr>
+</table>
+
+#### ÄŚech complex
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "cech_complex_representation.png"
+ </td>
+ <td width="50%">
+ The ÄŚech complex is a simplicial complex constructed from a proximity graph.
+ The set of all simplices is filtered by the radius of their minimal enclosing ball.
+ </td>
+ <td width="15%">
+ <b>Author:</b> Vincent Rouvreau<br>
+ <b>Introduced in:</b> GUDHI 2.2.0<br>
+ <b>Copyright:</b> MIT [(GPL v3)](../../licensing/)<br>
+ <b>Includes:</b> [Miniball](https://people.inf.ethz.ch/gaertner/subdir/software/miniball.html)<br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref cech_complex
+ </td>
+ </tr>
+</table>
+
+#### Rips complex
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "rips_complex_representation.png"
+ </td>
+ <td width="50%">
+ Rips complex is a simplicial complex constructed from a one skeleton graph.<br>
+ The filtration value of each edge is computed from a user-given distance function and is inserted until a
+ user-given threshold value.<br>
+ This complex can be built from a point cloud and a distance function, or from a distance matrix.
+ </td>
+ <td width="15%">
+ <b>Author:</b> Cl&eacute;ment Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse<br>
+ <b>Introduced in:</b> GUDHI 2.0.0<br>
+ <b>Copyright:</b> MIT<br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref rips_complex
+ </td>
+ </tr>
+</table>
+
+#### Witness complex
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "Witness_complex_representation.png"
+ </td>
+ <td width="50%">
+ Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$.
+ The data structure is described in \cite boissonnatmariasimplextreealgorithmica .
+ </td>
+ <td width="15%">
+ <b>Author:</b> Siargey Kachanovich<br>
+ <b>Introduced in:</b> GUDHI 1.3.0<br>
+ <b>Copyright:</b> MIT ([GPL v3](../../licensing/) for Euclidean version)<br>
+ <b>Euclidean version requires:</b> \ref eigen &ge; 3.1.0 and \ref cgal &ge; 4.11.0
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref witness_complex
+ </td>
+ </tr>
+</table>
+
+### Cover Complexes
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "gicvisu.jpg"
+ </td>
+ <td width="50%">
+ Nerves and Graph Induced Complexes are cover complexes, i.e. simplicial complexes that provably contain
+ topological information about the input data. They can be computed with a cover of the
+ data, that comes i.e. from the preimage of a family of intervals covering the image
+ of a scalar-valued function defined on the data. <br>
+ </td>
+ <td width="15%">
+ <b>Author:</b> Mathieu Carri&egrave;re<br>
+ <b>Introduced in:</b> GUDHI 2.1.0<br>
+ <b>Copyright:</b> MIT [(GPL v3)](../../licensing/)<br>
+ <b>Requires:</b> \ref cgal &ge; 4.11.0
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref cover_complex
+ </td>
+ </tr>
+</table>
+
+## Data structures and basic operations {#DataStructuresAndBasicOperations}
+
+### Data structures
+
+#### Simplex tree
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "Simplex_tree_representation.png"
+ </td>
+ <td width="50%">
+ The simplex tree is an efficient and flexible
+ data structure for representing general (filtered) simplicial complexes. The data structure
+ is described in \cite boissonnatmariasimplextreealgorithmica .
+ </td>
+ <td width="15%">
+ <b>Author:</b> Cl&eacute;ment Maria<br>
+ <b>Introduced in:</b> GUDHI 1.0.0<br>
+ <b>Copyright:</b> MIT<br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref simplex_tree
+ </td>
+ </tr>
+</table>
+
+#### Skeleton blocker
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "ds_representation.png"
+ </td>
+ <td width="50%">
+ The Skeleton-Blocker data-structure proposes a light encoding for simplicial complexes by storing only an *implicit*
+ representation of its simplices \cite socg_blockers_2011,\cite blockers2012. Intuitively, it just stores the
+ 1-skeleton of a simplicial complex with a graph and the set of its "missing faces" that is very small in practice.
+ This data-structure handles all simplicial complexes operations such as simplex enumeration or simplex removal but
+ operations that are particularly efficient are operations that do not require simplex enumeration such as edge
+ iteration, link computation or simplex contraction.
+ </td>
+ <td width="15%">
+ <b>Author:</b> David Salinas<br>
+ <b>Introduced in:</b> GUDHI 1.1.0<br>
+ <b>Copyright:</b> MIT<br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref skbl
+ </td>
+ </tr>
+</table>
+
+#### Toplex Map
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "map.png"
+ </td>
+ <td width="50%">
+ The Toplex map data structure is composed firstly of a raw storage of toplices (the maximal simplices)
+ and secondly of a map which associate any vertex to a set of pointers toward all toplices
+ containing this vertex.
+ </td>
+ <td width="15%">
+ <b>Author:</b> Fran&ccedil;ois Godi<br>
+ <b>Introduced in:</b> GUDHI 2.1.0<br>
+ <b>Copyright:</b> MIT<br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref toplex_map
+ </td>
+ </tr>
+</table>
+
+### Basic operations
+
+#### Contraction
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "sphere_contraction_representation.png"
+ </td>
+ <td width="50%">
+ The purpose of this package is to offer a user-friendly interface for edge contraction simplification of huge
+ simplicial complexes. It uses the \ref skbl data-structure whose size remains small during simplification of most
+ used geometrical complexes of topological data analysis such as the Rips or the Delaunay complexes. In practice,
+ the size of this data-structure is even much lower than the total number of simplices.
+ </td>
+ <td width="15%">
+ <b>Author:</b> David Salinas<br>
+ <b>Introduced in:</b> GUDHI 1.1.0<br>
+ <b>Copyright:</b> MIT [(LGPL v3)](../../licensing/)<br>
+ <b>Requires:</b> \ref cgal &ge; 4.11.0
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref contr
+ </td>
+ </tr>
+</table>
+
+## Topological descriptors computation {#TopologicalDescriptorsComputation}
+
+### Persistent Cohomology
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "3DTorus_poch.png"
+ </td>
+ <td width="50%">
+ The theory of homology consists in attaching to a topological space a sequence of (homology) groups, capturing
+ global topological features like connected components, holes, cavities, etc. Persistent homology studies the
+ evolution -- birth, life and death -- of these features when the topological space is changing. Consequently, the
+ theory is essentially composed of three elements: topological spaces, their homology groups and an evolution
+ scheme.
+ Computation of persistent cohomology using the algorithm of \cite DBLP:journals/dcg/SilvaMV11 and
+ \cite DBLP:journals/corr/abs-1208-5018 and the Compressed Annotation Matrix implementation of
+ \cite DBLP:conf/esa/BoissonnatDM13 .
+ </td>
+ <td width="15%">
+ <b>Author:</b> Cl&eacute;ment Maria<br>
+ <b>Introduced in:</b> GUDHI 1.0.0<br>
+ <b>Copyright:</b> MIT<br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref persistent_cohomology
+ </td>
+ </tr>
+</table>
+
+## Manifold reconstruction {#ManifoldReconstruction}
+
+### Tangential complex
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "tc_examples.png"
+ </td>
+ <td width="50%">
+ A Tangential Delaunay complex is a <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a>
+ designed to reconstruct a \f$ k \f$-dimensional manifold embedded in \f$ d \f$-dimensional Euclidean space.
+ The input is a point sample coming from an unknown manifold.
+ The running time depends only linearly on the extrinsic dimension \f$ d \f$
+ and exponentially on the intrinsic dimension \f$ k \f$.
+ </td>
+ <td width="15%">
+ <b>Author:</b> Cl&eacute;ment Jamin<br>
+ <b>Introduced in:</b> GUDHI 2.0.0<br>
+ <b>Copyright:</b> MIT [(GPL v3)](../../licensing/)<br>
+ <b>Requires:</b> \ref eigen &ge; 3.1.0 and \ref cgal &ge; 4.11.0
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref tangential_complex
+ </td>
+ </tr>
+</table>
+
+## Topological descriptors tools {#TopologicalDescriptorsTools}
+
+### Bottleneck distance
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "perturb_pd.png"
+ </td>
+ <td width="50%">
+ Bottleneck distance measures the similarity between two persistence diagrams.
+ It's the shortest distance b for which there exists a perfect matching between
+ the points of the two diagrams (+ all the diagonal points) such that
+ any couple of matched points are at distance at most b,
+ where the distance between points is the sup norm in \f$\mathbb{R}^2\f$
+ (not the Euclidean distance).
+ </td>
+ <td width="15%">
+ <b>Author:</b> Fran&ccedil;ois Godi<br>
+ <b>Introduced in:</b> GUDHI 2.0.0<br>
+ <b>Copyright:</b> MIT [(GPL v3)](../../licensing/)<br>
+ <b>Requires:</b> \ref cgal &ge; 4.11.0
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref bottleneck_distance
+ </td>
+ </tr>
+</table>
+
+### Persistence representations
+
+<table>
+ <tr>
+ <td width="35%" rowspan=2>
+ \image html "average_landscape.png"
+ </td>
+ <td width="50%">
+ It contains implementation of various representations of persistence diagrams; diagrams themselves, persistence
+ landscapes (rigorous and grid version), persistence heat maps, vectors and others. It implements basic
+ functionalities which are necessary to use persistence in statistics and machine learning.
+ </td>
+ <td width="15%">
+ <b>Author:</b> Pawel Dlotko<br>
+ <b>Introduced in:</b> GUDHI 2.1.0<br>
+ <b>Copyright:</b> MIT<br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 height="25">
+ <b>User manual:</b> \ref Persistence_representations
+ </td>
+ </tr>
+</table>
diff --git a/src/common/doc/offline_header.html b/src/common/doc/offline_header.html
new file mode 100644
index 00000000..6a02a895
--- /dev/null
+++ b/src/common/doc/offline_header.html
@@ -0,0 +1,41 @@
+<!-- HTML header for doxygen 1.8.6-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!-- GUDHI website : class="no-js" lang="en" is necessary -->
+<html xmlns="http://www.w3.org/1999/xhtml" class="no-js" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen $doxygenversion"/>
+<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
+<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
+<!-- GUDHI website css for header END -->
+<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath^jquery.js"></script>
+<script type="text/javascript" src="$relpath^dynsections.js"></script>
+$treeview
+$search
+$mathjax
+<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
+$extrastylesheet
+</head>
+<body>
+
+
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+
+<!--BEGIN TITLEAREA-->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 30px;">
+ <!--BEGIN DISABLE_INDEX-->
+ <!--BEGIN SEARCHENGINE-->
+ <td>$searchbox</td>
+ <!--END SEARCHENGINE-->
+ <!--END DISABLE_INDEX-->
+ </tr>
+ </tbody>
+</table>
+</div>
+<!--END TITLEAREA-->
+<!-- end header part -->
diff --git a/src/common/doc/stylesheet.css b/src/common/doc/stylesheet.css
new file mode 100644
index 00000000..1df177a4
--- /dev/null
+++ b/src/common/doc/stylesheet.css
@@ -0,0 +1,1367 @@
+/* The standard CSS for doxygen 1.8.6 */
+
+body, table, div, p, dl {
+ font: 400 14px/22px Roboto,sans-serif;
+}
+
+/* @group Heading Levels */
+
+h1.groupheader {
+ font-size: 150%;
+}
+
+.title {
+ font: 400 14px/28px Roboto,sans-serif;
+ font-size: 150%;
+ font-weight: bold;
+ margin: 10px 2px;
+}
+
+h2.groupheader {
+ border-bottom: 1px solid #879ECB;
+ color: #354C7B;
+ font-size: 150%;
+ font-weight: normal;
+ margin-top: 1.75em;
+ padding-top: 8px;
+ padding-bottom: 4px;
+ width: 100%;
+}
+
+h3.groupheader {
+ font-size: 100%;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ -webkit-transition: text-shadow 0.5s linear;
+ -moz-transition: text-shadow 0.5s linear;
+ -ms-transition: text-shadow 0.5s linear;
+ -o-transition: text-shadow 0.5s linear;
+ transition: text-shadow 0.5s linear;
+ margin-right: 15px;
+}
+
+h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
+ text-shadow: 0 0 15px cyan;
+}
+
+dt {
+ font-weight: bold;
+}
+
+div.multicol {
+ -moz-column-gap: 1em;
+ -webkit-column-gap: 1em;
+ -moz-column-count: 3;
+ -webkit-column-count: 3;
+}
+
+p.startli, p.startdd {
+ margin-top: 2px;
+}
+
+p.starttd {
+ margin-top: 0px;
+}
+
+p.endli {
+ margin-bottom: 0px;
+}
+
+p.enddd {
+ margin-bottom: 4px;
+}
+
+p.endtd {
+ margin-bottom: 2px;
+}
+
+/* @end */
+
+caption {
+ font-weight: bold;
+}
+
+span.legend {
+ font-size: 70%;
+ text-align: center;
+}
+
+h3.version {
+ font-size: 90%;
+ text-align: center;
+}
+
+div.qindex, div.navtab{
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+}
+
+div.qindex, div.navpath {
+ width: 100%;
+ line-height: 140%;
+}
+
+div.navtab {
+ margin-right: 15px;
+}
+
+/* @group Link Styling */
+
+a {
+ color: #3D578C;
+ font-weight: normal;
+ text-decoration: none;
+}
+
+.contents a:visited {
+ color: #4665A2;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+a.qindex {
+ font-weight: bold;
+}
+
+a.qindexHL {
+ font-weight: bold;
+ background-color: #9CAFD4;
+ color: #ffffff;
+ border: 1px double #869DCA;
+}
+
+.contents a.qindexHL:visited {
+ color: #ffffff;
+}
+
+a.el {
+ font-weight: bold;
+}
+
+a.elRef {
+}
+
+a.code, a.code:visited, a.line, a.line:visited {
+ color: #4665A2;
+}
+
+a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
+ color: #4665A2;
+}
+
+/* @end */
+
+dl.el {
+ margin-left: -1cm;
+}
+
+pre.fragment {
+ border: 1px solid #C4CFE5;
+ background-color: #FBFCFD;
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+ overflow: auto;
+ word-wrap: break-word;
+ font-size: 9pt;
+ line-height: 125%;
+ font-family: monospace, fixed;
+ font-size: 105%;
+}
+
+div.fragment {
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+ background-color: #FBFCFD;
+ border: 1px solid #C4CFE5;
+}
+
+div.line {
+ font-family: monospace, fixed;
+ font-size: 13px;
+ min-height: 13px;
+ line-height: 1.0;
+ text-wrap: unrestricted;
+ white-space: -moz-pre-wrap; /* Moz */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ white-space: pre-wrap; /* CSS3 */
+ word-wrap: break-word; /* IE 5.5+ */
+ text-indent: -53px;
+ padding-left: 53px;
+ padding-bottom: 0px;
+ margin: 0px;
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+div.line.glow {
+ background-color: cyan;
+ box-shadow: 0 0 10px cyan;
+}
+
+
+span.lineno {
+ padding-right: 4px;
+ text-align: right;
+ border-right: 2px solid #0F0;
+ background-color: #E8E8E8;
+ white-space: pre;
+}
+span.lineno a {
+ background-color: #D8D8D8;
+}
+
+span.lineno a:hover {
+ background-color: #C8C8C8;
+}
+
+div.ah {
+ background-color: black;
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 3px;
+ margin-top: 3px;
+ padding: 0.2em;
+ border: solid thin #333;
+ border-radius: 0.5em;
+ -webkit-border-radius: .5em;
+ -moz-border-radius: .5em;
+ box-shadow: 2px 2px 3px #999;
+ -webkit-box-shadow: 2px 2px 3px #999;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
+ background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000);
+}
+
+div.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ font-weight: bold;
+}
+
+div.groupText {
+ margin-left: 16px;
+ font-style: italic;
+}
+
+body {
+ background-color: white;
+ color: black;
+ margin: 0;
+}
+
+div.contents {
+ margin-top: 10px;
+ margin-left: 12px;
+ margin-right: 8px;
+}
+
+td.indexkey {
+ background-color: #EBEFF6;
+ font-weight: bold;
+ border: 1px solid #C4CFE5;
+ margin: 2px 0px 2px 0;
+ padding: 2px 10px;
+ white-space: nowrap;
+ vertical-align: top;
+}
+
+td.indexvalue {
+ background-color: #EBEFF6;
+ border: 1px solid #C4CFE5;
+ padding: 2px 10px;
+ margin: 2px 0px;
+}
+
+tr.memlist {
+ background-color: #EEF1F7;
+}
+
+p.formulaDsp {
+ text-align: center;
+}
+
+img.formulaDsp {
+
+}
+
+img.formulaInl {
+ vertical-align: middle;
+}
+
+div.center {
+ text-align: center;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+}
+
+div.center img {
+ border: 0px;
+}
+
+address.footer {
+ text-align: right;
+ padding-right: 12px;
+}
+
+img.footer {
+ border: 0px;
+ vertical-align: middle;
+}
+
+/* @group Code Colorization */
+
+span.keyword {
+ color: #008000
+}
+
+span.keywordtype {
+ color: #604020
+}
+
+span.keywordflow {
+ color: #e08000
+}
+
+span.comment {
+ color: #800000
+}
+
+span.preprocessor {
+ color: #806020
+}
+
+span.stringliteral {
+ color: #002080
+}
+
+span.charliteral {
+ color: #008080
+}
+
+span.vhdldigit {
+ color: #ff00ff
+}
+
+span.vhdlchar {
+ color: #000000
+}
+
+span.vhdlkeyword {
+ color: #700070
+}
+
+span.vhdllogic {
+ color: #ff0000
+}
+
+blockquote {
+ background-color: #F7F8FB;
+ border-left: 2px solid #9CAFD4;
+ margin: 0 24px 0 4px;
+ padding: 0 12px 0 16px;
+}
+
+/* @end */
+
+/*
+.search {
+ color: #003399;
+ font-weight: bold;
+}
+
+form.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+
+input.search {
+ font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+*/
+
+td.tiny {
+ font-size: 75%;
+}
+
+.dirtab {
+ padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #A3B4D7;
+}
+
+th.dirtab {
+ background: #EBEFF6;
+ font-weight: bold;
+}
+
+hr {
+ height: 0px;
+ border: none;
+ border-top: 1px solid #4A6AAA;
+}
+
+hr.footer {
+ height: 1px;
+}
+
+/* @group Member Descriptions */
+
+table.memberdecls {
+ border-spacing: 0px;
+ padding: 0px;
+}
+
+.memberdecls td, .fieldtable tr {
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+.memberdecls td.glow, .fieldtable tr.glow {
+ background-color: cyan;
+ box-shadow: 0 0 15px cyan;
+}
+
+.mdescLeft, .mdescRight,
+.memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+ background-color: #F9FAFC;
+ border: none;
+ margin: 4px;
+ padding: 1px 0 0 8px;
+}
+
+.mdescLeft, .mdescRight {
+ padding: 0px 8px 4px 8px;
+ color: #555;
+}
+
+.memSeparator {
+ border-bottom: 1px solid #DEE4F0;
+ line-height: 1px;
+ margin: 0px;
+ padding: 0px;
+}
+
+.memItemLeft, .memTemplItemLeft {
+ white-space: nowrap;
+}
+
+.memItemRight {
+ width: 100%;
+}
+
+.memTemplParams {
+ color: #4665A2;
+ white-space: nowrap;
+ font-size: 80%;
+}
+
+/* @end */
+
+/* @group Member Details */
+
+/* Styles for detailed member documentation */
+
+.memtemplate {
+ font-size: 80%;
+ color: #4665A2;
+ font-weight: normal;
+ margin-left: 9px;
+}
+
+.memnav {
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+
+.mempage {
+ width: 100%;
+}
+
+.memitem {
+ padding: 0;
+ margin-bottom: 10px;
+ margin-right: 5px;
+ -webkit-transition: box-shadow 0.5s linear;
+ -moz-transition: box-shadow 0.5s linear;
+ -ms-transition: box-shadow 0.5s linear;
+ -o-transition: box-shadow 0.5s linear;
+ transition: box-shadow 0.5s linear;
+ display: table !important;
+ width: 100%;
+}
+
+.memitem.glow {
+ box-shadow: 0 0 15px cyan;
+}
+
+.memname {
+ font-weight: bold;
+ margin-left: 6px;
+}
+
+.memname td {
+ vertical-align: bottom;
+}
+
+.memproto, dl.reflist dt {
+ border-top: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 0px 6px 0px;
+ color: #253555;
+ font-weight: bold;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ /* opera specific markup */
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ /* firefox specific markup */
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-topleft: 4px;
+ /* webkit specific markup */
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ -webkit-border-top-right-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+
+}
+
+.memdoc, dl.reflist dd {
+ border-bottom: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 10px 2px 10px;
+ background-color: #FBFCFD;
+ border-top-width: 0;
+ background-image:url('nav_g.png');
+ background-repeat:repeat-x;
+ background-color: #FFFFFF;
+ /* opera specific markup */
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ /* firefox specific markup */
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-bottomright: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ /* webkit specific markup */
+ -webkit-border-bottom-left-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+dl.reflist dt {
+ padding: 5px;
+}
+
+dl.reflist dd {
+ margin: 0px 0px 10px 0px;
+ padding: 5px;
+}
+
+.paramkey {
+ text-align: right;
+}
+
+.paramtype {
+ white-space: nowrap;
+}
+
+.paramname {
+ color: #602020;
+ white-space: nowrap;
+}
+.paramname em {
+ font-style: normal;
+}
+.paramname code {
+ line-height: 14px;
+}
+
+.params, .retval, .exception, .tparams {
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+.params .paramname, .retval .paramname {
+ font-weight: bold;
+ vertical-align: top;
+}
+
+.params .paramtype {
+ font-style: italic;
+ vertical-align: top;
+}
+
+.params .paramdir {
+ font-family: "courier new",courier,monospace;
+ vertical-align: top;
+}
+
+table.mlabels {
+ border-spacing: 0px;
+}
+
+td.mlabels-left {
+ width: 100%;
+ padding: 0px;
+}
+
+td.mlabels-right {
+ vertical-align: bottom;
+ padding: 0px;
+ white-space: nowrap;
+}
+
+span.mlabels {
+ margin-left: 8px;
+}
+
+span.mlabel {
+ background-color: #728DC1;
+ border-top:1px solid #5373B4;
+ border-left:1px solid #5373B4;
+ border-right:1px solid #C4CFE5;
+ border-bottom:1px solid #C4CFE5;
+ text-shadow: none;
+ color: white;
+ margin-right: 4px;
+ padding: 2px 3px;
+ border-radius: 3px;
+ font-size: 7pt;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+
+
+/* @end */
+
+/* these are for tree view when not used as main index */
+
+div.directory {
+ margin: 10px 0px;
+ border-top: 1px solid #A8B8D9;
+ border-bottom: 1px solid #A8B8D9;
+ width: 100%;
+}
+
+.directory table {
+ border-collapse:collapse;
+}
+
+.directory td {
+ margin: 0px;
+ padding: 0px;
+ vertical-align: top;
+}
+
+.directory td.entry {
+ white-space: nowrap;
+ padding-right: 6px;
+ padding-top: 3px;
+}
+
+.directory td.entry a {
+ outline:none;
+}
+
+.directory td.entry a img {
+ border: none;
+}
+
+.directory td.desc {
+ width: 100%;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 3px;
+ border-left: 1px solid rgba(0,0,0,0.05);
+}
+
+.directory tr.even {
+ padding-left: 6px;
+ background-color: #F7F8FB;
+}
+
+.directory img {
+ vertical-align: -30%;
+}
+
+.directory .levels {
+ white-space: nowrap;
+ width: 100%;
+ text-align: right;
+ font-size: 9pt;
+}
+
+.directory .levels span {
+ cursor: pointer;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: #3D578C;
+}
+
+div.dynheader {
+ margin-top: 8px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+address {
+ font-style: normal;
+ color: #2A3D61;
+}
+
+table.doxtable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.doxtable td, table.doxtable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.doxtable th {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+table.fieldtable {
+ /*width: 100%;*/
+ margin-bottom: 10px;
+ border: 1px solid #A8B8D9;
+ border-spacing: 0px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+ box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+}
+
+.fieldtable td, .fieldtable th {
+ padding: 3px 7px 2px;
+}
+
+.fieldtable td.fieldtype, .fieldtable td.fieldname {
+ white-space: nowrap;
+ border-right: 1px solid #A8B8D9;
+ border-bottom: 1px solid #A8B8D9;
+ vertical-align: top;
+}
+
+.fieldtable td.fieldname {
+ padding-top: 3px;
+}
+
+.fieldtable td.fielddoc {
+ border-bottom: 1px solid #A8B8D9;
+ /*width: 100%;*/
+}
+
+.fieldtable td.fielddoc p:first-child {
+ margin-top: 0px;
+}
+
+.fieldtable td.fielddoc p:last-child {
+ margin-bottom: 2px;
+}
+
+.fieldtable tr:last-child td {
+ border-bottom: none;
+}
+
+.fieldtable th {
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ font-size: 90%;
+ color: #253555;
+ padding-bottom: 4px;
+ padding-top: 5px;
+ text-align:left;
+ -moz-border-radius-topleft: 4px;
+ -moz-border-radius-topright: 4px;
+ -webkit-border-top-left-radius: 4px;
+ -webkit-border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ border-bottom: 1px solid #A8B8D9;
+}
+
+
+.tabsearch {
+ top: 0px;
+ left: 10px;
+ height: 36px;
+ background-image: url('tab_b.png');
+ z-index: 101;
+ overflow: hidden;
+ font-size: 13px;
+}
+
+.navpath ul
+{
+ font-size: 11px;
+ background-image:url('tab_b.png');
+ background-repeat:repeat-x;
+ background-position: 0 -5px;
+ height:30px;
+ line-height:30px;
+ color:#8AA0CC;
+ border:solid 1px #C2CDE4;
+ overflow:hidden;
+ margin:0px;
+ padding:0px;
+}
+
+.navpath li
+{
+ list-style-type:none;
+ float:left;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:url('bc_s.png');
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+}
+
+.navpath li.navelem a
+{
+ height:32px;
+ display:block;
+ text-decoration: none;
+ outline: none;
+ color: #283A5D;
+ font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ text-decoration: none;
+}
+
+.navpath li.navelem a:hover
+{
+ color:#6884BD;
+}
+
+.navpath li.footer
+{
+ list-style-type:none;
+ float:right;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:none;
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+ font-size: 8pt;
+}
+
+
+div.summary
+{
+ float: right;
+ font-size: 8pt;
+ padding-right: 5px;
+ width: 50%;
+ text-align: right;
+}
+
+div.summary a
+{
+ white-space: nowrap;
+}
+
+div.ingroups
+{
+ font-size: 8pt;
+ width: 50%;
+ text-align: left;
+}
+
+div.ingroups a
+{
+ white-space: nowrap;
+}
+
+div.header
+{
+ background-image:url('nav_h.png');
+ background-repeat:repeat-x;
+ background-color: #F9FAFC;
+ margin: 0px;
+ border-bottom: 1px solid #C4CFE5;
+}
+
+div.headertitle
+{
+ padding: 5px 5px 5px 10px;
+}
+
+dl
+{
+ padding: 0 0 0 10px;
+}
+
+/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */
+dl.section
+{
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+dl.note
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #D0C000;
+}
+
+dl.warning, dl.attention
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #FF0000;
+}
+
+dl.pre, dl.post, dl.invariant
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00D000;
+}
+
+dl.deprecated
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #505050;
+}
+
+dl.todo
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00C0E0;
+}
+
+dl.test
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #3030E0;
+}
+
+dl.bug
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #C08050;
+}
+
+dl.section dd {
+ margin-bottom: 6px;
+}
+
+
+#projectlogo
+{
+ text-align: center;
+ vertical-align: bottom;
+ border-collapse: separate;
+}
+
+#projectlogo img
+{
+ border: 0px none;
+}
+
+#projectname
+{
+ border: 0px none;
+ font: 300% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 2px 0px;
+}
+
+#projectbrief
+{
+ font: 60% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#projectnumber
+{
+ font: 80% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#titlearea
+{
+ padding: 0px;
+ margin: 0px;
+ width: 100%;
+ border-bottom: 1px solid #5373B4;
+}
+
+.image
+{
+ text-align: center;
+}
+
+.dotgraph
+{
+ text-align: center;
+}
+
+.mscgraph
+{
+ text-align: center;
+}
+
+.diagraph
+{
+ text-align: center;
+}
+
+.caption
+{
+ font-weight: bold;
+}
+
+div.zoom
+{
+ border: 1px solid #90A5CE;
+}
+
+dl.citelist {
+ margin-bottom:50px;
+}
+
+dl.citelist dt {
+ color:#334975;
+ float:left;
+ font-weight:bold;
+ margin-right:10px;
+ padding:5px;
+}
+
+dl.citelist dd {
+ margin:2px 0;
+ padding:5px 0;
+}
+
+div.toc {
+ padding: 14px 25px;
+ background-color: #F4F6FA;
+ border: 1px solid #D8DFEE;
+ border-radius: 7px 7px 7px 7px;
+ float: right;
+ height: auto;
+ margin: 0 20px 10px 10px;
+ width: 200px;
+}
+
+div.toc li {
+ background: url("bdwn.png") no-repeat scroll 0 5px transparent;
+ font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;
+ margin-top: 5px;
+ padding-left: 10px;
+ padding-top: 2px;
+}
+
+div.toc h3 {
+ font: bold 12px/1.2 Arial,FreeSans,sans-serif;
+ color: #4665A2;
+ border-bottom: 0 none;
+ margin: 0;
+}
+
+div.toc ul {
+ list-style: none outside none;
+ border: medium none;
+ padding: 0px;
+}
+
+div.toc li.level1 {
+ margin-left: 0px;
+}
+
+div.toc li.level2 {
+ margin-left: 15px;
+}
+
+div.toc li.level3 {
+ margin-left: 30px;
+}
+
+div.toc li.level4 {
+ margin-left: 45px;
+}
+
+.inherit_header {
+ font-weight: bold;
+ color: gray;
+ cursor: pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.inherit_header td {
+ padding: 6px 0px 2px 5px;
+}
+
+.inherit {
+ display: none;
+}
+
+tr.heading h2 {
+ margin-top: 12px;
+ margin-bottom: 4px;
+}
+
+/* tooltip related style info */
+
+.ttc {
+ position: absolute;
+ display: none;
+}
+
+#powerTip {
+ cursor: default;
+ white-space: nowrap;
+ background-color: white;
+ border: 1px solid gray;
+ border-radius: 4px 4px 4px 4px;
+ box-shadow: 1px 1px 7px gray;
+ display: none;
+ font-size: smaller;
+ max-width: 80%;
+ opacity: 0.9;
+ padding: 1ex 1em 1em;
+ position: absolute;
+ z-index: 2147483647;
+}
+
+#powerTip div.ttdoc {
+ color: grey;
+ font-style: italic;
+}
+
+#powerTip div.ttname a {
+ font-weight: bold;
+}
+
+#powerTip div.ttname {
+ font-weight: bold;
+}
+
+#powerTip div.ttdeci {
+ color: #006318;
+}
+
+#powerTip div {
+ margin: 0px;
+ padding: 0px;
+ font: 12px/16px Roboto,sans-serif;
+}
+
+#powerTip:before, #powerTip:after {
+ content: "";
+ position: absolute;
+ margin: 0px;
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.w:after, #powerTip.w:before,
+#powerTip.e:after, #powerTip.e:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.nw:after, #powerTip.nw:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+}
+
+#powerTip.n:after, #powerTip.s:after,
+#powerTip.w:after, #powerTip.e:after,
+#powerTip.nw:after, #powerTip.ne:after,
+#powerTip.sw:after, #powerTip.se:after {
+ border-color: rgba(255, 255, 255, 0);
+}
+
+#powerTip.n:before, #powerTip.s:before,
+#powerTip.w:before, #powerTip.e:before,
+#powerTip.nw:before, #powerTip.ne:before,
+#powerTip.sw:before, #powerTip.se:before {
+ border-color: rgba(128, 128, 128, 0);
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.nw:after, #powerTip.nw:before {
+ top: 100%;
+}
+
+#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after {
+ border-top-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+#powerTip.n:before {
+ border-top-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+#powerTip.n:after, #powerTip.n:before {
+ left: 50%;
+}
+
+#powerTip.nw:after, #powerTip.nw:before {
+ right: 14px;
+}
+
+#powerTip.ne:after, #powerTip.ne:before {
+ left: 14px;
+}
+
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ bottom: 100%;
+}
+
+#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after {
+ border-bottom-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+
+#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before {
+ border-bottom-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+
+#powerTip.s:after, #powerTip.s:before {
+ left: 50%;
+}
+
+#powerTip.sw:after, #powerTip.sw:before {
+ right: 14px;
+}
+
+#powerTip.se:after, #powerTip.se:before {
+ left: 14px;
+}
+
+#powerTip.e:after, #powerTip.e:before {
+ left: 100%;
+}
+#powerTip.e:after {
+ border-left-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.e:before {
+ border-left-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+#powerTip.w:after, #powerTip.w:before {
+ right: 100%;
+}
+#powerTip.w:after {
+ border-right-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.w:before {
+ border-right-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+@media print
+{
+ #top { display: none; }
+ #side-nav { display: none; }
+ #nav-path { display: none; }
+ body { overflow:visible; }
+ h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
+ .summary { display: none; }
+ .memitem { page-break-inside: avoid; }
+ #doc-content
+ {
+ margin-left:0 !important;
+ height:auto !important;
+ width:auto !important;
+ overflow:inherit;
+ display:inline;
+ }
+}
+
diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt
new file mode 100644
index 00000000..583a0027
--- /dev/null
+++ b/src/common/example/CMakeLists.txt
@@ -0,0 +1,30 @@
+project(Common_examples)
+
+add_executable ( vector_double_off_reader example_vector_double_points_off_reader.cpp )
+target_link_libraries(vector_double_off_reader ${CGAL_LIBRARY})
+file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+add_test(NAME Common_example_vector_double_off_reader COMMAND $<TARGET_FILE:vector_double_off_reader>
+ "alphacomplexdoc.off")
+
+if (DIFF_PATH)
+ # Do not forget to copy test results files in current binary dir
+ file(COPY "vectordoubleoffreader_result.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+
+ add_test(Common_example_vector_double_off_reader_diff_files ${DIFF_PATH}
+ ${CMAKE_CURRENT_BINARY_DIR}/vectordoubleoffreader_result.txt ${CMAKE_CURRENT_BINARY_DIR}/alphacomplexdoc.off.txt)
+endif()
+
+if(NOT CGAL_VERSION VERSION_LESS 4.11.0)
+ add_executable ( cgal_3D_off_reader example_CGAL_3D_points_off_reader.cpp )
+ target_link_libraries(cgal_3D_off_reader ${CGAL_LIBRARY})
+ add_test(NAME Common_example_vector_cgal_3D_off_reader COMMAND $<TARGET_FILE:cgal_3D_off_reader>
+ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off")
+endif()
+
+# requires CGAL and Eigen3
+if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ add_executable ( cgal_off_reader example_CGAL_points_off_reader.cpp )
+ target_link_libraries(cgal_off_reader ${CGAL_LIBRARY})
+ add_test(NAME Common_example_vector_cgal_off_reader COMMAND $<TARGET_FILE:cgal_off_reader>
+ "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off")
+endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
diff --git a/src/common/example/cgal3Doffreader_result.txt b/src/common/example/cgal3Doffreader_result.txt
new file mode 100644
index 00000000..f992c8e3
--- /dev/null
+++ b/src/common/example/cgal3Doffreader_result.txt
@@ -0,0 +1,8 @@
+Point[1] = (0.959535, -0.418347, 0.302237)
+Point[2] = (2.16795, 1.85348, -0.52312)
+Point[3] = (-2.38753, -1.50911, -0.565889)
+Point[4] = (-2.70428, -1.25688, 0.188394)
+Point[5] = (-1.22932, -1.64337, -0.998632)
+...
+Point[300] = (-0.56244, 2.6018, -0.749591)
+
diff --git a/src/common/example/example_CGAL_3D_points_off_reader.cpp b/src/common/example/example_CGAL_3D_points_off_reader.cpp
new file mode 100644
index 00000000..4658d8d5
--- /dev/null
+++ b/src/common/example/example_CGAL_3D_points_off_reader.cpp
@@ -0,0 +1,41 @@
+#include <gudhi/Points_3D_off_io.h>
+
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
+using Point_3 = Kernel::Point_3;
+
+void usage(char * const progName) {
+ std::cerr << "Usage: " << progName << " inputFile.off" << std::endl;
+ exit(-1);
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ std::string off_input_file(argv[1]);
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_3D_off_reader<Point_3> off_reader(off_input_file);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << off_input_file << std::endl;
+ usage(argv[0]);
+ }
+
+ // Retrieve the triangulation
+ std::vector<Point_3> point_cloud = off_reader.get_point_cloud();
+
+ int n {};
+ for (auto point : point_cloud) {
+ ++n;
+ std::cout << "Point[" << n << "] = (" << point[0] << ", " << point[1] << ", " << point[2] << ")\n";
+ }
+ return 0;
+}
diff --git a/src/common/example/example_CGAL_points_off_reader.cpp b/src/common/example/example_CGAL_points_off_reader.cpp
new file mode 100644
index 00000000..f45683a5
--- /dev/null
+++ b/src/common/example/example_CGAL_points_off_reader.cpp
@@ -0,0 +1,46 @@
+#include <gudhi/Points_off_io.h>
+
+// For CGAL points type in dimension d
+// cf. http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Point__d.html
+#include <CGAL/Epick_d.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using Kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >;
+using Point_d = Kernel::Point_d;
+
+void usage(char * const progName) {
+ std::cerr << "Usage: " << progName << " inputFile.off" << std::endl;
+ exit(-1);
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ std::string off_input_file(argv[1]);
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_off_reader<Point_d> off_reader(off_input_file);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << off_input_file << std::endl;
+ usage(argv[0]);
+ }
+
+ // Retrieve the triangulation
+ std::vector<Point_d> point_cloud = off_reader.get_point_cloud();
+
+ int n {};
+ for (auto point : point_cloud) {
+ std::cout << "Point[" << n << "] = ";
+ for (std::size_t i {0}; i < point.size(); i++)
+ std::cout << point[i] << " ";
+ std::cout << "\n";
+ ++n;
+ }
+ return 0;
+}
diff --git a/src/common/example/example_vector_double_points_off_reader.cpp b/src/common/example/example_vector_double_points_off_reader.cpp
new file mode 100644
index 00000000..5093da85
--- /dev/null
+++ b/src/common/example/example_vector_double_points_off_reader.cpp
@@ -0,0 +1,43 @@
+#include <gudhi/Points_off_io.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using Point_d = std::vector<double>;
+
+void usage(char * const progName) {
+ std::cerr << "Usage: " << progName << " inputFile.off" << std::endl;
+ exit(-1);
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ std::string off_input_file(argv[1]);
+ // Read the OFF file (input file name given as parameter) and triangulate points
+ Gudhi::Points_off_reader<Point_d> off_reader(off_input_file);
+ // Check the read operation was correct
+ if (!off_reader.is_valid()) {
+ std::cerr << "Unable to read file " << off_input_file << std::endl;
+ usage(argv[0]);
+ }
+
+ // Retrieve the triangulation
+ std::vector<Point_d> point_cloud = off_reader.get_point_cloud();
+
+ std::ofstream output_file(off_input_file + ".txt");
+ int n {0};
+ for (auto point : point_cloud) {
+ output_file << "Point[" << n << "] = ";
+ for (std::size_t i {0}; i < point.size(); i++)
+ output_file << point[i] << " ";
+ output_file << "\n";
+ ++n;
+ }
+ output_file.close();
+ return 0;
+}
diff --git a/src/common/example/vectordoubleoffreader_result.txt b/src/common/example/vectordoubleoffreader_result.txt
new file mode 100644
index 00000000..b399425a
--- /dev/null
+++ b/src/common/example/vectordoubleoffreader_result.txt
@@ -0,0 +1,7 @@
+Point[0] = 1 1 0
+Point[1] = 7 0 0
+Point[2] = 4 6 0
+Point[3] = 9 6 0
+Point[4] = 0 14 0
+Point[5] = 2 19 0
+Point[6] = 9 17 0
diff --git a/src/common/include/gudhi/Clock.h b/src/common/include/gudhi/Clock.h
new file mode 100644
index 00000000..00ab2f27
--- /dev/null
+++ b/src/common/include/gudhi/Clock.h
@@ -0,0 +1,77 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): David Salinas
+ *
+ * Copyright (C) 2014 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef CLOCK_H_
+#define CLOCK_H_
+
+#include <iostream>
+#include <string>
+#include <chrono>
+
+namespace Gudhi {
+
+class Clock {
+ public:
+ // Construct and start the timer
+ Clock(const std::string& msg_ = std::string())
+ : startTime(std::chrono::system_clock::now()),
+ end_called(false),
+ msg(msg_) { }
+
+ // Restart the timer
+ void begin() const {
+ end_called = false;
+ startTime = std::chrono::system_clock::now();
+ }
+
+ // Stop the timer
+ void end() const {
+ end_called = true;
+ endTime = std::chrono::system_clock::now();
+ }
+
+ std::string message() const {
+ return msg;
+ }
+
+ // Print current value to std::cout
+ void print() const {
+ std::cout << *this << std::endl;
+ }
+
+ friend std::ostream& operator<<(std::ostream& stream, const Clock& clock) {
+ if (!clock.msg.empty())
+ stream << clock.msg << ": ";
+
+ stream << clock.num_seconds() << "s\n";
+ return stream;
+ }
+
+ // Get the number of seconds between the timer start and:
+ // - the last call of end() if it was called
+ // - or now otherwise. In this case, the timer is not stopped.
+ double num_seconds() const {
+ if (!end_called) {
+ auto end = std::chrono::system_clock::now();
+ return std::chrono::duration_cast<std::chrono::milliseconds>(end-startTime).count() / 1000.;
+ } else {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(endTime-startTime).count() / 1000.;
+ }
+ }
+
+ private:
+ mutable std::chrono::time_point<std::chrono::system_clock> startTime, endTime;
+ mutable bool end_called;
+ std::string msg;
+};
+
+} // namespace Gudhi
+
+#endif // CLOCK_H_
diff --git a/src/common/include/gudhi/Debug_utils.h b/src/common/include/gudhi/Debug_utils.h
new file mode 100644
index 00000000..38abc06d
--- /dev/null
+++ b/src/common/include/gudhi/Debug_utils.h
@@ -0,0 +1,45 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): David Salinas
+ *
+ * Copyright (C) 2014 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+#ifndef DEBUG_UTILS_H_
+#define DEBUG_UTILS_H_
+
+#include <iostream>
+
+#ifndef NDEBUG
+ // GUDHI_DEBUG is the Gudhi official flag for debug mode.
+ #define GUDHI_DEBUG
+#endif
+
+// GUDHI_CHECK throw an exception if expression is false in debug mode, but does nothing in release mode
+// Could assert in release mode, but cmake sets NDEBUG (for "NO DEBUG") in this mode, means assert does nothing.
+#ifdef GUDHI_DEBUG
+ #define GUDHI_CHECK(expression, excpt) ((expression) ? (void) 0 : (throw excpt))
+ #define GUDHI_CHECK_code(CODE) CODE
+#else
+ #define GUDHI_CHECK(expression, excpt) (void) 0
+ #define GUDHI_CHECK_code(CODE)
+#endif
+
+#define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl
+
+// #define DBG_VERBOSE
+#ifdef DBG_VERBOSE
+ #define DBG(a) std::cout << "DBG: " << (a) << std::endl
+ #define DBGMSG(a, b) std::cout << "DBG: " << a << b << std::endl
+ #define DBGVALUE(a) std::cout << "DBG: " << #a << ": " << a << std::endl
+ #define DBGCONT(a) std::cout << "DBG: container " << #a << " -> "; for (auto x : a) std::cout << x << ","; std::cout << std::endl
+#else
+ #define DBG(a) (void) 0
+ #define DBGMSG(a, b) (void) 0
+ #define DBGVALUE(a) (void) 0
+ #define DBGCONT(a) (void) 0
+#endif
+
+#endif // DEBUG_UTILS_H_
diff --git a/src/common/include/gudhi/Null_output_iterator.h b/src/common/include/gudhi/Null_output_iterator.h
new file mode 100644
index 00000000..3d03bca6
--- /dev/null
+++ b/src/common/include/gudhi/Null_output_iterator.h
@@ -0,0 +1,36 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Marc Glisse
+ *
+ * Copyright (C) 2017 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef NULL_OUTPUT_ITERATOR_H_
+#define NULL_OUTPUT_ITERATOR_H_
+
+#include <iterator>
+
+namespace Gudhi {
+
+/** An output iterator that ignores whatever it is given. */
+struct Null_output_iterator {
+ typedef std::output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ Null_output_iterator& operator++() {return *this;}
+ Null_output_iterator operator++(int) {return *this;}
+ struct proxy {
+ template<class T>
+ proxy& operator=(T&&){return *this;}
+ };
+ proxy operator*()const{return {};}
+};
+} // namespace Gudhi
+
+#endif // NULL_OUTPUT_ITERATOR_H_
diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h
new file mode 100644
index 00000000..aaff95b8
--- /dev/null
+++ b/src/common/include/gudhi/Off_reader.h
@@ -0,0 +1,173 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): David Salinas
+ *
+ * Copyright (C) 2014 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+
+#ifndef OFF_READER_H_
+#define OFF_READER_H_
+
+
+#include <sstream>
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <vector>
+#include <fstream>
+
+namespace Gudhi {
+
+/** \brief OFF file reader top class visitor.
+ *
+ * OFF file must be conform to \ref FileFormatsOFF
+ */
+class Off_reader {
+ public:
+ Off_reader(std::ifstream& stream) : stream_(stream) { }
+
+ ~Off_reader() {
+ stream_.close();
+ }
+
+ /** \brief
+ * Read an OFF file and calls the following methods :
+ *
+ * <CODE>void init(int dim,int num_vertices,int num_faces,int num_edges); // from file header - num_edges may not be set
+ *
+ * void point(const std::vector<double>& point); // for each point read
+ *
+ * void maximal_face(const std::list<int>& face); // for each face read
+ *
+ * void done(); // upon file read is finished</CODE>
+ *
+ * of the visitor when reading a point or a maximal face. Edges are not taken into account.
+ */
+ template<typename OffVisitor>
+ bool read(OffVisitor& off_visitor) {
+ bool success_read_off_preambule = read_off_preambule(off_visitor);
+ if (!success_read_off_preambule) {
+ std::cerr << "could not read off preambule\n";
+ return false;
+ }
+
+ bool success_read_off_points = read_off_points(off_visitor);
+ if (!success_read_off_points) {
+ std::cerr << "could not read off points\n";
+ return false;
+ }
+
+ bool success_read_off_faces = read_off_faces(off_visitor);
+ if (!success_read_off_faces) {
+ std::cerr << "could not read off faces\n";
+ return false;
+ }
+
+ off_visitor.done();
+ return success_read_off_preambule && success_read_off_points && success_read_off_faces;
+ }
+
+ private:
+ std::ifstream& stream_;
+
+ struct Off_info {
+ int dim;
+ int num_vertices;
+ int num_edges;
+ int num_faces;
+ };
+
+ Off_info off_info_;
+
+ template<typename OffVisitor>
+ bool read_off_preambule(OffVisitor& off_visitor) {
+ std::string line;
+ if (!goto_next_uncomment_line(line)) return false;
+
+ bool is_off_file = (line.find("OFF") != std::string::npos);
+ bool is_noff_file = (line.find("nOFF") != std::string::npos);
+
+
+
+ if (!is_off_file && !is_noff_file) {
+ std::cerr << line << std::endl;
+ std::cerr << "missing off header\n";
+ return false;
+ }
+
+ if (is_noff_file) {
+ // Should be on a separate line, but we accept it on the same line as the number of vertices
+ stream_ >> off_info_.dim;
+ } else {
+ off_info_.dim = 3;
+ }
+
+ if (!goto_next_uncomment_line(line)) return false;
+ std::istringstream iss(line);
+ if (!(iss >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) {
+ std::cerr << "incorrect number of vertices/faces/edges\n";
+ return false;
+ }
+ off_visitor.init(off_info_.dim, off_info_.num_vertices, off_info_.num_faces, off_info_.num_edges);
+
+ return true;
+ }
+
+ bool goto_next_uncomment_line(std::string& uncomment_line) {
+ do {
+ // skip whitespace, including empty lines
+ if (!std::ifstream::sentry(stream_)) return false;
+ std::getline(stream_, uncomment_line);
+ } while (uncomment_line[0] == '#');
+ return static_cast<bool>(stream_);
+ }
+
+ template<typename OffVisitor>
+ bool read_off_points(OffVisitor& visitor) {
+ int num_vertices_to_read = off_info_.num_vertices;
+ while (num_vertices_to_read--) {
+ std::string line;
+ if (!goto_next_uncomment_line(line)) return false;
+ std::vector<double> point;
+ std::istringstream iss(line);
+ point.assign(std::istream_iterator<double>(iss), std::istream_iterator<double>());
+ // if(point.size() != off_info_.dim) return false;
+ visitor.point(point);
+ }
+ return true;
+ }
+
+ template<typename OffVisitor>
+ bool read_off_faces(OffVisitor& visitor) {
+ std::string line;
+ while (goto_next_uncomment_line(line)) {
+ std::istringstream iss(line);
+ int num_face_vertices;
+ iss >> num_face_vertices;
+ std::vector<int> face;
+ face.assign(std::istream_iterator<int>(iss), std::istream_iterator<int>());
+ // if (face.size() != (off_info_.dim + 1)) return false;
+ visitor.maximal_face(face);
+ }
+ return true;
+ }
+};
+
+template<typename OFFVisitor>
+void read_off(const std::string& name_file_off, OFFVisitor& vis) {
+ std::ifstream stream(name_file_off);
+ if (!stream.is_open()) {
+ std::cerr << "could not open file \n";
+ } else {
+ Off_reader off_reader(stream);
+ off_reader.read(vis);
+ }
+}
+
+} // namespace Gudhi
+
+#endif // OFF_READER_H_
diff --git a/src/common/include/gudhi/Point.h b/src/common/include/gudhi/Point.h
new file mode 100644
index 00000000..e85277e9
--- /dev/null
+++ b/src/common/include/gudhi/Point.h
@@ -0,0 +1,157 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): David Salinas
+ *
+ * Copyright (C) 2014 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef POINT_H_
+#define POINT_H_
+
+#include <cmath>
+#include <vector>
+#include <cassert>
+#include <cstddef>
+#include <initializer_list>
+
+class Point_d {
+ public:
+ Point_d(size_t dim = 3) : coords_(dim, 0) { }
+
+ Point_d(const Point_d& other) : coords_(other.coords_) { }
+
+ Point_d(const std::initializer_list<double>& list) : coords_(list) { }
+
+ template<typename CoordsIt>
+ Point_d(CoordsIt begin, CoordsIt end) : coords_(begin, end) { }
+
+ size_t dimension() const {
+ return coords_.size();
+ }
+
+ double x() const {
+ return coords_[0];
+ }
+
+ double y() const {
+ return coords_[1];
+ }
+
+ double z() const {
+ return coords_[2];
+ }
+
+ double& x() {
+ return coords_[0];
+ }
+
+ double& y() {
+ return coords_[1];
+ }
+
+ double& z() {
+ return coords_[2];
+ }
+
+ std::vector<double>::const_iterator begin() const {
+ return coords_.begin();
+ }
+
+ std::vector<double>::const_iterator end() const {
+ return coords_.end();
+ }
+
+ double& operator[](unsigned i) {
+ return coords_[i];
+ }
+
+ const double& operator[](unsigned i) const {
+ return coords_[i];
+ }
+
+ double squared_norm() const {
+ double res = 0;
+ for (auto x : coords_)
+ res += x * x;
+ return res;
+ }
+
+ friend double squared_dist(const Point_d& p1, const Point_d& p2) {
+ assert(p1.dimension() == p2.dimension());
+ double res = 0;
+ for (unsigned i = 0; i < p1.coords_.size(); ++i)
+ res += (p1[i] - p2[i])*(p1[i] - p2[i]);
+ return res;
+ }
+
+ /**
+ * dot product
+ */
+ double operator*(const Point_d& other) const {
+ assert(dimension() == other.dimension());
+ double res = 0;
+ for (unsigned i = 0; i < coords_.size(); ++i)
+ res += coords_[i] * other[i];
+ return res;
+ }
+
+ /**
+ * only if points have dimension 3
+ */
+ Point_d cross_product(const Point_d& other) {
+ assert(dimension() == 3 && other.dimension() == 3);
+ Point_d res(3);
+ res[0] = (*this)[1] * other[2] - (*this)[2] * other[1];
+ res[1] = (*this)[2] * other[0] - (*this)[0] * other[2];
+ res[2] = (*this)[0] * other[1] - (*this)[1] * other[0];
+ return res;
+ }
+
+ Point_d operator+(const Point_d& other) const {
+ assert(dimension() == other.dimension());
+ Point_d res(dimension());
+ for (unsigned i = 0; i < coords_.size(); ++i)
+ res[i] = (*this)[i] + other[i];
+ return res;
+ }
+
+ Point_d operator*(double lambda) const {
+ Point_d res(dimension());
+ for (unsigned i = 0; i < coords_.size(); ++i)
+ res[i] = (*this)[i] * lambda;
+ return res;
+ }
+
+ Point_d operator/(double lambda) const {
+ Point_d res(dimension());
+ for (unsigned i = 0; i < coords_.size(); ++i)
+ res[i] = (*this)[i] / lambda;
+ return res;
+ }
+
+ Point_d operator-(const Point_d& other) const {
+ assert(dimension() == other.dimension());
+ Point_d res(dimension());
+ for (unsigned i = 0; i < coords_.size(); ++i)
+ res[i] = (*this)[i] - other[i];
+ return res;
+ }
+
+ friend Point_d unit_normal(const Point_d& p1, const Point_d& p2, const Point_d& p3) {
+ assert(p1.dimension() == 3);
+ assert(p2.dimension() == 3);
+ assert(p3.dimension() == 3);
+ Point_d p1p2 = p2 - p1;
+ Point_d p1p3 = p3 - p1;
+ Point_d res(p1p2.cross_product(p1p3));
+ return res / std::sqrt(res.squared_norm());
+ }
+
+ private:
+ std::vector<double> coords_;
+};
+
+#endif // POINT_H_
diff --git a/src/common/include/gudhi/Points_3D_off_io.h b/src/common/include/gudhi/Points_3D_off_io.h
new file mode 100644
index 00000000..2d110af3
--- /dev/null
+++ b/src/common/include/gudhi/Points_3D_off_io.h
@@ -0,0 +1,190 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Vincent Rouvreau
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+#ifndef POINTS_3D_OFF_IO_H_
+#define POINTS_3D_OFF_IO_H_
+
+#include <gudhi/Off_reader.h>
+
+#include <string>
+#include <vector>
+#include <fstream>
+#include <map>
+
+namespace Gudhi {
+
+/**
+ * @brief OFF file visitor implementation according to Off_reader in order to read points from an OFF file.
+ */
+template<typename Point_3>
+class Points_3D_off_visitor_reader {
+ private:
+ std::vector<Point_3> point_cloud_;
+ bool valid_;
+
+ public:
+ /** @brief Off_reader visitor init implementation.
+ *
+ * The init parameters are set from OFF file header.
+ * Dimension value is required and the value must be 3.
+ *
+ * @param[in] dim space dimension of vertices.
+ * @param[in] num_vertices number of vertices in the OFF file (not used).
+ * @param[in] num_faces number of faces in the OFF file (not used).
+ * @param[in] num_edges number of edges in the OFF file (not used).
+ */
+ void init(int dim, int num_vertices, int num_faces, int num_edges) {
+#ifdef DEBUG_TRACES
+ std::cout << "Points_3D_off_visitor_reader::init - dim=" << dim << " - num_vertices=" <<
+ num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl;
+#endif // DEBUG_TRACES
+ if (dim == 3) {
+ valid_ = true;
+ } else {
+ valid_ = false;
+ std::cerr << "Points_3D_off_reader::Points_3D_off_reader cannot read OFF files in dimension " << dim << "\n";
+ }
+
+ if (num_faces > 0) {
+ std::cerr << "Points_3D_off_visitor_reader::init faces are not taken into account from OFF file for Points.\n";
+ }
+ if (num_edges > 0) {
+ std::cerr << "Points_3D_off_visitor_reader::init edges are not taken into account from OFF file for Points.\n";
+ }
+ }
+
+ /** @brief Off_reader visitor point implementation.
+ *
+ * The point function is called on each vertex line from OFF file.
+ * This function inserts the vertex in the vector of points.
+ *
+ * @param[in] point vector of vertex coordinates.
+ *
+ * @details
+ * Point_3 must have a constructor with the following form:
+ *
+ * @code template<class InputIterator > Point_3::Point_3(double x, double y, double z) @endcode
+ */
+ void point(const std::vector<double>& point) {
+ if (valid_) {
+#ifdef DEBUG_TRACES
+ std::cout << "Points_3D_off_visitor_reader::point ";
+ for (auto coordinate : point) {
+ std::cout << coordinate << " | ";
+ }
+ std::cout << std::endl;
+#endif // DEBUG_TRACES
+ // Fill the point cloud
+ point_cloud_.push_back(Point_3(point[0], point[1], point[2]));
+ }
+ }
+
+ // Off_reader visitor maximal_face implementation - Only points are read
+
+ void maximal_face(const std::vector<int>& face) { }
+
+ // Off_reader visitor done implementation - Only points are read
+
+ void done() { }
+
+ /** @brief Point cloud getter.
+ *
+ * @return The point cloud.
+ */
+ const std::vector<Point_3>& get_point_cloud() const {
+ return point_cloud_;
+ }
+
+ /** @brief Returns if the OFF file read operation was successful or not.
+ *
+ * @return OFF file read status.
+ */
+ bool is_valid() const {
+ return valid_;
+ }
+};
+
+/**
+ * \@brief OFF file reader implementation in order to read dimension 3 points from an OFF file.
+ *
+ * @details
+ * This class is using the Points_3D_off_visitor_reader to visit the OFF file according to Off_reader.
+ *
+ * Point_3 must have a constructor with the following form:
+ *
+ * @code template<class InputIterator > Point_3::Point_3(double x, double y, double z) @endcode
+ *
+ * @section point3doffioexample Example
+ *
+ * This example loads points from an OFF file and builds a vector of CGAL points in dimension 3.
+ * Then, it is asked to display the points.
+ *
+ * @include common/example_CGAL_3D_points_off_reader.cpp
+ *
+ * When launching:
+ *
+ * @code $> ./cgal3Doffreader ../../data/points/tore3D_300.off
+ * @endcode
+ *
+ * the program output is:
+ *
+ * @include common/cgal3Doffreader_result.txt
+ */
+template<typename Point_3>
+class Points_3D_off_reader {
+ public:
+ /** @brief Reads the OFF file and constructs a vector of points from the points
+ * that are in the OFF file.
+ *
+ * @param[in] name_file OFF file to read.
+ *
+ * @post Check with is_valid() function to see if read operation was successful.
+ */
+ Points_3D_off_reader(const std::string& name_file)
+ : valid_(false) {
+ std::ifstream stream(name_file);
+ if (stream.is_open()) {
+ Off_reader off_reader(stream);
+ Points_3D_off_visitor_reader<Point_3> off_visitor;
+ valid_ = off_reader.read(off_visitor);
+ valid_ = valid_ && off_visitor.is_valid();
+ if (valid_) {
+ point_cloud = off_visitor.get_point_cloud();
+ }
+ } else {
+ std::cerr << "Points_3D_off_reader::Points_3D_off_reader could not open file " << name_file << "\n";
+ }
+ }
+
+ /** @brief Returns if the OFF file read operation was successful or not.
+ *
+ * @return OFF file read status.
+ */
+ bool is_valid() const {
+ return valid_;
+ }
+
+ /** @brief Point cloud getter.
+ *
+ * @return point_cloud.
+ */
+ const std::vector<Point_3>& get_point_cloud() const {
+ return point_cloud;
+ }
+
+ private:
+ /** @brief point_cloud.*/
+ std::vector<Point_3> point_cloud;
+ /** @brief OFF file read status.*/
+ bool valid_;
+};
+
+} // namespace Gudhi
+
+#endif // POINTS_3D_OFF_IO_H_
diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h
new file mode 100644
index 00000000..99371d56
--- /dev/null
+++ b/src/common/include/gudhi/Points_off_io.h
@@ -0,0 +1,171 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Vincent Rouvreau
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+#ifndef POINTS_OFF_IO_H_
+#define POINTS_OFF_IO_H_
+
+#include <gudhi/Off_reader.h>
+
+#include <string>
+#include <vector>
+#include <fstream>
+#include <map>
+
+namespace Gudhi {
+
+/**
+ * \brief OFF file visitor implementation according to Off_reader in order to read points from an OFF file.
+ */
+template<typename Point_d>
+class Points_off_visitor_reader {
+ private:
+ std::vector<Point_d> point_cloud;
+
+ public:
+ /** \brief Off_reader visitor init implementation.
+ *
+ * The init parameters are set from OFF file header.
+ * Dimension value is required in order to construct a vector of points.
+ *
+ * @param[in] dim space dimension of vertices.
+ * @param[in] num_vertices number of vertices in the OFF file (not used).
+ * @param[in] num_faces number of faces in the OFF file (not used).
+ * @param[in] num_edges number of edges in the OFF file (not used).
+ */
+ void init(int dim, int num_vertices, int num_faces, int num_edges) {
+#ifdef DEBUG_TRACES
+ std::cout << "Points_off_visitor_reader::init - dim=" << dim << " - num_vertices=" <<
+ num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl;
+#endif // DEBUG_TRACES
+ if (num_faces > 0) {
+ std::cerr << "Points_off_visitor_reader::init faces are not taken into account from OFF file for Points.\n";
+ }
+ if (num_edges > 0) {
+ std::cerr << "Points_off_visitor_reader::init edges are not taken into account from OFF file for Points.\n";
+ }
+ }
+
+ /** @brief Off_reader visitor point implementation.
+ *
+ * The point function is called on each vertex line from OFF file.
+ * This function inserts the vertex in the vector of points.
+ *
+ * @param[in] point vector of vertex coordinates.
+ *
+ * @details
+ * Point_d must have a constructor with the following form:
+ *
+ * @code template<class InputIterator > Point_d::Point_d(InputIterator first, InputIterator last) @endcode
+ *
+ */
+ void point(const std::vector<double>& point) {
+#ifdef DEBUG_TRACES
+ std::cout << "Points_off_visitor_reader::point ";
+ for (auto coordinate : point) {
+ std::cout << coordinate << " | ";
+ }
+ std::cout << std::endl;
+#endif // DEBUG_TRACES
+ // Fill the point cloud
+ point_cloud.push_back(Point_d(point.begin(), point.end()));
+ }
+
+ // Off_reader visitor maximal_face implementation - Only points are read
+ void maximal_face(const std::vector<int>& face) { }
+
+ // Off_reader visitor done implementation - Only points are read
+ void done() { }
+
+ /** \brief Point cloud getter.
+ *
+ * @return point_cloud.
+ */
+ const std::vector<Point_d>& get_point_cloud() const {
+ return point_cloud;
+ }
+};
+
+/**
+ * \brief OFF file reader implementation in order to read points from an OFF file.
+ *
+ * This class is using the Points_off_visitor_reader to visit the OFF file according to Off_reader.
+ *
+ * Point_d must have a constructor with the following form:
+ *
+ * \code template<class InputIterator > Point_d::Point_d(int d, InputIterator first, InputIterator last) \endcode
+ *
+ * where d is the point dimension.
+ *
+ * \section pointoffioexample Example
+ *
+ * This example loads points from an OFF file and builds a vector of points (vector of double).
+ * Then, it is asked to display the points.
+ *
+ * \include common/example_vector_double_points_off_reader.cpp
+ *
+ * When launching:
+ *
+ * \code $> ./vector_double_off_reader ../../data/points/alphacomplexdoc.off
+ * \endcode
+ *
+ * the program outputs a file ../../data/points/alphacomplexdoc.off.txt:
+ *
+ * \include common/vectordoubleoffreader_result.txt
+ */
+template<typename Point_d>
+class Points_off_reader {
+ public:
+ /** \brief Reads the OFF file and constructs a vector of points from the points
+ * that are in the OFF file.
+ *
+ * @param[in] name_file OFF file to read.
+ *
+ * \post Check with is_valid() function to see if read operation was successful.
+ */
+ Points_off_reader(const std::string& name_file)
+ : valid_(false) {
+ std::ifstream stream(name_file);
+ if (stream.is_open()) {
+ Off_reader off_reader(stream);
+ Points_off_visitor_reader<Point_d> off_visitor;
+ valid_ = off_reader.read(off_visitor);
+ if (valid_) {
+ point_cloud = off_visitor.get_point_cloud();
+ }
+ } else {
+ std::cerr << "Points_off_reader::Points_off_reader could not open file " << name_file << "\n";
+ }
+ }
+
+ /** \brief Returns if the OFF file read operation was successful or not.
+ *
+ * @return OFF file read status.
+ */
+ bool is_valid() const {
+ return valid_;
+ }
+
+ /** \brief Point cloud getter.
+ *
+ * @return point_cloud.
+ */
+ const std::vector<Point_d>& get_point_cloud() const {
+ return point_cloud;
+ }
+
+ private:
+ /** \brief point_cloud.*/
+ std::vector<Point_d> point_cloud;
+ /** \brief OFF file read status.*/
+ bool valid_;
+};
+
+} // namespace Gudhi
+
+#endif // POINTS_OFF_IO_H_
diff --git a/src/common/include/gudhi/Simple_object_pool.h b/src/common/include/gudhi/Simple_object_pool.h
new file mode 100644
index 00000000..d1482b44
--- /dev/null
+++ b/src/common/include/gudhi/Simple_object_pool.h
@@ -0,0 +1,69 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Marc Glisse
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef SIMPLE_OBJECT_POOL_H_
+#define SIMPLE_OBJECT_POOL_H_
+
+#include <boost/pool/pool.hpp>
+#include <utility>
+
+namespace Gudhi {
+
+/** \private
+ * This is a simpler version of boost::object_pool, that requires
+ * that users explicitly destroy all objects. This lets the
+ * performance scale much better, see
+ * https://svn.boost.org/trac/boost/ticket/3789 .
+ */
+template <class T>
+class Simple_object_pool : protected boost::pool<boost::default_user_allocator_malloc_free> {
+ protected:
+ typedef boost::pool<boost::default_user_allocator_malloc_free> Base;
+ typedef T* pointer;
+
+ Base& base() {
+ return *this;
+ }
+
+ Base const& base()const {
+ return *this;
+ }
+
+ public:
+ typedef T element_type;
+ typedef boost::default_user_allocator_malloc_free user_allocator;
+ typedef typename Base::size_type size_type;
+ typedef typename Base::difference_type difference_type;
+
+ template<class...U>
+ Simple_object_pool(U&&...u) : Base(sizeof (T), std::forward<U>(u)...) { }
+
+ template<class...U>
+ pointer construct(U&&...u) {
+ void* p = base().malloc BOOST_PREVENT_MACRO_SUBSTITUTION();
+ assert(p);
+ try {
+ new(p) T(std::forward<U>(u)...);
+ } catch (...) {
+ base().free BOOST_PREVENT_MACRO_SUBSTITUTION(p);
+ throw;
+ }
+ return static_cast<pointer> (p);
+ }
+
+ void destroy(pointer p) {
+ p->~T();
+ base().free BOOST_PREVENT_MACRO_SUBSTITUTION(p);
+ }
+};
+
+} // namespace Gudhi
+
+#endif // SIMPLE_OBJECT_POOL_H_
diff --git a/src/common/include/gudhi/Unitary_tests_utils.h b/src/common/include/gudhi/Unitary_tests_utils.h
new file mode 100644
index 00000000..4ad4dae8
--- /dev/null
+++ b/src/common/include/gudhi/Unitary_tests_utils.h
@@ -0,0 +1,28 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Vincent Rouvreau
+ *
+ * Copyright (C) 2017 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+#ifndef UNITARY_TESTS_UTILS_H_
+#define UNITARY_TESTS_UTILS_H_
+
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+#include <limits> // for std::numeric_limits<>
+
+template<typename FloatingType >
+void GUDHI_TEST_FLOAT_EQUALITY_CHECK(FloatingType a, FloatingType b,
+ FloatingType epsilon = std::numeric_limits<FloatingType>::epsilon()) {
+#ifdef DEBUG_TRACES
+ 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);
+}
+
+#endif // UNITARY_TESTS_UTILS_H_
diff --git a/src/common/include/gudhi/allocator.h b/src/common/include/gudhi/allocator.h
new file mode 100644
index 00000000..b7ccd180
--- /dev/null
+++ b/src/common/include/gudhi/allocator.h
@@ -0,0 +1,43 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Marc Glisse
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef ALLOCATOR_H_
+#define ALLOCATOR_H_
+
+#include <memory>
+#include <utility>
+
+namespace Gudhi {
+
+/** \private
+ * An allocator that can be used to build an uninitialized vector.
+ */
+template <class T, class Base = std::allocator<T>>
+struct no_init_allocator : Base {
+ typedef std::allocator_traits<Base> Base_traits;
+ template <class U> struct rebind {
+ typedef no_init_allocator<U, typename Base_traits::template rebind_alloc<U>> other;
+ };
+
+ // Inherit constructors.
+ using Base::Base;
+
+ // Do nothing: that's the whole point!
+ template<class P>
+ void construct(P*) noexcept {}
+
+ template<class P, class...U> void construct(P*p, U&&...u) {
+ Base_traits::construct(*(Base*)this, p, std::forward<U>(u)...);
+ }
+};
+
+} // namespace Gudhi
+
+#endif // ALLOCATOR_H_
diff --git a/src/common/include/gudhi/console_color.h b/src/common/include/gudhi/console_color.h
new file mode 100644
index 00000000..f9167119
--- /dev/null
+++ b/src/common/include/gudhi/console_color.h
@@ -0,0 +1,85 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef CONSOLE_COLOR_H_
+#define CONSOLE_COLOR_H_
+
+#include <iostream>
+
+#if defined(WIN32)
+#include <windows.h>
+#endif
+
+inline std::ostream& blue(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout,
+ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
+#else
+ s << "\x1b[0;34m";
+#endif
+ return s;
+}
+
+inline std::ostream& red(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY);
+#else
+ s << "\x1b[0;31m";
+#endif
+ return s;
+}
+
+inline std::ostream& green(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
+#else
+ s << "\x1b[0;32m";
+#endif
+ return s;
+}
+
+inline std::ostream& yellow(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout,
+ FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
+#else
+ s << "\x1b[0;33m";
+#endif
+ return s;
+}
+
+inline std::ostream& white(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout,
+ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
+#else
+ s << "\x1b[0;37m";
+#endif
+ return s;
+}
+
+inline std::ostream& black_on_white(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout,
+ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
+#else
+ s << "\x1b[0;33m";
+#endif
+ return s;
+}
+
+
+#endif // CONSOLE_COLOR_H_
diff --git a/src/common/include/gudhi/distance_functions.h b/src/common/include/gudhi/distance_functions.h
new file mode 100644
index 00000000..94cf9ccc
--- /dev/null
+++ b/src/common/include/gudhi/distance_functions.h
@@ -0,0 +1,111 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Clément Maria
+ *
+ * Copyright (C) 2014 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef DISTANCE_FUNCTIONS_H_
+#define DISTANCE_FUNCTIONS_H_
+
+#include <gudhi/Debug_utils.h>
+
+#include <gudhi/Miniball.hpp>
+
+#include <boost/range/metafunctions.hpp>
+#include <boost/range/size.hpp>
+
+#include <cmath> // for std::sqrt
+#include <type_traits> // for std::decay
+#include <iterator> // for std::begin, std::end
+#include <utility>
+
+namespace Gudhi {
+
+/** @file
+ * @brief Global distance functions
+ */
+
+/** @brief Compute the Euclidean distance between two Points given by a range of coordinates. The points are assumed to
+ * have the same dimension. */
+class Euclidean_distance {
+ public:
+ // boost::range_value is not SFINAE-friendly so we cannot use it in the return type
+ template< typename Point >
+ typename std::iterator_traits<typename boost::range_iterator<Point>::type>::value_type
+ operator()(const Point& p1, const Point& p2) const {
+ auto it1 = std::begin(p1);
+ auto it2 = std::begin(p2);
+ typedef typename boost::range_value<Point>::type NT;
+ NT dist = 0;
+ for (; it1 != std::end(p1); ++it1, ++it2) {
+ GUDHI_CHECK(it2 != std::end(p2), "inconsistent point dimensions");
+ NT tmp = *it1 - *it2;
+ dist += tmp*tmp;
+ }
+ GUDHI_CHECK(it2 == std::end(p2), "inconsistent point dimensions");
+ using std::sqrt;
+ return sqrt(dist);
+ }
+ template< typename T >
+ T operator() (const std::pair< T, T >& f, const std::pair< T, T >& s) const {
+ T dx = f.first - s.first;
+ T dy = f.second - s.second;
+ using std::sqrt;
+ return sqrt(dx*dx + dy*dy);
+ }
+};
+
+/** @brief Compute the radius of the minimal enclosing ball between Points given by a range of coordinates.
+ * The points are assumed to have the same dimension. */
+class Minimal_enclosing_ball_radius {
+ public:
+ /** \brief Minimal_enclosing_ball_radius from two points.
+ *
+ * @param[in] point_1 First point.
+ * @param[in] point_2 second point.
+ * @return The minimal enclosing ball radius for the two points (aka. Euclidean distance / 2.).
+ *
+ * \tparam Point must be a range of Cartesian coordinates.
+ *
+ */
+ template< typename Point >
+ typename std::iterator_traits<typename boost::range_iterator<Point>::type>::value_type
+ operator()(const Point& point_1, const Point& point_2) const {
+ return Euclidean_distance()(point_1, point_2) / 2.;
+ }
+ /** \brief Minimal_enclosing_ball_radius from a point cloud.
+ *
+ * @param[in] point_cloud The points.
+ * @return The minimal enclosing ball radius for the points.
+ *
+ * \tparam Point_cloud must be a range of points with Cartesian coordinates.
+ * Point_cloud is a range over a range of Coordinate.
+ *
+ */
+ template< typename Point_cloud,
+ typename Point_iterator = typename boost::range_const_iterator<Point_cloud>::type,
+ typename Point = typename std::iterator_traits<Point_iterator>::value_type,
+ typename Coordinate_iterator = typename boost::range_const_iterator<Point>::type,
+ typename Coordinate = typename std::iterator_traits<Coordinate_iterator>::value_type>
+ Coordinate
+ operator()(const Point_cloud& point_cloud) const {
+ using Min_sphere = Miniball::Miniball<Miniball::CoordAccessor<Point_iterator, Coordinate_iterator>>;
+
+ Min_sphere ms(boost::size(*point_cloud.begin()), point_cloud.begin(), point_cloud.end());
+#ifdef DEBUG_TRACES
+ std::cout << "Minimal_enclosing_ball_radius = " << std::sqrt(ms.squared_radius()) << " | nb points = "
+ << boost::size(point_cloud) << " | dimension = "
+ << boost::size(*point_cloud.begin()) << std::endl;
+#endif // DEBUG_TRACES
+
+ return std::sqrt(ms.squared_radius());
+ }
+};
+
+} // namespace Gudhi
+
+#endif // DISTANCE_FUNCTIONS_H_
diff --git a/src/common/include/gudhi/graph_simplicial_complex.h b/src/common/include/gudhi/graph_simplicial_complex.h
new file mode 100644
index 00000000..b8508697
--- /dev/null
+++ b/src/common/include/gudhi/graph_simplicial_complex.h
@@ -0,0 +1,99 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Clément Maria
+ *
+ * Copyright (C) 2014 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef GRAPH_SIMPLICIAL_COMPLEX_H_
+#define GRAPH_SIMPLICIAL_COMPLEX_H_
+
+#include <boost/graph/adjacency_list.hpp>
+
+#include <utility> // for pair<>
+#include <vector>
+#include <map>
+#include <tuple> // for std::tie
+
+namespace Gudhi {
+
+/* Edge tag for Boost PropertyGraph. */
+struct edge_filtration_t {
+ typedef boost::edge_property_tag kind;
+};
+
+/* Vertex tag for Boost PropertyGraph. */
+struct vertex_filtration_t {
+ typedef boost::vertex_property_tag kind;
+};
+
+/** \brief Proximity_graph contains the vertices and edges with their filtration values in order to store the result
+ * of `Gudhi::compute_proximity_graph` function.
+ *
+ * \tparam SimplicialComplexForProximityGraph furnishes `Filtration_value` type definition.
+ *
+ */
+template <typename SimplicialComplexForProximityGraph>
+using Proximity_graph = typename boost::adjacency_list < boost::vecS, boost::vecS, boost::directedS
+, boost::property < vertex_filtration_t, typename SimplicialComplexForProximityGraph::Filtration_value >
+, boost::property < edge_filtration_t, typename SimplicialComplexForProximityGraph::Filtration_value >>;
+
+/** \brief Computes the proximity graph of the points.
+ *
+ * If points contains n elements, the proximity graph is the graph with n vertices, and an edge [u,v] iff the
+ * distance function between points u and v is smaller than threshold.
+ *
+ * \tparam ForwardPointRange furnishes `.begin()` and `.end()` methods.
+ *
+ * \tparam Distance furnishes `operator()(const Point& p1, const Point& p2)`, where
+ * `Point` is a point from the `ForwardPointRange`, and that returns a `Filtration_value`.
+ */
+template< typename SimplicialComplexForProximityGraph
+ , typename ForwardPointRange
+ , typename Distance >
+Proximity_graph<SimplicialComplexForProximityGraph> compute_proximity_graph(
+ const ForwardPointRange& points,
+ typename SimplicialComplexForProximityGraph::Filtration_value threshold,
+ Distance distance) {
+ using Vertex_handle = typename SimplicialComplexForProximityGraph::Vertex_handle;
+ using Filtration_value = typename SimplicialComplexForProximityGraph::Filtration_value;
+
+ std::vector<std::pair< Vertex_handle, Vertex_handle >> edges;
+ std::vector< Filtration_value > edges_fil;
+ std::map< Vertex_handle, Filtration_value > vertices;
+
+ Vertex_handle idx_u, idx_v;
+ Filtration_value fil;
+ idx_u = 0;
+ for (auto it_u = points.begin(); it_u != points.end(); ++it_u) {
+ idx_v = idx_u + 1;
+ for (auto it_v = it_u + 1; it_v != points.end(); ++it_v, ++idx_v) {
+ fil = distance(*it_u, *it_v);
+ if (fil <= threshold) {
+ edges.emplace_back(idx_u, idx_v);
+ edges_fil.push_back(fil);
+ }
+ }
+ ++idx_u;
+ }
+
+ // Points are labeled from 0 to idx_u-1
+ Proximity_graph<SimplicialComplexForProximityGraph> skel_graph(edges.begin(), edges.end(), edges_fil.begin(), idx_u);
+
+ auto vertex_prop = boost::get(vertex_filtration_t(), skel_graph);
+
+ typename boost::graph_traits<Proximity_graph<SimplicialComplexForProximityGraph>>::vertex_iterator vi, vi_end;
+ for (std::tie(vi, vi_end) = boost::vertices(skel_graph);
+ vi != vi_end; ++vi) {
+ boost::put(vertex_prop, *vi, 0.);
+ }
+
+ return skel_graph;
+}
+
+} // namespace Gudhi
+
+#endif // GRAPH_SIMPLICIAL_COMPLEX_H_
diff --git a/src/common/include/gudhi/random_point_generators.h b/src/common/include/gudhi/random_point_generators.h
new file mode 100644
index 00000000..fb69f832
--- /dev/null
+++ b/src/common/include/gudhi/random_point_generators.h
@@ -0,0 +1,502 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 Inria
+ *
+ * Modification(s):
+ * - 2019/08 Vincent Rouvreau: Fix issue #10 for CGAL
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef RANDOM_POINT_GENERATORS_H_
+#define RANDOM_POINT_GENERATORS_H_
+
+#include <CGAL/number_utils.h>
+#include <CGAL/Random.h>
+#include <CGAL/point_generators_d.h>
+#include <CGAL/version.h> // for CGAL_VERSION_NR
+
+#include <vector> // for vector<>
+
+// Make compilation fail - required for external projects - https://github.com/GUDHI/gudhi-devel/issues/10
+#if CGAL_VERSION_NR < 1041101000
+# error Alpha_complex_3d is only available for CGAL >= 4.11
+#endif
+
+namespace Gudhi {
+
+///////////////////////////////////////////////////////////////////////////////
+// Note: All these functions have been tested with the CGAL::Epick_d kernel
+///////////////////////////////////////////////////////////////////////////////
+
+// construct_point: dim 2
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2) {
+ typename Kernel::FT tab[2];
+ tab[0] = x1;
+ tab[1] = x2;
+ return k.construct_point_d_object()(2, &tab[0], &tab[2]);
+}
+
+// construct_point: dim 3
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3) {
+ typename Kernel::FT tab[3];
+ tab[0] = x1;
+ tab[1] = x2;
+ tab[2] = x3;
+ return k.construct_point_d_object()(3, &tab[0], &tab[3]);
+}
+
+// construct_point: dim 4
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3,
+ typename Kernel::FT x4) {
+ typename Kernel::FT tab[4];
+ tab[0] = x1;
+ tab[1] = x2;
+ tab[2] = x3;
+ tab[3] = x4;
+ return k.construct_point_d_object()(4, &tab[0], &tab[4]);
+}
+
+// construct_point: dim 5
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3,
+ typename Kernel::FT x4, typename Kernel::FT x5) {
+ typename Kernel::FT tab[5];
+ tab[0] = x1;
+ tab[1] = x2;
+ tab[2] = x3;
+ tab[3] = x4;
+ tab[4] = x5;
+ return k.construct_point_d_object()(5, &tab[0], &tab[5]);
+}
+
+// construct_point: dim 6
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3,
+ typename Kernel::FT x4, typename Kernel::FT x5, typename Kernel::FT x6) {
+ typename Kernel::FT tab[6];
+ tab[0] = x1;
+ tab[1] = x2;
+ tab[2] = x3;
+ tab[3] = x4;
+ tab[4] = x5;
+ tab[5] = x6;
+ return k.construct_point_d_object()(6, &tab[0], &tab[6]);
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_plane(std::size_t num_points, int intrinsic_dim,
+ int ambient_dim,
+ double coord_min = -5., double coord_max = 5.) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ std::vector<FT> pt(ambient_dim, FT(0));
+ for (int j = 0; j < intrinsic_dim; ++j)
+ pt[j] = rng.get_double(coord_min, coord_max);
+
+ Point p = k.construct_point_d_object()(ambient_dim, pt.begin(), pt.end());
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_moment_curve(std::size_t num_points, int dim,
+ typename Kernel::FT min_x,
+ typename Kernel::FT max_x) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT x = rng.get_double(min_x, max_x);
+ std::vector<FT> coords;
+ coords.reserve(dim);
+ for (int p = 1; p <= dim; ++p)
+ coords.push_back(std::pow(CGAL::to_double(x), p));
+ Point p = k.construct_point_d_object()(
+ dim, coords.begin(), coords.end());
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+
+// R = big radius, r = small radius
+template <typename Kernel/*, typename TC_basis*/>
+std::vector<typename Kernel::Point_d> generate_points_on_torus_3D(std::size_t num_points, double R, double r,
+ bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ Point p = construct_point(k,
+ (R + r * std::cos(u)) * std::cos(v),
+ (R + r * std::cos(u)) * std::sin(v),
+ r * std::sin(u));
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+// "Private" function used by generate_points_on_torus_d
+template <typename Kernel, typename OutputIterator>
+static void generate_uniform_points_on_torus_d(const Kernel &k, int dim, std::size_t num_slices,
+ OutputIterator out,
+ double radius_noise_percentage = 0.,
+ std::vector<typename Kernel::FT> current_point =
+ std::vector<typename Kernel::FT>()) {
+ CGAL::Random rng;
+ int point_size = static_cast<int>(current_point.size());
+ if (point_size == 2 * dim) {
+ *out++ = k.construct_point_d_object()(point_size, current_point.begin(), current_point.end());
+ } else {
+ for (std::size_t slice_idx = 0; slice_idx < num_slices; ++slice_idx) {
+ double radius_noise_ratio = 1.;
+ if (radius_noise_percentage > 0.) {
+ radius_noise_ratio = rng.get_double(
+ (100. - radius_noise_percentage) / 100.,
+ (100. + radius_noise_percentage) / 100.);
+ }
+ std::vector<typename Kernel::FT> cp2 = current_point;
+ double alpha = 6.2832 * slice_idx / num_slices;
+ cp2.push_back(radius_noise_ratio * std::cos(alpha));
+ cp2.push_back(radius_noise_ratio * std::sin(alpha));
+ generate_uniform_points_on_torus_d(
+ k, dim, num_slices, out, radius_noise_percentage, cp2);
+ }
+ }
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_torus_d(std::size_t num_points, int dim, bool uniform = false,
+ double radius_noise_percentage = 0.) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ if (uniform) {
+ std::size_t num_slices = (std::size_t)std::pow(num_points, 1. / dim);
+ generate_uniform_points_on_torus_d(
+ k, dim, num_slices, std::back_inserter(points), radius_noise_percentage);
+ } else {
+ for (std::size_t i = 0; i < num_points;) {
+ double radius_noise_ratio = 1.;
+ if (radius_noise_percentage > 0.) {
+ radius_noise_ratio = rng.get_double(
+ (100. - radius_noise_percentage) / 100.,
+ (100. + radius_noise_percentage) / 100.);
+ }
+ std::vector<typename Kernel::FT> pt;
+ pt.reserve(dim * 2);
+ for (int curdim = 0; curdim < dim; ++curdim) {
+ FT alpha = rng.get_double(0, 6.2832);
+ pt.push_back(radius_noise_ratio * std::cos(alpha));
+ pt.push_back(radius_noise_ratio * std::sin(alpha));
+ }
+
+ Point p = k.construct_point_d_object()(pt.begin(), pt.end());
+ points.push_back(p);
+ ++i;
+ }
+ }
+ return points;
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_sphere_d(std::size_t num_points, int dim, double radius,
+ double radius_noise_percentage = 0.) {
+ typedef typename Kernel::Point_d Point;
+ Kernel k;
+ CGAL::Random rng;
+ CGAL::Random_points_on_sphere_d<Point> generator(dim, radius);
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ Point p = *generator++;
+ if (radius_noise_percentage > 0.) {
+ double radius_noise_ratio = rng.get_double(
+ (100. - radius_noise_percentage) / 100.,
+ (100. + radius_noise_percentage) / 100.);
+
+ typename Kernel::Point_to_vector_d k_pt_to_vec =
+ k.point_to_vector_d_object();
+ typename Kernel::Vector_to_point_d k_vec_to_pt =
+ k.vector_to_point_d_object();
+ typename Kernel::Scaled_vector_d k_scaled_vec =
+ k.scaled_vector_d_object();
+ p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio));
+ }
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_in_ball_d(std::size_t num_points, int dim, double radius) {
+ typedef typename Kernel::Point_d Point;
+ Kernel k;
+ CGAL::Random rng;
+ CGAL::Random_points_in_ball_d<Point> generator(dim, radius);
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ Point p = *generator++;
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_in_cube_d(std::size_t num_points, int dim, double radius) {
+ typedef typename Kernel::Point_d Point;
+ Kernel k;
+ CGAL::Random rng;
+ CGAL::Random_points_in_cube_d<Point> generator(dim, radius);
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ Point p = *generator++;
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_two_spheres_d(std::size_t num_points, int dim, double radius,
+ double distance_between_centers,
+ double radius_noise_percentage = 0.) {
+ typedef typename Kernel::FT FT;
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::Vector_d Vector;
+ Kernel k;
+ CGAL::Random rng;
+ CGAL::Random_points_on_sphere_d<Point> generator(dim, radius);
+ std::vector<Point> points;
+ points.reserve(num_points);
+
+ std::vector<FT> t(dim, FT(0));
+ t[0] = distance_between_centers;
+ Vector c1_to_c2(t.begin(), t.end());
+
+ for (std::size_t i = 0; i < num_points;) {
+ Point p = *generator++;
+ if (radius_noise_percentage > 0.) {
+ double radius_noise_ratio = rng.get_double(
+ (100. - radius_noise_percentage) / 100.,
+ (100. + radius_noise_percentage) / 100.);
+
+ typename Kernel::Point_to_vector_d k_pt_to_vec =
+ k.point_to_vector_d_object();
+ typename Kernel::Vector_to_point_d k_vec_to_pt =
+ k.vector_to_point_d_object();
+ typename Kernel::Scaled_vector_d k_scaled_vec =
+ k.scaled_vector_d_object();
+ p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio));
+ }
+
+ typename Kernel::Translated_point_d k_transl =
+ k.translated_point_d_object();
+ Point p2 = k_transl(p, c1_to_c2);
+ points.push_back(p);
+ points.push_back(p2);
+ i += 2;
+ }
+ return points;
+}
+
+// Product of a 3-sphere and a circle => d = 3 / D = 5
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_3sphere_and_circle(std::size_t num_points,
+ double sphere_radius) {
+ typedef typename Kernel::FT FT;
+ typedef typename Kernel::Point_d Point;
+ Kernel k;
+ CGAL::Random rng;
+ CGAL::Random_points_on_sphere_d<Point> generator(3, sphere_radius);
+ std::vector<Point> points;
+ points.reserve(num_points);
+
+ typename Kernel::Compute_coordinate_d k_coord =
+ k.compute_coordinate_d_object();
+ for (std::size_t i = 0; i < num_points;) {
+ Point p_sphere = *generator++; // First 3 coords
+
+ FT alpha = rng.get_double(0, 6.2832);
+ std::vector<FT> pt(5);
+ pt[0] = k_coord(p_sphere, 0);
+ pt[1] = k_coord(p_sphere, 1);
+ pt[2] = k_coord(p_sphere, 2);
+ pt[3] = std::cos(alpha);
+ pt[4] = std::sin(alpha);
+ Point p(pt.begin(), pt.end());
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+// a = big radius, b = small radius
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_3D(std::size_t num_points, double a, double b,
+ bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ double tmp = cos(u / 2) * sin(v) - sin(u / 2) * sin(2. * v);
+ Point p = construct_point(k,
+ (a + b * tmp) * cos(u),
+ (a + b * tmp) * sin(u),
+ b * (sin(u / 2) * sin(v) + cos(u / 2) * sin(2. * v)));
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+// a = big radius, b = small radius
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_4D(std::size_t num_points, double a, double b,
+ double noise = 0., bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ Point p = construct_point(k,
+ (a + b * cos(v)) * cos(u) + (noise == 0. ? 0. : rng.get_double(0, noise)),
+ (a + b * cos(v)) * sin(u) + (noise == 0. ? 0. : rng.get_double(0, noise)),
+ b * sin(v) * cos(u / 2) + (noise == 0. ? 0. : rng.get_double(0, noise)),
+ b * sin(v) * sin(u / 2) + (noise == 0. ? 0. : rng.get_double(0, noise)));
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+
+// a = big radius, b = small radius
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d>
+generate_points_on_klein_bottle_variant_5D(
+ std::size_t num_points, double a, double b, bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ FT x1 = (a + b * cos(v)) * cos(u);
+ FT x2 = (a + b * cos(v)) * sin(u);
+ FT x3 = b * sin(v) * cos(u / 2);
+ FT x4 = b * sin(v) * sin(u / 2);
+ FT x5 = x1 + x2 + x3 + x4;
+
+ Point p = construct_point(k, x1, x2, x3, x4, x5);
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+} // namespace Gudhi
+
+#endif // RANDOM_POINT_GENERATORS_H_
diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h
new file mode 100644
index 00000000..98335552
--- /dev/null
+++ b/src/common/include/gudhi/reader_utils.h
@@ -0,0 +1,357 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Clement Maria, Pawel Dlotko, Clement Jamin
+ *
+ * Copyright (C) 2014 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef READER_UTILS_H_
+#define READER_UTILS_H_
+
+#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Debug_utils.h>
+
+#include <boost/function_output_iterator.hpp>
+#include <boost/graph/adjacency_list.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <limits> // for numeric_limits
+#include <string>
+#include <vector>
+#include <utility> // for pair
+#include <tuple> // for std::make_tuple
+
+namespace Gudhi {
+
+// Keep this file tag for Doxygen to parse the code, otherwise, functions are not documented.
+// It is required for global functions and variables.
+
+/** @file
+ * @brief This file includes common file reader for GUDHI
+ */
+
+/**
+ * @brief Read a set of points to turn it into a vector< vector<double> > by filling points.
+ *
+ * File format: 1 point per line<br>
+ * X11 X12 ... X1d<br>
+ * X21 X22 ... X2d<br>
+ * etc<br>
+ */
+inline void read_points(std::string file_name, std::vector<std::vector<double>>& points) {
+ std::ifstream in_file(file_name.c_str(), std::ios::in);
+ if (!in_file.is_open()) {
+ std::cerr << "Unable to open file " << file_name << std::endl;
+ return;
+ }
+
+ std::string line;
+ double x;
+ while (getline(in_file, line)) {
+ std::vector<double> point;
+ std::istringstream iss(line);
+ while (iss >> x) {
+ point.push_back(x);
+ }
+ // Check for empty lines
+ if (!point.empty()) points.push_back(point);
+ }
+ in_file.close();
+}
+
+/**
+ * @brief Read a graph from a file.
+ *
+ * \tparam Graph_t Type for the return graph. Must be constructible from iterators on pairs of Vertex_handle
+ * \tparam Filtration_value Type for the value of the read filtration
+ * \tparam Vertex_handle Type for the value of the read vertices
+ *
+ * File format: 1 simplex per line<br>
+ * Dim1 X11 X12 ... X1d Fil1<br>
+ * Dim2 X21 X22 ... X2d Fil2<br>
+ * etc<br>
+ *
+ * The vertices must be labeled from 0 to n-1.
+ * Every simplex must appear exactly once.
+ * Simplices of dimension more than 1 are ignored.
+ */
+template <typename Graph_t, typename Filtration_value, typename Vertex_handle>
+Graph_t read_graph(std::string file_name) {
+ std::ifstream in_(file_name.c_str(), std::ios::in);
+ if (!in_.is_open()) {
+ std::string error_str("read_graph - Unable to open file ");
+ error_str.append(file_name);
+ std::cerr << error_str << std::endl;
+ throw std::invalid_argument(error_str);
+ }
+
+ typedef std::pair<Vertex_handle, Vertex_handle> Edge_t;
+ std::vector<Edge_t> edges;
+ std::vector<Filtration_value> edges_fil;
+ std::map<Vertex_handle, Filtration_value> vertices;
+
+ std::string line;
+ int dim;
+ Vertex_handle u, v, max_h = -1;
+ Filtration_value fil;
+ while (getline(in_, line)) {
+ std::istringstream iss(line);
+ while (iss >> dim) {
+ switch (dim) {
+ case 0: {
+ iss >> u;
+ iss >> fil;
+ vertices[u] = fil;
+ if (max_h < u) {
+ max_h = u;
+ }
+ break;
+ }
+ case 1: {
+ iss >> u;
+ iss >> v;
+ iss >> fil;
+ edges.push_back(Edge_t(u, v));
+ edges_fil.push_back(fil);
+ break;
+ }
+ default: { break; }
+ }
+ }
+ }
+ in_.close();
+
+ if ((size_t)(max_h + 1) != vertices.size()) {
+ std::cerr << "Error: vertices must be labeled from 0 to n-1 \n";
+ }
+
+ Graph_t skel_graph(edges.begin(), edges.end(), edges_fil.begin(), vertices.size());
+ auto vertex_prop = boost::get(vertex_filtration_t(), skel_graph);
+
+ typename boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
+ auto v_it = vertices.begin();
+ for (std::tie(vi, vi_end) = boost::vertices(skel_graph); vi != vi_end; ++vi, ++v_it) {
+ boost::put(vertex_prop, *vi, v_it->second);
+ }
+
+ return skel_graph;
+}
+
+/**
+ * @brief Read a face from a file.
+ *
+ * File format: 1 simplex per line<br>
+ * Dim1 X11 X12 ... X1d Fil1<br>
+ * Dim2 X21 X22 ... X2d Fil2<br>
+ * etc<br>
+ *
+ * The vertices must be labeled from 0 to n-1.
+ * Every simplex must appear exactly once.
+ * Simplices of dimension more than 1 are ignored.
+ */
+template <typename Vertex_handle, typename Filtration_value>
+bool read_simplex(std::istream& in_, std::vector<Vertex_handle>& simplex, Filtration_value& fil) {
+ int dim = 0;
+ if (!(in_ >> dim)) return false;
+ Vertex_handle v;
+ for (int i = 0; i < dim + 1; ++i) {
+ if (!(in_ >> v)) return false;
+ simplex.push_back(v);
+ }
+ if (!(in_ >> fil)) return false;
+ in_.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); // ignore until the carriage return
+ return true;
+}
+
+/**
+ * @brief Read a hasse simplex from a file.
+ *
+ * File format: 1 simplex per line<br>
+ * Dim1 k11 k12 ... k1Dim1 Fil1<br>
+ * Dim2 k21 k22 ... k2Dim2 Fil2<br>
+ * etc<br>
+ *
+ * The key of a simplex is its position in the filtration order and also the number of its row in the file.
+ * Dimi ki1 ki2 ... kiDimi Fili means that the ith simplex in the filtration has dimension Dimi, filtration value
+ * fil1 and simplices with key ki1 ... kiDimi in its boundary.*/
+template <typename Simplex_key, typename Filtration_value>
+bool read_hasse_simplex(std::istream& in_, std::vector<Simplex_key>& boundary, Filtration_value& fil) {
+ int dim;
+ if (!(in_ >> dim)) return false;
+ if (dim == 0) {
+ in_ >> fil;
+ return true;
+ }
+ Simplex_key key;
+ for (int i = 0; i < dim + 1; ++i) {
+ in_ >> key;
+ boundary.push_back(key);
+ }
+ in_ >> fil;
+ return true;
+}
+
+/**
+ * @brief Read a lower triangular distance matrix from a csv file. We assume that the .csv store the whole
+ * (square) matrix.
+ *
+ * @author Pawel Dlotko
+ *
+ * Square matrix file format:<br>
+ * 0;D12;...;D1j<br>
+ * D21;0;...;D2j<br>
+ * ...<br>
+ * Dj1;Dj2;...;0<br>
+ *
+ * lower matrix file format:<br>
+ * 0<br>
+ * D21;<br>
+ * D31;D32;<br>
+ * ...<br>
+ * Dj1;Dj2;...;Dj(j-1);<br>
+ *
+ **/
+template <typename Filtration_value>
+std::vector<std::vector<Filtration_value>> read_lower_triangular_matrix_from_csv_file(const std::string& filename,
+ const char separator = ';') {
+#ifdef DEBUG_TRACES
+ std::cout << "Using procedure read_lower_triangular_matrix_from_csv_file \n";
+#endif // DEBUG_TRACES
+ std::vector<std::vector<Filtration_value>> result;
+ std::ifstream in;
+ in.open(filename.c_str());
+ if (!in.is_open()) {
+ return result;
+ }
+
+ std::string line;
+
+ // the first line is emtpy, so we ignore it:
+ std::getline(in, line);
+ std::vector<Filtration_value> values_in_this_line;
+ result.push_back(values_in_this_line);
+
+ int number_of_line = 0;
+
+ // first, read the file line by line to a string:
+ while (std::getline(in, line)) {
+ // if line is empty, break
+ if (line.size() == 0) break;
+
+ // if the last element of a string is comma:
+ if (line[line.size() - 1] == separator) {
+ // then shrink the string by one
+ line.pop_back();
+ }
+
+ // replace all commas with spaces
+ std::replace(line.begin(), line.end(), separator, ' ');
+
+ // put the new line to a stream
+ std::istringstream iss(line);
+ // and now read the doubles.
+
+ int number_of_entry = 0;
+ std::vector<Filtration_value> values_in_this_line;
+ while (iss.good()) {
+ double entry;
+ iss >> entry;
+ if (number_of_entry <= number_of_line) {
+ values_in_this_line.push_back(entry);
+ }
+ ++number_of_entry;
+ }
+ if (!values_in_this_line.empty()) result.push_back(values_in_this_line);
+ ++number_of_line;
+ }
+ in.close();
+
+#ifdef DEBUG_TRACES
+ std::cerr << "Here is the matrix we read : \n";
+ for (size_t i = 0; i != result.size(); ++i) {
+ for (size_t j = 0; j != result[i].size(); ++j) {
+ std::cerr << result[i][j] << " ";
+ }
+ std::cerr << std::endl;
+ }
+#endif // DEBUG_TRACES
+
+ return result;
+} // read_lower_triangular_matrix_from_csv_file
+
+/**
+Reads a file containing persistence intervals.
+Each line might contain 2, 3 or 4 values: [[field] dimension] birth death
+The output iterator `out` is used this way: `*out++ = std::make_tuple(dim, birth, death);`
+where `dim` is an `int`, `birth` a `double`, and `death` a `double`.
+Note: the function does not check that birth <= death.
+**/
+template <typename OutputIterator>
+void read_persistence_intervals_and_dimension(std::string const& filename, OutputIterator out) {
+ std::ifstream in(filename);
+ if (!in.is_open()) {
+ std::string error_str("read_persistence_intervals_and_dimension - Unable to open file ");
+ error_str.append(filename);
+ std::cerr << error_str << std::endl;
+ throw std::invalid_argument(error_str);
+ }
+
+ while (!in.eof()) {
+ std::string line;
+ getline(in, line);
+ if (line.length() != 0 && line[0] != '#') {
+ double numbers[4];
+ int n = sscanf(line.c_str(), "%lf %lf %lf %lf", &numbers[0], &numbers[1], &numbers[2], &numbers[3]);
+ if (n >= 2) {
+ int dim = (n >= 3 ? static_cast<int>(numbers[n - 3]) : -1);
+ *out++ = std::make_tuple(dim, numbers[n - 2], numbers[n - 1]);
+ }
+ }
+ }
+}
+
+/**
+Reads a file containing persistence intervals.
+Each line might contain 2, 3 or 4 values: [[field] dimension] birth death
+The return value is an `std::map<dim, std::vector<std::pair<birth, death>>>`
+where `dim` is an `int`, `birth` a `double`, and `death` a `double`.
+Note: the function does not check that birth <= death.
+**/
+inline std::map<int, std::vector<std::pair<double, double>>> read_persistence_intervals_grouped_by_dimension(
+ std::string const& filename) {
+ std::map<int, std::vector<std::pair<double, double>>> ret;
+ read_persistence_intervals_and_dimension(
+ filename, boost::make_function_output_iterator([&ret](std::tuple<int, double, double> t) {
+ ret[get<0>(t)].push_back(std::make_pair(get<1>(t), get<2>(t)));
+ }));
+ return ret;
+}
+
+/**
+Reads a file containing persistence intervals.
+Each line might contain 2, 3 or 4 values: [[field] dimension] birth death
+If `only_this_dim` = -1, dimension is ignored and all lines are returned.
+If `only_this_dim` is >= 0, only the lines where dimension = `only_this_dim`
+(or where dimension is not specified) are returned.
+The return value is an `std::vector<std::pair<birth, death>>`
+where `dim` is an `int`, `birth` a `double`, and `death` a `double`.
+Note: the function does not check that birth <= death.
+**/
+inline std::vector<std::pair<double, double>> read_persistence_intervals_in_dimension(std::string const& filename,
+ int only_this_dim = -1) {
+ std::vector<std::pair<double, double>> ret;
+ read_persistence_intervals_and_dimension(
+ filename, boost::make_function_output_iterator([only_this_dim, &ret](std::tuple<int, double, double> t) {
+ if (only_this_dim == get<0>(t) || only_this_dim == -1) ret.emplace_back(get<1>(t), get<2>(t));
+ }));
+ return ret;
+}
+
+} // namespace Gudhi
+
+#endif // READER_UTILS_H_
diff --git a/src/common/include/gudhi/writing_persistence_to_file.h b/src/common/include/gudhi/writing_persistence_to_file.h
new file mode 100644
index 00000000..2e36b831
--- /dev/null
+++ b/src/common/include/gudhi/writing_persistence_to_file.h
@@ -0,0 +1,105 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Pawel Dlotko
+ *
+ * Copyright (C) 2017 Swansea University, UK
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef WRITING_PERSISTENCE_TO_FILE_H_
+#define WRITING_PERSISTENCE_TO_FILE_H_
+
+#include <iostream>
+#include <string>
+#include <limits>
+
+namespace Gudhi {
+
+/**
+* This is a class to store persistence intervals. Its main purpose is to
+* exchange data in between different packages and provide unified way
+* of writing a collection of persistence intervals to file.
+**/
+template <typename Filtration_type, typename Coefficient_field>
+class Persistence_interval_common {
+ public:
+ /**
+ * Constructor taking as an input birth and death of the pair.
+ **/
+ Persistence_interval_common(Filtration_type birth, Filtration_type death)
+ : birth_(birth),
+ death_(death),
+ dimension_(std::numeric_limits<unsigned>::max()),
+ arith_element_(std::numeric_limits<Coefficient_field>::max()) {}
+
+ /**
+ * Constructor taking as an input birth, death and dimension of the pair.
+ **/
+ Persistence_interval_common(Filtration_type birth, Filtration_type death, unsigned dim)
+ : birth_(birth), death_(death), dimension_(dim), arith_element_(std::numeric_limits<Coefficient_field>::max()) {}
+
+ /**
+* Constructor taking as an input birth, death, dimension of the pair as well
+* as the number p such that this interval is present over Z_p field.
+**/
+ Persistence_interval_common(Filtration_type birth, Filtration_type death, unsigned dim, Coefficient_field field)
+ : birth_(birth), death_(death), dimension_(dim), arith_element_(field) {}
+
+ /**
+ * Operator to compare two persistence pairs. During the comparision all the
+ * fields: birth, death, dimensiona and arith_element_ are taken into account
+ * and they all have to be equal for two pairs to be equal.
+ **/
+ bool operator==(const Persistence_interval_common& i2) const {
+ return ((this->birth_ == i2.birth_) && (this->death_ == i2.death_) && (this->dimension_ == i2.dimension_) &&
+ (this->arith_element_ == i2.arith_element_));
+ }
+
+ /**
+ * Check if two persistence paris are not equal.
+ **/
+ bool operator!=(const Persistence_interval_common& i2) const { return (!((*this) == i2)); }
+
+ /**
+ * Operator to compare objects of a type Persistence_interval_common.
+ * One intervals is smaller than the other if it has lower persistence.
+ * Note that this operator do not take Arith_element into account when doing comparisions.
+ **/
+ bool operator<(const Persistence_interval_common& i2) const {
+ return fabs(this->death_ - this->birth_) < fabs(i2.death_ - i2.birth_);
+ }
+
+ friend std::ostream& operator<<(std::ostream& out, const Persistence_interval_common& it) {
+ if (it.arith_element_ != std::numeric_limits<Coefficient_field>::max()) {
+ out << it.arith_element_ << " ";
+ }
+ if (it.dimension_ != std::numeric_limits<unsigned>::max()) {
+ out << it.dimension_ << " ";
+ }
+ out << it.birth_ << " " << it.death_ << " ";
+ return out;
+ }
+
+ private:
+ Filtration_type birth_;
+ Filtration_type death_;
+ unsigned dimension_;
+ Coefficient_field arith_element_;
+};
+
+/**
+ * This function write a vector<Persistence_interval_common> to a stream
+**/
+template <typename Persistence_interval_range>
+void write_persistence_intervals_to_stream(const Persistence_interval_range& intervals,
+ std::ostream& out = std::cout) {
+ for (auto interval : intervals) {
+ out << interval << "\n";
+ }
+}
+
+} // namespace Gudhi
+
+#endif // WRITING_PERSISTENCE_TO_FILE_H_
diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt
new file mode 100644
index 00000000..0b49fa1e
--- /dev/null
+++ b/src/common/test/CMakeLists.txt
@@ -0,0 +1,24 @@
+project(Common_tests)
+
+include(GUDHI_test_coverage)
+
+add_executable ( Common_test_points_off_reader test_points_off_reader.cpp )
+target_link_libraries(Common_test_points_off_reader ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+add_executable ( Common_test_distance_matrix_reader test_distance_matrix_reader.cpp )
+target_link_libraries(Common_test_distance_matrix_reader ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+add_executable ( Common_test_persistence_intervals_reader test_persistence_intervals_reader.cpp )
+target_link_libraries(Common_test_persistence_intervals_reader ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
+# Do not forget to copy test files in current binary dir
+file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+file(COPY "${CMAKE_SOURCE_DIR}/src/common/test/persistence_intervals_with_dimension.pers" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+file(COPY "${CMAKE_SOURCE_DIR}/src/common/test/persistence_intervals_with_field.pers" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+file(COPY "${CMAKE_SOURCE_DIR}/src/common/test/persistence_intervals_without_dimension.pers" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+
+gudhi_add_coverage_test(Common_test_points_off_reader)
+gudhi_add_coverage_test(Common_test_distance_matrix_reader)
+gudhi_add_coverage_test(Common_test_persistence_intervals_reader)
diff --git a/src/common/test/README b/src/common/test/README
new file mode 100644
index 00000000..a8e6efe9
--- /dev/null
+++ b/src/common/test/README
@@ -0,0 +1,14 @@
+To compile:
+***********
+
+cmake .
+make
+
+To launch with details:
+***********************
+
+./Common_test_points_off_reader --report_level=detailed --log_level=all
+
+ ==> echo $? returns 0 in case of success (non-zero otherwise)
+
+
diff --git a/src/common/test/dtoffrw_alphashapedoc_result.off b/src/common/test/dtoffrw_alphashapedoc_result.off
new file mode 100644
index 00000000..1deb8dbd
--- /dev/null
+++ b/src/common/test/dtoffrw_alphashapedoc_result.off
@@ -0,0 +1,7 @@
+Point[0] = 1 1
+Point[1] = 7 0
+Point[2] = 4 6
+Point[3] = 9 6
+Point[4] = 0 14
+Point[5] = 2 19
+Point[6] = 9 17
diff --git a/src/common/test/persistence_intervals_with_dimension.pers b/src/common/test/persistence_intervals_with_dimension.pers
new file mode 100644
index 00000000..406748c8
--- /dev/null
+++ b/src/common/test/persistence_intervals_with_dimension.pers
@@ -0,0 +1,5 @@
+# Simple persistence diagram with dimension
+0 2.7 3.7
+1 9.6 14.
+3 34.2 34.974
+1 3. inf
diff --git a/src/common/test/persistence_intervals_with_field.pers b/src/common/test/persistence_intervals_with_field.pers
new file mode 100644
index 00000000..41dd9f1e
--- /dev/null
+++ b/src/common/test/persistence_intervals_with_field.pers
@@ -0,0 +1,4 @@
+3 0 2.7 3.7
+3 1 9.6 14.
+3 3 34.2 34.974
+3 1 3. inf
diff --git a/src/common/test/persistence_intervals_without_dimension.pers b/src/common/test/persistence_intervals_without_dimension.pers
new file mode 100644
index 00000000..76fa27f3
--- /dev/null
+++ b/src/common/test/persistence_intervals_without_dimension.pers
@@ -0,0 +1,7 @@
+# Simple persistence diagram without dimension
+2.7 3.7
+9.6 14.
+# Another comment
+34.2 34.974
+3. inf
+# End of file
diff --git a/src/common/test/test_distance_matrix_reader.cpp b/src/common/test/test_distance_matrix_reader.cpp
new file mode 100644
index 00000000..bb619a29
--- /dev/null
+++ b/src/common/test/test_distance_matrix_reader.cpp
@@ -0,0 +1,73 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Vincent Rouvreau
+ *
+ * Copyright (C) 2016 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#include <gudhi/reader_utils.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "distance_matrix_reader"
+#include <boost/test/unit_test.hpp>
+
+using Distance_matrix = std::vector<std::vector<double>>;
+
+BOOST_AUTO_TEST_CASE( lower_triangular_distance_matrix )
+{
+ Distance_matrix from_lower_triangular;
+ // Read lower_triangular_distance_matrix.csv file where the separator is a ','
+ from_lower_triangular = Gudhi::read_lower_triangular_matrix_from_csv_file<double>("lower_triangular_distance_matrix.csv",
+ ',');
+ for (auto& i : from_lower_triangular) {
+ for (auto j : i) {
+ std::cout << j << " ";
+ }
+ std::cout << std::endl;
+ }
+ std::cout << "from_lower_triangular size = " << from_lower_triangular.size() << std::endl;
+ BOOST_CHECK(from_lower_triangular.size() == 5);
+
+ for (std::size_t i = 0; i < from_lower_triangular.size(); i++) {
+ std::cout << "from_lower_triangular[" << i << "] size = " << from_lower_triangular[i].size() << std::endl;
+ BOOST_CHECK(from_lower_triangular[i].size() == i);
+ }
+ std::vector<double> expected = {1};
+ BOOST_CHECK(from_lower_triangular[1] == expected);
+
+ expected = {2,3};
+ BOOST_CHECK(from_lower_triangular[2] == expected);
+
+ expected = {4,5,6};
+ BOOST_CHECK(from_lower_triangular[3] == expected);
+
+ expected = {7,8,9,10};
+ BOOST_CHECK(from_lower_triangular[4] == expected);
+
+}
+
+BOOST_AUTO_TEST_CASE( full_square_distance_matrix )
+{
+ Distance_matrix from_full_square;
+ // Read full_square_distance_matrix.csv file where the separator is the default one ';'
+ from_full_square = Gudhi::read_lower_triangular_matrix_from_csv_file<double>("full_square_distance_matrix.csv");
+ for (auto& i : from_full_square) {
+ for (auto j : i) {
+ std::cout << j << " ";
+ }
+ std::cout << std::endl;
+ }
+ std::cout << "from_full_square size = " << from_full_square.size() << std::endl;
+ BOOST_CHECK(from_full_square.size() == 7);
+ for (std::size_t i = 0; i < from_full_square.size(); i++) {
+ std::cout << "from_full_square[" << i << "] size = " << from_full_square[i].size() << std::endl;
+ BOOST_CHECK(from_full_square[i].size() == i);
+ }
+}
diff --git a/src/common/test/test_persistence_intervals_reader.cpp b/src/common/test/test_persistence_intervals_reader.cpp
new file mode 100644
index 00000000..8fb4377d
--- /dev/null
+++ b/src/common/test/test_persistence_intervals_reader.cpp
@@ -0,0 +1,310 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Vincent Rouvreau
+ *
+ * Copyright (C) 2017 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#include <gudhi/reader_utils.h>
+
+#include <iostream>
+#include <vector>
+#include <utility> // for pair
+#include <tuple>
+#include <limits> // for inf
+#include <map>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "persistence_intervals_reader"
+#include <boost/test/unit_test.hpp>
+
+using Persistence_intervals_by_dimension = std::map<int, std::vector<std::pair<double, double>>>;
+using Persistence_intervals = std::vector<std::pair<double, double>>;
+// Test files with only 2 parameters (persistence birth and death) per line in file
+BOOST_AUTO_TEST_CASE( persistence_intervals_without_dimension )
+{
+ Persistence_intervals_by_dimension expected_intervals_by_dimension;
+ expected_intervals_by_dimension[-1].push_back(std::make_pair(2.7, 3.7));
+ expected_intervals_by_dimension[-1].push_back(std::make_pair(9.6, 14.));
+ expected_intervals_by_dimension[-1].push_back(std::make_pair(34.2, 34.974));
+ expected_intervals_by_dimension[-1].push_back(std::make_pair(3., std::numeric_limits<double>::infinity()));
+
+ Persistence_intervals_by_dimension persistence_intervals_by_dimension =
+ Gudhi::read_persistence_intervals_grouped_by_dimension("persistence_intervals_without_dimension.pers");
+
+ std::cout << "\nread_persistence_intervals_grouped_by_dimension - expected\n";
+ for (auto map_iter : expected_intervals_by_dimension) {
+ std::cout << "key=" << map_iter.first;
+ for (auto vec_iter : map_iter.second)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+ }
+
+ std::cout << "\nread_persistence_intervals_grouped_by_dimension - read\n";
+ for (auto map_iter : persistence_intervals_by_dimension) {
+ std::cout << "key=" << map_iter.first;
+ for (auto vec_iter : map_iter.second)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+ }
+
+ BOOST_CHECK(persistence_intervals_by_dimension == expected_intervals_by_dimension);
+
+ Persistence_intervals expected_intervals_in_dimension;
+ expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7));
+ expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.));
+ expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974));
+ expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity()));
+
+ Persistence_intervals persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers");
+
+ std::cout << "\nread_persistence_intervals_in_dimension - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension - read\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 0);
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 1);
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 2);
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_without_dimension.pers", 3);
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+}
+// Test files with 3 parameters (dimension birth death) per line in file
+BOOST_AUTO_TEST_CASE( persistence_intervals_with_dimension )
+{
+ Persistence_intervals_by_dimension expected_intervals_by_dimension;
+ expected_intervals_by_dimension[0].push_back(std::make_pair(2.7, 3.7));
+ expected_intervals_by_dimension[1].push_back(std::make_pair(9.6, 14.));
+ expected_intervals_by_dimension[3].push_back(std::make_pair(34.2, 34.974));
+ expected_intervals_by_dimension[1].push_back(std::make_pair(3., std::numeric_limits<double>::infinity()));
+
+ Persistence_intervals_by_dimension persistence_intervals_by_dimension =
+ Gudhi::read_persistence_intervals_grouped_by_dimension("persistence_intervals_with_dimension.pers");
+
+ std::cout << "\nread_persistence_intervals_grouped_by_dimension - expected\n";
+ for (auto map_iter : expected_intervals_by_dimension) {
+ std::cout << "key=" << map_iter.first;
+ for (auto vec_iter : map_iter.second)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+ }
+
+ std::cout << "\nread_persistence_intervals_grouped_by_dimension - read\n";
+ for (auto map_iter : persistence_intervals_by_dimension) {
+ std::cout << "key=" << map_iter.first;
+ for (auto vec_iter : map_iter.second)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+ }
+
+ BOOST_CHECK(persistence_intervals_by_dimension == expected_intervals_by_dimension);
+
+ Persistence_intervals expected_intervals_in_dimension;
+ expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7));
+ expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.));
+ expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974));
+ expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity()));
+
+ Persistence_intervals persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers");
+
+ std::cout << "\nread_persistence_intervals_in_dimension - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7));
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 0);
+
+ std::cout << "\nread_persistence_intervals_in_dimension 0 - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension 0 - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.));
+ expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity()));
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 1);
+
+ std::cout << "\nread_persistence_intervals_in_dimension 1 - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension 1 - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 2);
+
+ std::cout << "\nread_persistence_intervals_in_dimension 2 - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension 2 - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974));
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_dimension.pers", 3);
+
+ std::cout << "\nread_persistence_intervals_in_dimension 3 - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension 3 - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+}
+
+// Test files with 4 parameters (field dimension birth death) per line in file
+BOOST_AUTO_TEST_CASE( persistence_intervals_with_field )
+{
+ Persistence_intervals_by_dimension expected_intervals_by_dimension;
+ expected_intervals_by_dimension[0].push_back(std::make_pair(2.7, 3.7));
+ expected_intervals_by_dimension[1].push_back(std::make_pair(9.6, 14.));
+ expected_intervals_by_dimension[3].push_back(std::make_pair(34.2, 34.974));
+ expected_intervals_by_dimension[1].push_back(std::make_pair(3., std::numeric_limits<double>::infinity()));
+
+ Persistence_intervals_by_dimension persistence_intervals_by_dimension =
+ Gudhi::read_persistence_intervals_grouped_by_dimension("persistence_intervals_with_field.pers");
+
+ std::cout << "\nread_persistence_intervals_grouped_by_dimension - expected\n";
+ for (auto map_iter : expected_intervals_by_dimension) {
+ std::cout << "key=" << map_iter.first;
+ for (auto vec_iter : map_iter.second)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+ }
+
+ std::cout << "\nread_persistence_intervals_grouped_by_dimension - read\n";
+ for (auto map_iter : persistence_intervals_by_dimension) {
+ std::cout << "key=" << map_iter.first;
+ for (auto vec_iter : map_iter.second)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+ }
+
+ BOOST_CHECK(persistence_intervals_by_dimension == expected_intervals_by_dimension);
+
+ Persistence_intervals expected_intervals_in_dimension;
+ expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7));
+ expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.));
+ expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974));
+ expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity()));
+
+ Persistence_intervals persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers");
+
+ std::cout << "\nread_persistence_intervals_in_dimension - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ expected_intervals_in_dimension.push_back(std::make_pair(2.7, 3.7));
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 0);
+
+ std::cout << "\nread_persistence_intervals_in_dimension 0 - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension 0 - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ expected_intervals_in_dimension.push_back(std::make_pair(9.6, 14.));
+ expected_intervals_in_dimension.push_back(std::make_pair(3., std::numeric_limits<double>::infinity()));
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 1);
+
+ std::cout << "\nread_persistence_intervals_in_dimension 1 - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension 1 - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 2);
+
+ std::cout << "\nread_persistence_intervals_in_dimension 2 - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension 2 - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+ expected_intervals_in_dimension.clear();
+ expected_intervals_in_dimension.push_back(std::make_pair(34.2, 34.974));
+ persistence_intervals_in_dimension =
+ Gudhi::read_persistence_intervals_in_dimension("persistence_intervals_with_field.pers", 3);
+
+ std::cout << "\nread_persistence_intervals_in_dimension 3 - expected\n";
+ for (auto vec_iter : expected_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ std::cout << "\nread_persistence_intervals_in_dimension 3 - read\n";
+ for (auto vec_iter : persistence_intervals_in_dimension)
+ std::cout << " [" << vec_iter.first << " ," << vec_iter.second << "] ";
+
+ BOOST_CHECK(persistence_intervals_in_dimension == expected_intervals_in_dimension);
+
+}
diff --git a/src/common/test/test_points_off_reader.cpp b/src/common/test/test_points_off_reader.cpp
new file mode 100644
index 00000000..f190a13e
--- /dev/null
+++ b/src/common/test/test_points_off_reader.cpp
@@ -0,0 +1,61 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Vincent Rouvreau
+ *
+ * Copyright (C) 2015 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#include <gudhi/Points_off_io.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "points_off_read_write"
+#include <boost/test/unit_test.hpp>
+
+using Point_d = std::vector<double>;
+
+BOOST_AUTO_TEST_CASE( points_doc_test )
+{
+ // Read the OFF file (input file name given as parameter) and triangulates points
+ Gudhi::Points_off_reader<Point_d> off_reader("alphacomplexdoc.off");
+ // Check the read operation was correct
+ BOOST_CHECK(off_reader.is_valid());
+
+ // Retrieve the triangulation
+ std::vector<Point_d> point_cloud = off_reader.get_point_cloud();
+ BOOST_CHECK(point_cloud.size() == 7);
+
+ std::vector<Point_d> expected_points;
+ std::vector<double> point = {1.0, 1.0, 0.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {7.0, 0.0, 0.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {4.0, 6.0, 0.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {9.0, 6.0, 0.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {0.0, 14.0, 0.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {2.0, 19.0, 0.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+ point = {9.0, 17.0, 0.0};
+ expected_points.push_back(Point_d(point.begin(), point.end()));
+
+ BOOST_CHECK(point_cloud == expected_points);
+}
+
+BOOST_AUTO_TEST_CASE( Delaunay_triangulation_unexisting_file_read_test )
+{
+ Gudhi::Points_off_reader<Point_d> off_reader("some_impossible_weird_file_name.off");
+ // Check the read operation was correct
+ BOOST_CHECK(!off_reader.is_valid());
+
+ std::vector<Point_d> point_cloud = off_reader.get_point_cloud();
+ BOOST_CHECK(point_cloud.size() == 0);
+}
diff --git a/src/common/utilities/CMakeLists.txt b/src/common/utilities/CMakeLists.txt
new file mode 100644
index 00000000..3dcfe84d
--- /dev/null
+++ b/src/common/utilities/CMakeLists.txt
@@ -0,0 +1,16 @@
+project(off_file_from_shape_generator)
+
+if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ add_executable ( off_file_from_shape_generator off_file_from_shape_generator.cpp )
+ add_test(NAME off_file_from_shape_generator_on_sphere_1000_3_15.2 COMMAND $<TARGET_FILE:off_file_from_shape_generator>
+ "on" "sphere" "onSphere.off" "1000" "3" "15.2")
+ add_test(NAME off_file_from_shape_generator_in_sphere_100_2 COMMAND $<TARGET_FILE:off_file_from_shape_generator>
+ "in" "sphere" "inSphere.off" "100" "2")
+
+ # on cube is not available in CGAL
+ add_test(NAME off_file_from_shape_generator_in_cube_10000_3_5.8 COMMAND $<TARGET_FILE:off_file_from_shape_generator>
+ "in" "cube" "inCube.off" "10000" "3" "5.8")
+
+ install(TARGETS off_file_from_shape_generator DESTINATION bin)
+
+endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
diff --git a/src/common/utilities/off_file_from_shape_generator.cpp b/src/common/utilities/off_file_from_shape_generator.cpp
new file mode 100644
index 00000000..6efef4fc
--- /dev/null
+++ b/src/common/utilities/off_file_from_shape_generator.cpp
@@ -0,0 +1,177 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Vincent Rouvreau
+ *
+ * Copyright (C) 2014 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#include <gudhi/random_point_generators.h>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/algorithm.h>
+#include <CGAL/assertions.h>
+
+#include <iostream>
+#include <iterator>
+#include <vector>
+#include <fstream> // for std::ofstream
+#include <cstdlib>
+
+typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > K;
+typedef K::Point_d Point;
+
+void usage(char * const progName) {
+ std::cerr << "Usage: " << progName << " in|on sphere|cube off_file_name points_number[integer > 0] " <<
+ "dimension[integer > 1] radius[double > 0.0 | default = 1.0]" << std::endl;
+ exit(-1);
+}
+
+int main(int argc, char **argv) {
+ // program args management
+ if ((argc != 6) && (argc != 7)) {
+ std::cerr << "Error: Number of arguments (" << argc << ") is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ int points_number = atoi(argv[4]);
+ if (points_number <= 0) {
+ std::cerr << "Error: " << argv[4] << " is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ int dimension = atoi(argv[5]);
+ if (dimension <= 0) {
+ std::cerr << "Error: " << argv[5] << " is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ double radius = 1.0;
+ if (argc == 7) {
+ radius = atof(argv[6]);
+ if (radius <= 0.0) {
+ std::cerr << "Error: " << argv[6] << " is not correct" << std::endl;
+ usage(argv[0]);
+ }
+ }
+
+ bool in = false;
+ if (strcmp(argv[1], "in") == 0) {
+ in = true;
+ } else if (strcmp(argv[1], "on") != 0) {
+ std::cerr << "Error: " << argv[1] << " is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ enum class Data_shape { sphere, cube, curve, torus, klein, undefined};
+
+ Data_shape shape = Data_shape::undefined;
+ if (memcmp(argv[2], "sphere", sizeof("sphere")) == 0) {
+ shape = Data_shape::sphere;
+ } else if (memcmp(argv[2], "cube", sizeof("cube")) == 0) {
+ shape = Data_shape::cube;
+ } else if (memcmp(argv[2], "curve", sizeof("curve")) == 0) {
+ shape = Data_shape::curve;
+ } else if (memcmp(argv[2], "torus", sizeof("torus")) == 0) {
+ shape = Data_shape::torus;
+ } else if (memcmp(argv[2], "klein", sizeof("klein")) == 0) {
+ shape = Data_shape::klein;
+ } else {
+ std::cerr << "Error: " << argv[2] << " is not correct" << std::endl;
+ usage(argv[0]);
+ }
+
+ std::ofstream diagram_out(argv[3]);
+ if (dimension == 3) {
+ diagram_out << "OFF" << std::endl;
+ diagram_out << points_number << " 0 0" << std::endl;
+ } else {
+ diagram_out << "nOFF" << std::endl;
+ diagram_out << dimension << " " << points_number << " 0 0" << std::endl;
+ }
+
+ if (diagram_out.is_open()) {
+ // Generate "points_number" random points in a vector
+ std::vector<Point> points;
+ if (in) {
+ switch (shape) {
+ case Data_shape::sphere:
+ points = Gudhi::generate_points_in_ball_d<K>(points_number, dimension, radius);
+ break;
+ case Data_shape::cube:
+ points = Gudhi::generate_points_in_ball_d<K>(points_number, dimension, radius);
+ break;
+ case Data_shape::curve:
+ std::cerr << "Sorry: in curve is not available" << std::endl;
+ usage(argv[0]);
+ break;
+ case Data_shape::torus:
+ std::cerr << "Sorry: in torus is not available" << std::endl;
+ usage(argv[0]);
+ break;
+ case Data_shape::klein:
+ std::cerr << "Sorry: in klein is not available" << std::endl;
+ usage(argv[0]);
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ } else { // means "on"
+ switch (shape) {
+ case Data_shape::sphere:
+ points = Gudhi::generate_points_on_sphere_d<K>(points_number, dimension, radius);
+ break;
+ case Data_shape::cube:
+ std::cerr << "Sorry: on cube is not available" << std::endl;
+ usage(argv[0]);
+ break;
+ case Data_shape::curve:
+ points = Gudhi::generate_points_on_moment_curve<K>(points_number, dimension, -radius/2., radius/2.);
+ break;
+ case Data_shape::torus:
+ if (dimension == 3)
+ points = Gudhi::generate_points_on_torus_3D<K>(points_number, dimension, radius, radius/2.);
+ else
+ points = Gudhi::generate_points_on_torus_d<K>(points_number, dimension, true);
+ break;
+ case Data_shape::klein:
+ switch (dimension) {
+ case 3:
+ points = Gudhi::generate_points_on_klein_bottle_3D<K>(points_number, radius, radius/2., true);
+ break;
+ case 4:
+ points = Gudhi::generate_points_on_klein_bottle_4D<K>(points_number, radius, radius/2., 0., true);
+ break;
+ case 5:
+ points = Gudhi::generate_points_on_klein_bottle_variant_5D<K>(points_number, radius, radius/2., true);
+ break;
+ default:
+ std::cerr << "Sorry: on klein is only available for dimension 3, 4 and 5" << std::endl;
+ usage(argv[0]);
+ break;
+ }
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ for (auto thePoint : points) {
+ int i = 0;
+ for (; i < dimension - 1; i++) {
+ diagram_out << thePoint[i] << " ";
+ }
+ diagram_out << thePoint[i] << std::endl; // last point + Carriage Return
+ }
+ } else {
+ std::cerr << "Error: " << argv[3] << " cannot be opened" << std::endl;
+ usage(argv[0]);
+ }
+
+ return 0;
+}
+
diff --git a/src/common/utilities/pointsetgenerator.md b/src/common/utilities/pointsetgenerator.md
new file mode 100644
index 00000000..c8c819b7
--- /dev/null
+++ b/src/common/utilities/pointsetgenerator.md
@@ -0,0 +1,39 @@
+---
+layout: page
+title: "OFF point set generator"
+meta_title: "OFF point set generator"
+teaser: ""
+permalink: /pointsetgenerator/
+---
+{::comment}
+Leave the lines above as it is required by the web site generator 'Jekyll'
+{:/comment}
+
+
+Generates a pointset and save it in an OFF file. Command-line is:
+
+```
+off_file_from_shape_generator on|in sphere|cube|curve|torus|klein <filename> <num_points> <dimension> <parameter1> <parameter2>...
+```
+
+Warning: "on cube" generator is not available!
+
+**Examples**
+
+```
+off_file_from_shape_generator on sphere onSphere.off 1000 3 15.2
+```
+
+* Generates an onSphere.off file with 1000 points randomized on a sphere of dimension 3 and radius 15.2.
+
+```
+off_file_from_shape_generator in sphere inSphere.off 100 2
+```
+
+* Generates an inSphere.off file with 100 points randomized in a sphere of dimension 2 (circle) and radius 1.0 (default).
+
+```
+off_file_from_shape_generator in cube inCube.off 10000 3 5.8
+```
+
+* Generates a inCube.off file with 10000 points randomized in a cube of dimension 3 and side 5.8.