diff options
26 files changed, 326 insertions, 144 deletions
diff --git a/data/points/Kl.off b/data/points/Kl.off index 911bcd23..8930a321 100644 --- a/data/points/Kl.off +++ b/data/points/Kl.off @@ -1,5 +1,5 @@ -OFF -10000 0 0 +nOFF +5 10000 0 0 0.5 0 0 0 1 0.562791 0 0.125333 0 0.998027 0.625333 0 0.24869 0 0.992115 diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 63c6675c..91305032 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -34,6 +34,7 @@ #include <CGAL/Epick_d.h> #include <CGAL/Spatial_sort_traits_adapter_d.h> #include <CGAL/property_map.h> // for CGAL::Identity_property_map +#include <CGAL/NT_converter.h> #include <iostream> #include <vector> @@ -323,8 +324,9 @@ class Alpha_complex { if (f_simplex_dim > 0) { // squared_radius function initialization Squared_Radius squared_radius = kernel_.compute_squared_radius_d_object(); + CGAL::NT_converter<typename Geom_traits::FT, Filtration_value> cv; - alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end()); + alpha_complex_filtration = cv(squared_radius(pointVector.begin(), pointVector.end())); } complex.assign_filtration(f_simplex, alpha_complex_filtration); #ifdef DEBUG_TRACES diff --git a/src/Alpha_complex/utilities/alphacomplex.md b/src/Alpha_complex/utilities/alphacomplex.md index aace85d3..ede749a9 100644 --- a/src/Alpha_complex/utilities/alphacomplex.md +++ b/src/Alpha_complex/utilities/alphacomplex.md @@ -1,3 +1,13 @@ +---
+layout: page
+title: "Alpha complex"
+meta_title: "Alpha complex"
+teaser: ""
+permalink: /alphacomplex/
+---
+{::comment}
+Leave the lines above as it is required by the web site generator 'Jekyll'
+{:/comment}
# Alpha complex #
diff --git a/src/Bitmap_cubical_complex/utilities/cubicalcomplex.md b/src/Bitmap_cubical_complex/utilities/cubicalcomplex.md index 6e1b2578..a1bb9007 100644 --- a/src/Bitmap_cubical_complex/utilities/cubicalcomplex.md +++ b/src/Bitmap_cubical_complex/utilities/cubicalcomplex.md @@ -1,3 +1,13 @@ +---
+layout: page
+title: "Cubical complex"
+meta_title: "Cubical complex"
+teaser: ""
+permalink: /cubicalcomplex/
+---
+{::comment}
+Leave the lines above as it is required by the web site generator 'Jekyll'
+{:/comment}
# Cubical complex#
diff --git a/src/Bottleneck_distance/utilities/bottleneckdistance.md b/src/Bottleneck_distance/utilities/bottleneckdistance.md index 526f5822..f2749acc 100644 --- a/src/Bottleneck_distance/utilities/bottleneckdistance.md +++ b/src/Bottleneck_distance/utilities/bottleneckdistance.md @@ -1,3 +1,13 @@ +---
+layout: page
+title: "Bottleneck distance"
+meta_title: "Bottleneck distance"
+teaser: ""
+permalink: /bottleneckdistance/
+---
+{::comment}
+Leave the lines above as it is required by the web site generator 'Jekyll'
+{:/comment}
# Bottleneck distance #
diff --git a/src/GudhUI/model/Model.h b/src/GudhUI/model/Model.h index fc284cc6..072d1185 100644 --- a/src/GudhUI/model/Model.h +++ b/src/GudhUI/model/Model.h @@ -74,7 +74,7 @@ class CGAL_geometric_flag_complex_wrapper { // std::cout << "size:" << vertices.size() << std::endl; for (std::size_t i = 0; i < vertices.size(); ++i) for (std::size_t j = i + 1; j < vertices.size(); ++j) - complex_.add_edge(Vertex_handle(vertices[i]), Vertex_handle(vertices[j])); + complex_.add_edge_without_blockers(Vertex_handle(vertices[i]), Vertex_handle(vertices[j])); } } diff --git a/src/GudhUI/utils/Critical_points.h b/src/GudhUI/utils/Critical_points.h index 2a18e079..e7b9ef31 100644 --- a/src/GudhUI/utils/Critical_points.h +++ b/src/GudhUI/utils/Critical_points.h @@ -79,7 +79,7 @@ template<typename SkBlComplex> class Critical_points { unsigned pos = 0; for (Edge e : edges) { std::cout << "edge " << pos++ << "/" << edges.size() << "\n"; - auto eh = filled_complex_.add_edge(e.first, e.second); + auto eh = filled_complex_.add_edge_without_blockers(e.first, e.second); int is_contractible(is_link_reducible(eh)); switch (is_contractible) { diff --git a/src/GudhUI/utils/K_nearest_builder.h b/src/GudhUI/utils/K_nearest_builder.h index 7be0a4f4..4000a331 100644 --- a/src/GudhUI/utils/K_nearest_builder.h +++ b/src/GudhUI/utils/K_nearest_builder.h @@ -81,7 +81,7 @@ template<typename SkBlComplex> class K_nearest_builder { for (auto it = ++search.begin(); it != search.end(); ++it) { Vertex_handle q(std::get<1>(it->first)); if (p != q && complex_.contains_vertex(p) && complex_.contains_vertex(q)) - complex_.add_edge(p, q); + complex_.add_edge_without_blockers(p, q); } } } diff --git a/src/GudhUI/utils/Rips_builder.h b/src/GudhUI/utils/Rips_builder.h index b22f4db6..59b4bee2 100644 --- a/src/GudhUI/utils/Rips_builder.h +++ b/src/GudhUI/utils/Rips_builder.h @@ -60,7 +60,7 @@ template<typename SkBlComplex> class Rips_builder { std::cout.flush(); for (auto q = p; ++q != vertices.end(); /**/) if (squared_eucl_distance(complex_.point(*p), complex_.point(*q)) < 4 * alpha * alpha) - complex_.add_edge(*p, *q); + complex_.add_edge_without_blockers(*p, *q); } std::cout << std::endl; } diff --git a/src/Nerve_GIC/include/gudhi/GIC.h b/src/Nerve_GIC/include/gudhi/GIC.h index 40ff7a4a..f5b67be6 100644 --- a/src/Nerve_GIC/include/gudhi/GIC.h +++ b/src/Nerve_GIC/include/gudhi/GIC.h @@ -23,6 +23,11 @@ #ifndef GIC_H_ #define GIC_H_ +#ifdef GUDHI_USE_TBB +#include <tbb/parallel_for.h> +#include <tbb/mutex.h> +#endif + #include <gudhi/Debug_utils.h> #include <gudhi/graph_simplicial_complex.h> #include <gudhi/reader_utils.h> @@ -99,9 +104,8 @@ class Cover_complex { int data_dimension; // dimension of input data. int n; // number of points. - std::map<int, double> func; // function used to compute the output simplicial complex. - std::map<int, double> - func_color; // function used to compute the colors of the nodes of the output simplicial complex. + std::vector<double> func; // function used to compute the output simplicial complex. + std::vector<double> func_color; // function used to compute the colors of the nodes of the output simplicial complex. bool functional_cover = false; // whether we use a cover with preimages of a function or not. Graph one_skeleton_OFF; // one-skeleton given by the input OFF file (if it exists). @@ -114,8 +118,8 @@ class Cover_complex { Persistence_diagram PD; std::vector<double> distribution; - std::map<int, std::vector<int> > - cover; // function associating to each data point its vectors of cover elements to which it belongs. + std::vector<std::vector<int> > + cover; // function associating to each data point the vector of cover elements to which it belongs. std::map<int, std::vector<int> > cover_back; // inverse of cover, in order to get the data points associated to a specific cover element. std::map<int, double> cover_std; // standard function (induced by func) used to compute the extended persistence @@ -140,8 +144,8 @@ class Cover_complex { // Point comparator struct Less { - Less(std::map<int, double> func) { Fct = func; } - std::map<int, double> Fct; + Less(std::vector<double> func) { Fct = func; } + std::vector<double> Fct; bool operator()(int a, int b) { if (Fct[a] == Fct[b]) return a < b; @@ -276,6 +280,7 @@ class Cover_complex { point_cloud.emplace_back(point.begin(), point.begin() + data_dimension); boost::add_vertex(one_skeleton_OFF); vertices.push_back(boost::add_vertex(one_skeleton)); + std::vector<int> dummy; dummy.clear(); cover.push_back(dummy); i++; } } @@ -430,17 +435,29 @@ class Cover_complex { if (distances.size() == 0) compute_pairwise_distances(distance); - // #pragma omp parallel for - for (int i = 0; i < N; i++) { - SampleWithoutReplacement(n, m, samples); - double hausdorff_dist = 0; - for (int j = 0; j < n; j++) { - double mj = distances[j][samples[0]]; - for (int k = 1; k < m; k++) mj = std::min(mj, distances[j][samples[k]]); - hausdorff_dist = std::max(hausdorff_dist, mj); + #ifdef GUDHI_USE_TBB + tbb::parallel_for(0, N, [&](int i){ + SampleWithoutReplacement(n, m, samples); + double hausdorff_dist = 0; + for (int j = 0; j < n; j++) { + double mj = distances[j][samples[0]]; + for (int k = 1; k < m; k++) mj = std::min(mj, distances[j][samples[k]]); + hausdorff_dist = std::max(hausdorff_dist, mj); + } + delta += hausdorff_dist / N; + }); + #else + for (int i = 0; i < N; i++) { + SampleWithoutReplacement(n, m, samples); + double hausdorff_dist = 0; + for (int j = 0; j < n; j++) { + double mj = distances[j][samples[0]]; + for (int k = 1; k < m; k++) mj = std::min(mj, distances[j][samples[k]]); + hausdorff_dist = std::max(hausdorff_dist, mj); + } + delta += hausdorff_dist / N; } - delta += hausdorff_dist / N; - } + #endif if (verbose) std::cout << "delta = " << delta << std::endl; set_graph_from_rips(delta, distance); @@ -465,7 +482,7 @@ class Cover_complex { while (std::getline(input, line)) { std::stringstream stream(line); stream >> f; - func.emplace(i, f); + func.push_back(f); i++; } functional_cover = true; @@ -479,7 +496,7 @@ class Cover_complex { * */ void set_function_from_coordinate(int k) { - for (int i = 0; i < n; i++) func.emplace(i, point_cloud[i][k]); + for (int i = 0; i < n; i++) func.push_back(point_cloud[i][k]); functional_cover = true; cover_name = "coordinate " + std::to_string(k); } @@ -492,7 +509,7 @@ class Cover_complex { */ template <class InputRange> void set_function_from_range(InputRange const& function) { - for (int i = 0; i < n; i++) func.emplace(i, function[i]); + for (int i = 0; i < n; i++) func.push_back(function[i]); functional_cover = true; } @@ -710,37 +727,69 @@ class Cover_complex { funcstd[i] = 0.5 * (u + v); } - if (verbose) std::cout << "Computing connected components..." << std::endl; - // #pragma omp parallel for - for (int i = 0; i < res; i++) { - // Compute connected components - Graph G = one_skeleton.create_subgraph(); - int num = preimages[i].size(); - std::vector<int> component(num); - for (int j = 0; j < num; j++) boost::add_vertex(index[vertices[preimages[i][j]]], G); - boost::connected_components(G, &component[0]); - int max = 0; - - // For each point in preimage - for (int j = 0; j < num; j++) { - // Update number of components in preimage - if (component[j] > max) max = component[j]; - - // Identify component with Cantor polynomial N^2 -> N - int identifier = (std::pow(i + component[j], 2) + 3 * i + component[j]) / 2; - - // Update covers - cover[preimages[i][j]].push_back(identifier); - cover_back[identifier].push_back(preimages[i][j]); - cover_fct[identifier] = i; - cover_std[identifier] = funcstd[i]; - cover_color[identifier].second += func_color[preimages[i][j]]; - cover_color[identifier].first += 1; - } + #ifdef GUDHI_USE_TBB + if (verbose) std::cout << "Computing connected components (parallelized)..." << std::endl; + tbb::parallel_for(0, res, [&](int i){ + // Compute connected components + Graph G = one_skeleton.create_subgraph(); + int num = preimages[i].size(); + std::vector<int> component(num); + for (int j = 0; j < num; j++) boost::add_vertex(index[vertices[preimages[i][j]]], G); + boost::connected_components(G, &component[0]); + int max = 0; + + // For each point in preimage + for (int j = 0; j < num; j++) { + // Update number of components in preimage + if (component[j] > max) max = component[j]; + + // Identify component with Cantor polynomial N^2 -> N + int identifier = ((i + component[j])*(i + component[j]) + 3 * i + component[j]) / 2; + + // Update covers + cover[preimages[i][j]].push_back(identifier); + cover_back[identifier].push_back(preimages[i][j]); + cover_fct[identifier] = i; + cover_std[identifier] = funcstd[i]; + cover_color[identifier].second += func_color[preimages[i][j]]; + cover_color[identifier].first += 1; + } - // Maximal dimension is total number of connected components - id += max + 1; - } + // Maximal dimension is total number of connected components + id += max + 1; + }); + #else + if (verbose) std::cout << "Computing connected components..." << std::endl; + for (int i = 0; i < res; i++) { + // Compute connected components + Graph G = one_skeleton.create_subgraph(); + int num = preimages[i].size(); + std::vector<int> component(num); + for (int j = 0; j < num; j++) boost::add_vertex(index[vertices[preimages[i][j]]], G); + boost::connected_components(G, &component[0]); + int max = 0; + + // For each point in preimage + for (int j = 0; j < num; j++) { + // Update number of components in preimage + if (component[j] > max) max = component[j]; + + // Identify component with Cantor polynomial N^2 -> N + int identifier = (std::pow(i + component[j], 2) + 3 * i + component[j]) / 2; + + // Update covers + cover[preimages[i][j]].push_back(identifier); + cover_back[identifier].push_back(preimages[i][j]); + cover_fct[identifier] = i; + cover_std[identifier] = funcstd[i]; + cover_color[identifier].second += func_color[preimages[i][j]]; + cover_color[identifier].first += 1; + } + + // Maximal dimension is total number of connected components + id += max + 1; + } + #endif maximal_dim = id - 1; for (std::map<int, std::pair<int, double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++) @@ -803,24 +852,46 @@ class Cover_complex { for (int j = 0; j < n; j++) mindist[j] = std::numeric_limits<double>::max(); // Compute the geodesic distances to subsamples with Dijkstra - // #pragma omp parallel for - for (int i = 0; i < m; i++) { - if (verbose) std::cout << "Computing geodesic distances to seed " << i << "..." << std::endl; - int seed = voronoi_subsamples[i]; - std::vector<double> dmap(n); - boost::dijkstra_shortest_paths( - one_skeleton, vertices[seed], - boost::weight_map(weight).distance_map(boost::make_iterator_property_map(dmap.begin(), index))); - - for (int j = 0; j < n; j++) - if (mindist[j] > dmap[j]) { - mindist[j] = dmap[j]; - if (cover[j].size() == 0) - cover[j].push_back(i); - else - cover[j][0] = i; - } - } + #ifdef GUDHI_USE_TBB + if (verbose) std::cout << "Computing geodesic distances (parallelized)..." << std::endl; + tbb::mutex coverMutex; tbb::mutex mindistMutex; + tbb::parallel_for(0, m, [&](int i){ + int seed = voronoi_subsamples[i]; + std::vector<double> dmap(n); + boost::dijkstra_shortest_paths( + one_skeleton, vertices[seed], + boost::weight_map(weight).distance_map(boost::make_iterator_property_map(dmap.begin(), index))); + + coverMutex.lock(); mindistMutex.lock(); + for (int j = 0; j < n; j++) + if (mindist[j] > dmap[j]) { + mindist[j] = dmap[j]; + if (cover[j].size() == 0) + cover[j].push_back(i); + else + cover[j][0] = i; + } + coverMutex.unlock(); mindistMutex.unlock(); + }); + #else + for (int i = 0; i < m; i++) { + if (verbose) std::cout << "Computing geodesic distances to seed " << i << "..." << std::endl; + int seed = voronoi_subsamples[i]; + std::vector<double> dmap(n); + boost::dijkstra_shortest_paths( + one_skeleton, vertices[seed], + boost::weight_map(weight).distance_map(boost::make_iterator_property_map(dmap.begin(), index))); + + for (int j = 0; j < n; j++) + if (mindist[j] > dmap[j]) { + mindist[j] = dmap[j]; + if (cover[j].size() == 0) + cover[j].push_back(i); + else + cover[j][0] = i; + } + } + #endif for (int i = 0; i < n; i++) { cover_back[cover[i][0]].push_back(i); @@ -860,7 +931,7 @@ class Cover_complex { while (std::getline(input, line)) { std::stringstream stream(line); stream >> f; - func_color.emplace(i, f); + func_color.push_back(f); i++; } color_name = color_file_name; @@ -873,7 +944,7 @@ class Cover_complex { * */ void set_color_from_coordinate(int k = 0) { - for (int i = 0; i < n; i++) func_color[i] = point_cloud[i][k]; + for (int i = 0; i < n; i++) func_color.push_back(point_cloud[i][k]); color_name = "coordinate "; color_name.append(std::to_string(k)); } @@ -885,7 +956,7 @@ class Cover_complex { * */ void set_color_from_vector(std::vector<double> color) { - for (unsigned int i = 0; i < color.size(); i++) func_color[i] = color[i]; + for (unsigned int i = 0; i < color.size(); i++) func_color.push_back(color[i]); } public: // Create a .dot file that can be compiled with neato to produce a .pdf file. @@ -1039,45 +1110,29 @@ class Cover_complex { minf = std::min(minf, it->second); } + // Build filtration for (auto const& simplex : simplices) { - // Add a simplex and a cone on it - std::vector<int> splx = simplex; - splx.push_back(-2); - st.insert_simplex_and_subfaces(splx); + std::vector<int> splx = simplex; splx.push_back(-2); + st.insert_simplex_and_subfaces(splx, -3); } - // Build filtration - for (auto simplex : st.complex_simplex_range()) { - double filta = std::numeric_limits<double>::lowest(); - double filts = filta; - bool ascending = true; - for (auto vertex : st.simplex_vertex_range(simplex)) { - if (vertex == -2) { - ascending = false; - continue; - } - filta = std::max(-2 + (cover_std[vertex] - minf) / (maxf - minf), filta); - filts = std::max(2 - (cover_std[vertex] - minf) / (maxf - minf), filts); - } - if (ascending) - st.assign_filtration(simplex, filta); - else - st.assign_filtration(simplex, filts); + for (std::map<int, double>::iterator it = cover_std.begin(); it != cover_std.end(); it++) { + int vertex = it->first; float val = it->second; + int vert[] = {vertex}; int edge[] = {vertex, -2}; + st.assign_filtration(st.find(vert), -2 + (val - minf)/(maxf - minf)); + st.assign_filtration(st.find(edge), 2 - (val - minf)/(maxf - minf)); } - int magic[] = {-2}; - st.assign_filtration(st.find(magic), -3); + st.make_filtration_non_decreasing(); // Compute PD - st.initialize_filtration(); - Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Gudhi::persistent_cohomology::Field_Zp> pcoh(st); - pcoh.init_coefficients(2); + Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Gudhi::persistent_cohomology::Field_Zp> pcoh(st); pcoh.init_coefficients(2); pcoh.compute_persistent_cohomology(); // Output PD int max_dim = st.dimension(); for (int i = 0; i < max_dim; i++) { std::vector<std::pair<double, double> > bars = pcoh.intervals_in_dimension(i); - int num_bars = bars.size(); + int num_bars = bars.size(); if(i == 0) num_bars -= 1; if(verbose) std::cout << num_bars << " interval(s) in dimension " << i << ":" << std::endl; for (int j = 0; j < num_bars; j++) { double birth = bars[j].first; @@ -1206,8 +1261,7 @@ class Cover_complex { } if (type == "Nerve") { - for(auto& simplex : cover) - simplices.push_back(simplex.second); + for(int i = 0; i < n; i++) simplices.push_back(cover[i]); std::sort(simplices.begin(), simplices.end()); std::vector<std::vector<int> >::iterator it = std::unique(simplices.begin(), simplices.end()); simplices.resize(std::distance(simplices.begin(), it)); diff --git a/src/Nerve_GIC/test/test_GIC.cpp b/src/Nerve_GIC/test/test_GIC.cpp index d633753c..e3067d35 100644 --- a/src/Nerve_GIC/test/test_GIC.cpp +++ b/src/Nerve_GIC/test/test_GIC.cpp @@ -39,6 +39,7 @@ BOOST_AUTO_TEST_CASE(check_nerve) { N.set_type("Nerve"); std::string cloud_file_name("data/cloud"); N.read_point_cloud(cloud_file_name); + N.set_color_from_coordinate(); std::string graph_file_name("data/graph"); N.set_graph_from_file(graph_file_name); std::string cover_file_name("data/cover"); @@ -58,6 +59,7 @@ BOOST_AUTO_TEST_CASE(check_GIC) { GIC.set_type("GIC"); std::string cloud_file_name("data/cloud"); GIC.read_point_cloud(cloud_file_name); + GIC.set_color_from_coordinate(); std::string graph_file_name("data/graph"); GIC.set_graph_from_file(graph_file_name); std::string cover_file_name("data/cover"); @@ -77,6 +79,7 @@ BOOST_AUTO_TEST_CASE(check_voronoiGIC) { GIC.set_type("GIC"); std::string cloud_file_name("data/cloud"); GIC.read_point_cloud(cloud_file_name); + GIC.set_color_from_coordinate(); std::string graph_file_name("data/graph"); GIC.set_graph_from_file(graph_file_name); GIC.set_cover_from_Voronoi(Gudhi::Euclidean_distance(), 2); diff --git a/src/Nerve_GIC/utilities/covercomplex.md b/src/Nerve_GIC/utilities/covercomplex.md index f33cb2e0..6d16d16f 100644 --- a/src/Nerve_GIC/utilities/covercomplex.md +++ b/src/Nerve_GIC/utilities/covercomplex.md @@ -1,3 +1,13 @@ +--- +layout: page +title: "Cover complex" +meta_title: "Cover complex" +teaser: "" +permalink: /covercomplex/ +--- +{::comment} +Leave the lines above as it is required by the web site generator 'Jekyll' +{:/comment} # Cover complex # diff --git a/src/Persistent_cohomology/concept/FilteredComplex.h b/src/Persistent_cohomology/concept/FilteredComplex.h index c19698df..d6b662e9 100644 --- a/src/Persistent_cohomology/concept/FilteredComplex.h +++ b/src/Persistent_cohomology/concept/FilteredComplex.h @@ -31,7 +31,7 @@ struct FilteredComplex typedef unspecified Simplex_handle; /** \brief Key associated to each simplex. * - * Must be a signed integer type. */ + * Must be an integer type. */ typedef unspecified Simplex_key; /** \brief Type for the value of the filtration function. * @@ -67,8 +67,8 @@ struct FilteredComplex Simplex_key key ( Simplex_handle sh ); /** \brief Returns the simplex that has index idx in the filtration. * - * This is never called on null_key(). */ - Simplex_handle simplex ( Simplex_key idx ); + * This is only called on valid indices. */ + Simplex_handle simplex ( size_t idx ); /** \brief Assign a key to a simplex. */ void assign_key(Simplex_handle sh, Simplex_key key); diff --git a/src/Rips_complex/utilities/ripscomplex.md b/src/Rips_complex/utilities/ripscomplex.md index 857e6293..d4dbc36e 100644 --- a/src/Rips_complex/utilities/ripscomplex.md +++ b/src/Rips_complex/utilities/ripscomplex.md @@ -1,3 +1,13 @@ +--- +layout: page +title: "Rips complex" +meta_title: "Rips complex" +teaser: "" +permalink: /ripscomplex/ +--- +{::comment} +Leave the lines above as it is required by the web site generator 'Jekyll' +{:/comment} # Rips complex # diff --git a/src/Witness_complex/utilities/witnesscomplex.md b/src/Witness_complex/utilities/witnesscomplex.md index 2341759b..3be9bc55 100644 --- a/src/Witness_complex/utilities/witnesscomplex.md +++ b/src/Witness_complex/utilities/witnesscomplex.md @@ -1,3 +1,13 @@ +---
+layout: page
+title: "Witness complex"
+meta_title: "Witness complex"
+teaser: ""
+permalink: /witnesscomplex/
+---
+{::comment}
+Leave the lines above as it is required by the web site generator 'Jekyll'
+{:/comment}
# Witness complex #
diff --git a/src/common/doc/header.html b/src/common/doc/header.html index d69b28fa..2f54e68d 100644 --- a/src/common/doc/header.html +++ b/src/common/doc/header.html @@ -9,7 +9,7 @@ <!--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="http://pages.saclay.inria.fr/vincent.rouvreau/gudhi/gudhi-doc-2.0.0/assets/css/styles_feeling_responsive.css" /> +<link rel="stylesheet" type="text/css" href="http://gudhi.gforge.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> 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/example/CMakeLists.txt b/src/common/example/CMakeLists.txt index afe865d4..1273c699 100644 --- a/src/common/example/CMakeLists.txt +++ b/src/common/example/CMakeLists.txt @@ -3,11 +3,20 @@ 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> - "${CMAKE_SOURCE_DIR}/data/points/SO3_10000.off") + "alphacomplexdoc.off") install(TARGETS vector_double_off_reader DESTINATION bin) +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(CGAL_FOUND) add_executable ( cgal_3D_off_reader example_CGAL_3D_points_off_reader.cpp ) target_link_libraries(cgal_3D_off_reader ${CGAL_LIBRARY}) diff --git a/src/common/example/example_CGAL_3D_points_off_reader.cpp b/src/common/example/example_CGAL_3D_points_off_reader.cpp index 665b7a29..4658d8d5 100644 --- a/src/common/example/example_CGAL_3D_points_off_reader.cpp +++ b/src/common/example/example_CGAL_3D_points_off_reader.cpp @@ -20,12 +20,12 @@ int main(int argc, char **argv) { usage(argv[0]); } - std::string offInputFile(argv[1]); + 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(offInputFile); + 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 " << offInputFile << std::endl; + std::cerr << "Unable to read file " << off_input_file << std::endl; usage(argv[0]); } diff --git a/src/common/example/example_CGAL_points_off_reader.cpp b/src/common/example/example_CGAL_points_off_reader.cpp index 8c6a6b54..f45683a5 100644 --- a/src/common/example/example_CGAL_points_off_reader.cpp +++ b/src/common/example/example_CGAL_points_off_reader.cpp @@ -22,12 +22,12 @@ int main(int argc, char **argv) { usage(argv[0]); } - std::string offInputFile(argv[1]); + 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(offInputFile); + 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 " << offInputFile << std::endl; + std::cerr << "Unable to read file " << off_input_file << std::endl; usage(argv[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 index 8aecb26e..5093da85 100644 --- a/src/common/example/example_vector_double_points_off_reader.cpp +++ b/src/common/example/example_vector_double_points_off_reader.cpp @@ -17,25 +17,27 @@ int main(int argc, char **argv) { usage(argv[0]); } - std::string offInputFile(argv[1]); + 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(offInputFile); + 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 " << offInputFile << std::endl; + 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) { - std::cout << "Point[" << n << "] = "; + output_file << "Point[" << n << "] = "; for (std::size_t i {0}; i < point.size(); i++) - std::cout << point[i] << " "; - std::cout << "\n"; + output_file << point[i] << " "; + output_file << "\n"; ++n; } + output_file.close(); return 0; } diff --git a/src/common/example/cgaloffreader_result.txt b/src/common/example/vectordoubleoffreader_result.txt index 1deb8dbd..1deb8dbd 100644 --- a/src/common/example/cgaloffreader_result.txt +++ b/src/common/example/vectordoubleoffreader_result.txt diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index 4fcd2af2..32320e4d 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -105,25 +105,26 @@ class Off_reader { 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 ((is_off_file) && (!is_noff_file)) { - off_info_.dim = 3; - if (!(iss >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) { - std::cerr << "incorrect number of vertices/faces/edges\n"; - return false; - } - } else { - if (!(iss >> off_info_.dim >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) { + 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); @@ -131,10 +132,12 @@ class Off_reader { } bool goto_next_uncomment_line(std::string& uncomment_line) { - uncomment_line.clear(); - do - std::getline(stream_, uncomment_line); while (uncomment_line[0] == '%'); - return (uncomment_line.size() > 0 && uncomment_line[0] != '%'); + do { + // skip whitespace, including empty lines + if (!std::ifstream::sentry(stream_)) return false; + std::getline(stream_, uncomment_line); + } while (uncomment_line[0] == '#'); + return (bool)stream_; } template<typename OffVisitor> diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h index 29af8a8a..08f324c6 100644 --- a/src/common/include/gudhi/Points_off_io.h +++ b/src/common/include/gudhi/Points_off_io.h @@ -126,9 +126,9 @@ class Points_off_visitor_reader { * \code $> ./vector_double_off_reader ../../data/points/alphacomplexdoc.off * \endcode * - * the program output is: + * the program outputs a file ../../data/points/alphacomplexdoc.off.txt: * - * \include common/cgaloffreader_result.txt + * \include common/vectordoubleoffreader_result.txt */ template<typename Point_d> class Points_off_reader { diff --git a/src/common/utilities/pointsetgenerator.md b/src/common/utilities/pointsetgenerator.md index 284715d4..3b23e668 100644 --- a/src/common/utilities/pointsetgenerator.md +++ b/src/common/utilities/pointsetgenerator.md @@ -1,6 +1,16 @@ - - -# common # +--- +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} + + +# Miscellaneous # ## off_file_from_shape_generator ## diff --git a/src/cython/example/bottleneck_basic_example.py b/src/cython/example/bottleneck_basic_example.py index 31cecb29..a7fa01c1 100755 --- a/src/cython/example/bottleneck_basic_example.py +++ b/src/cython/example/bottleneck_basic_example.py @@ -28,8 +28,6 @@ __author__ = "Francois Godi, Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 INRIA" __license__ = "GPL v3" -import gudhi - diag1 = [[2.7, 3.7],[9.6, 14.],[34.2, 34.974], [3.,float('Inf')]] diag2 = [[2.8, 4.45],[9.5, 14.1],[3.2,float('Inf')]] |