From af98f16e12ec9d1af7d925ecdc53b4daefea6ebe Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 18 Mar 2021 16:16:48 +0100 Subject: Add weight support --- src/python/include/Alpha_complex_factory.h | 65 +++++++++++++++++++++++++--- src/python/include/Alpha_complex_interface.h | 28 ++++++++---- 2 files changed, 79 insertions(+), 14 deletions(-) (limited to 'src/python/include') diff --git a/src/python/include/Alpha_complex_factory.h b/src/python/include/Alpha_complex_factory.h index 3405fdd6..36e98615 100644 --- a/src/python/include/Alpha_complex_factory.h +++ b/src/python/include/Alpha_complex_factory.h @@ -55,13 +55,13 @@ class Abstract_alpha_complex { virtual ~Abstract_alpha_complex() = default; }; -class Exact_Alphacomplex_dD final : public Abstract_alpha_complex { +class Exact_alpha_complex_dD final : public Abstract_alpha_complex { private: using Kernel = CGAL::Epeck_d; using Point = typename Kernel::Point_d; public: - Exact_Alphacomplex_dD(const std::vector>& points, bool exact_version) + Exact_alpha_complex_dD(const std::vector>& points, bool exact_version) : exact_version_(exact_version), alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal)) { } @@ -81,13 +81,13 @@ class Exact_Alphacomplex_dD final : public Abstract_alpha_complex { Alpha_complex alpha_complex_; }; -class Inexact_Alphacomplex_dD final : public Abstract_alpha_complex { +class Inexact_alpha_complex_dD final : public Abstract_alpha_complex { private: using Kernel = CGAL::Epick_d; using Point = typename Kernel::Point_d; public: - Inexact_Alphacomplex_dD(const std::vector>& points, bool exact_version) + Inexact_alpha_complex_dD(const std::vector>& points, bool exact_version) : exact_version_(exact_version), alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal)) { } @@ -106,8 +106,61 @@ class Inexact_Alphacomplex_dD final : public Abstract_alpha_complex { Alpha_complex alpha_complex_; }; +class Exact_weighted_alpha_complex_dD final : public Abstract_alpha_complex { + private: + using Kernel = CGAL::Epeck_d; + using Point = typename Kernel::Point_d; + + public: + Exact_weighted_alpha_complex_dD(const std::vector>& points, + const std::vector& weights, bool exact_version) + : exact_version_(exact_version), + alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal), weights) { + } + + virtual std::vector get_point(int vh) override { + Point const& point = alpha_complex_.get_point(vh).point(); + return pt_cgal_to_cython(point); + } + + virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, + bool default_filtration_value) override { + return alpha_complex_.create_complex(*simplex_tree, max_alpha_square, exact_version_, default_filtration_value); + } + + private: + bool exact_version_; + Alpha_complex alpha_complex_; +}; + +class Inexact_weighted_alpha_complex_dD final : public Abstract_alpha_complex { + private: + using Kernel = CGAL::Epick_d; + using Point = typename Kernel::Point_d; + + public: + Inexact_weighted_alpha_complex_dD(const std::vector>& points, + const std::vector& weights, bool exact_version) + : exact_version_(exact_version), + alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal), weights) { + } + + virtual std::vector get_point(int vh) override { + Point const& point = alpha_complex_.get_point(vh).point(); + return pt_cgal_to_cython(point); + } + virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, + bool default_filtration_value) override { + return alpha_complex_.create_complex(*simplex_tree, max_alpha_square, exact_version_, default_filtration_value); + } + + private: + bool exact_version_; + Alpha_complex alpha_complex_; +}; + template -class Alphacomplex_3D final : public Abstract_alpha_complex { +class Alpha_complex_3D final : public Abstract_alpha_complex { private: using Point = typename Alpha_complex_3d::Bare_point_3; @@ -116,7 +169,7 @@ class Alphacomplex_3D final : public Abstract_alpha_complex { } public: - Alphacomplex_3D(const std::vector>& points) + Alpha_complex_3D(const std::vector>& points) : alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal_3)) { } diff --git a/src/python/include/Alpha_complex_interface.h b/src/python/include/Alpha_complex_interface.h index 23be194d..43c96b2f 100644 --- a/src/python/include/Alpha_complex_interface.h +++ b/src/python/include/Alpha_complex_interface.h @@ -27,8 +27,11 @@ namespace alpha_complex { class Alpha_complex_interface { public: - Alpha_complex_interface(const std::vector>& points, bool fast_version, bool exact_version) + Alpha_complex_interface(const std::vector>& points, + const std::vector& weights, + bool fast_version, bool exact_version) : points_(points), + weights_(weights), fast_version_(fast_version), exact_version_(exact_version) { } @@ -41,13 +44,13 @@ class Alpha_complex_interface { bool default_filtration_value) { if (points_.size() > 0) { std::size_t dimension = points_[0].size(); - if (dimension == 3 && !default_filtration_value) { + if (dimension == 3 && weights_.size() == 0 && !default_filtration_value) { if (fast_version_) - alpha_ptr_ = std::make_unique>(points_); + alpha_ptr_ = std::make_unique>(points_); else if (exact_version_) - alpha_ptr_ = std::make_unique>(points_); + alpha_ptr_ = std::make_unique>(points_); else - alpha_ptr_ = std::make_unique>(points_); + alpha_ptr_ = std::make_unique>(points_); if (!alpha_ptr_->create_simplex_tree(simplex_tree, max_alpha_square, default_filtration_value)) { // create_simplex_tree will fail if all points are on a plane - Retry with dD by setting dimension to 2 dimension--; @@ -55,11 +58,19 @@ class Alpha_complex_interface { } } // Not ** else ** because we have to take into account if 3d fails - if (dimension != 3 || default_filtration_value) { + if (dimension != 3 || weights_.size() != 0 || default_filtration_value) { if (fast_version_) { - alpha_ptr_ = std::make_unique(points_, exact_version_); + if (weights_.size() == 0) { + alpha_ptr_ = std::make_unique(points_, exact_version_); + } else { + alpha_ptr_ = std::make_unique(points_, weights_, exact_version_); + } } else { - alpha_ptr_ = std::make_unique(points_, exact_version_); + if (weights_.size() == 0) { + alpha_ptr_ = std::make_unique(points_, exact_version_); + } else { + alpha_ptr_ = std::make_unique(points_, weights_, exact_version_); + } } alpha_ptr_->create_simplex_tree(simplex_tree, max_alpha_square, default_filtration_value); } @@ -69,6 +80,7 @@ class Alpha_complex_interface { private: std::unique_ptr alpha_ptr_; std::vector> points_; + std::vector weights_; bool fast_version_; bool exact_version_; }; -- cgit v1.2.3 From e4381a3e2ad79d3150cd03704bef3fc006e7c54b Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Sat, 3 Apr 2021 10:27:08 +0200 Subject: Python alpha complex specific 3d with weighted version and functor to get points --- src/python/CMakeLists.txt | 2 + src/python/gudhi/alpha_complex_3d.pyx | 129 ++++++++++++++++++++++++ src/python/include/Alpha_complex_factory.h | 48 +++++++-- src/python/include/Alpha_complex_interface.h | 59 ++++------- src/python/include/Alpha_complex_interface_3d.h | 71 +++++++++++++ 5 files changed, 261 insertions(+), 48 deletions(-) create mode 100644 src/python/gudhi/alpha_complex_3d.pyx create mode 100644 src/python/include/Alpha_complex_interface_3d.h (limited to 'src/python/include') diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 73303a24..307181b7 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -61,6 +61,7 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'subsampling', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'tangential_complex', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'alpha_complex', ") + set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'alpha_complex_3d', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'euclidean_witness_complex', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'euclidean_strong_witness_complex', ") # Modules that should not be auto-imported in __init__.py @@ -156,6 +157,7 @@ if(PYTHONINTERP_FOUND) endif () if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'alpha_complex', ") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'alpha_complex_3d', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'subsampling', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'tangential_complex', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'euclidean_witness_complex', ") diff --git a/src/python/gudhi/alpha_complex_3d.pyx b/src/python/gudhi/alpha_complex_3d.pyx new file mode 100644 index 00000000..3959004a --- /dev/null +++ b/src/python/gudhi/alpha_complex_3d.pyx @@ -0,0 +1,129 @@ +# 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) 2021 Inria +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + +from __future__ import print_function +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +from libc.stdint cimport intptr_t +import errno +import os +import warnings + +from gudhi.simplex_tree cimport * +from gudhi.simplex_tree import SimplexTree +from gudhi import read_points_from_off_file + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2021 Inria" +__license__ = "GPL v3" + +cdef extern from "Alpha_complex_interface_3d.h" namespace "Gudhi": + cdef cppclass Alpha_complex_interface_3d "Gudhi::alpha_complex::Alpha_complex_interface_3d": + Alpha_complex_interface_3d(vector[vector[double]] points, vector[double] weights, bool fast_version, bool exact_version) nogil except + + vector[double] get_point(int vertex) nogil except + + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) nogil except + + +# AlphaComplex3D python interface +cdef class AlphaComplex3D: + """AlphaComplex3D is a simplicial complex constructed from the finite cells + of a Delaunay Triangulation. + + The filtration value of each simplex is computed as the square of the + circumradius of the simplex if the circumsphere is empty (the simplex is + then said to be Gabriel), and as the minimum of the filtration values of + the codimension 1 cofaces that make it not Gabriel otherwise. + + All simplices that have a filtration value strictly greater than a given + alpha squared value are not inserted into the complex. + + .. note:: + + When AlphaComplex3D is constructed with an infinite value of alpha, the + complex is a Delaunay complex. + + """ + + cdef Alpha_complex_interface_3d * this_ptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, points=[], weights=[], precision='safe'): + """AlphaComplex3D constructor. + + :param points: A list of points in d-Dimension. + :type points: Iterable[Iterable[float]] + + :param weights: A list of weights. If set, the number of weights must correspond to the + number of points. + :type weights: Iterable[float] + + :param precision: Alpha complex precision can be 'fast', 'safe' or 'exact'. Default is + 'safe'. + :type precision: string + + :raises ValueError: In case of inconsistency between the number of points and weights. + """ + + # The real cython constructor + def __cinit__(self, points = [], weights=[], precision = 'safe'): + assert precision in ['fast', 'safe', 'exact'], \ + "Alpha complex precision can only be 'fast', 'safe' or 'exact'" + cdef bool fast = precision == 'fast' + cdef bool exact = precision == 'exact' + + # weights are set but is inconsistent with the number of points + if len(weights) != 0 and len(weights) != len(points): + raise ValueError("Inconsistency between the number of points and weights") + + # need to copy the points to use them without the gil + cdef vector[vector[double]] pts + cdef vector[double] wgts + pts = points + wgts = weights + with nogil: + self.this_ptr = new Alpha_complex_interface_3d(pts, wgts, fast, exact) + + def __dealloc__(self): + if self.this_ptr != NULL: + del self.this_ptr + + def __is_defined(self): + """Returns true if AlphaComplex3D pointer is not NULL. + """ + return self.this_ptr != NULL + + def get_point(self, vertex): + """This function returns the point corresponding to a given vertex from the :class:`~gudhi.SimplexTree`. + + :param vertex: The vertex. + :type vertex: int + :rtype: list of float + :returns: the point. + """ + return self.this_ptr.get_point(vertex) + + def create_simplex_tree(self, max_alpha_square = float('inf')): + """ + :param max_alpha_square: The maximum alpha square threshold the simplices shall not exceed. Default is set to + infinity, and there is very little point using anything else since it does not save time. + :type max_alpha_square: float + :returns: A simplex tree created from the Delaunay Triangulation. + :rtype: SimplexTree + """ + stree = SimplexTree() + cdef double mas = max_alpha_square + cdef intptr_t stree_int_ptr=stree.thisptr + with nogil: + self.this_ptr.create_simplex_tree(stree_int_ptr, + mas) + return stree diff --git a/src/python/include/Alpha_complex_factory.h b/src/python/include/Alpha_complex_factory.h index 36e98615..5d3bfb65 100644 --- a/src/python/include/Alpha_complex_factory.h +++ b/src/python/include/Alpha_complex_factory.h @@ -31,6 +31,34 @@ namespace Gudhi { namespace alpha_complex { +template +struct Point_cgal_to_cython; + +template +struct Point_cgal_to_cython { + std::vector operator()(CgalPointType const& point) const + { + std::vector vd; + vd.reserve(point.dimension()); + for (auto coord = point.cartesian_begin(); coord != point.cartesian_end(); coord++) + vd.push_back(CGAL::to_double(*coord)); + return vd; + } +}; + +template +struct Point_cgal_to_cython { + std::vector operator()(CgalPointType const& weighted_point) const + { + auto point = weighted_point.point(); + std::vector vd; + vd.reserve(point.dimension()); + for (auto coord = point.cartesian_begin(); coord != point.cartesian_end(); coord++) + vd.push_back(CGAL::to_double(*coord)); + return vd; + } +}; + template std::vector pt_cgal_to_cython(CgalPointType const& point) { std::vector vd; @@ -159,13 +187,14 @@ class Inexact_weighted_alpha_complex_dD final : public Abstract_alpha_complex { Alpha_complex alpha_complex_; }; -template +template class Alpha_complex_3D final : public Abstract_alpha_complex { private: - using Point = typename Alpha_complex_3d::Bare_point_3; + using Bare_point = typename Alpha_complex_3d::Bare_point_3; + using Point = typename Alpha_complex_3d::Point_3; - static Point pt_cython_to_cgal_3(std::vector const& vec) { - return Point(vec[0], vec[1], vec[2]); + static Bare_point pt_cython_to_cgal_3(std::vector const& vec) { + return Bare_point(vec[0], vec[1], vec[2]); } public: @@ -173,18 +202,23 @@ class Alpha_complex_3D final : public Abstract_alpha_complex { : alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal_3)) { } + Alpha_complex_3D(const std::vector>& points, const std::vector& weights) + : alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal_3), weights) { + } + virtual std::vector get_point(int vh) override { Point const& point = alpha_complex_.get_point(vh); - return pt_cgal_to_cython(point); + return Point_cgal_to_cython()(point); } virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, bool default_filtration_value) override { - return alpha_complex_.create_complex(*simplex_tree, max_alpha_square); + alpha_complex_.create_complex(*simplex_tree, max_alpha_square); + return true; } private: - Alpha_complex_3d alpha_complex_; + Alpha_complex_3d alpha_complex_; }; diff --git a/src/python/include/Alpha_complex_interface.h b/src/python/include/Alpha_complex_interface.h index 43c96b2f..31a8147b 100644 --- a/src/python/include/Alpha_complex_interface.h +++ b/src/python/include/Alpha_complex_interface.h @@ -30,10 +30,20 @@ class Alpha_complex_interface { Alpha_complex_interface(const std::vector>& points, const std::vector& weights, bool fast_version, bool exact_version) - : points_(points), - weights_(weights), - fast_version_(fast_version), - exact_version_(exact_version) { + : empty_point_set_(points.size() == 0) { + if (fast_version) { + if (weights.size() == 0) { + alpha_ptr_ = std::make_unique(points, exact_version); + } else { + alpha_ptr_ = std::make_unique(points, weights, exact_version); + } + } else { + if (weights.size() == 0) { + alpha_ptr_ = std::make_unique(points, exact_version); + } else { + alpha_ptr_ = std::make_unique(points, weights, exact_version); + } + } } std::vector get_point(int vh) { @@ -42,47 +52,14 @@ class Alpha_complex_interface { void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, bool default_filtration_value) { - if (points_.size() > 0) { - std::size_t dimension = points_[0].size(); - if (dimension == 3 && weights_.size() == 0 && !default_filtration_value) { - if (fast_version_) - alpha_ptr_ = std::make_unique>(points_); - else if (exact_version_) - alpha_ptr_ = std::make_unique>(points_); - else - alpha_ptr_ = std::make_unique>(points_); - if (!alpha_ptr_->create_simplex_tree(simplex_tree, max_alpha_square, default_filtration_value)) { - // create_simplex_tree will fail if all points are on a plane - Retry with dD by setting dimension to 2 - dimension--; - alpha_ptr_.reset(); - } - } - // Not ** else ** because we have to take into account if 3d fails - if (dimension != 3 || weights_.size() != 0 || default_filtration_value) { - if (fast_version_) { - if (weights_.size() == 0) { - alpha_ptr_ = std::make_unique(points_, exact_version_); - } else { - alpha_ptr_ = std::make_unique(points_, weights_, exact_version_); - } - } else { - if (weights_.size() == 0) { - alpha_ptr_ = std::make_unique(points_, exact_version_); - } else { - alpha_ptr_ = std::make_unique(points_, weights_, exact_version_); - } - } - alpha_ptr_->create_simplex_tree(simplex_tree, max_alpha_square, default_filtration_value); - } - } + // Nothing to be done in case of an empty point set + if (!empty_point_set_) + alpha_ptr_->create_simplex_tree(simplex_tree, max_alpha_square, default_filtration_value); } private: std::unique_ptr alpha_ptr_; - std::vector> points_; - std::vector weights_; - bool fast_version_; - bool exact_version_; + bool empty_point_set_; }; } // namespace alpha_complex diff --git a/src/python/include/Alpha_complex_interface_3d.h b/src/python/include/Alpha_complex_interface_3d.h new file mode 100644 index 00000000..bb66b8e1 --- /dev/null +++ b/src/python/include/Alpha_complex_interface_3d.h @@ -0,0 +1,71 @@ +/* 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) 2021 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#ifndef INCLUDE_ALPHA_COMPLEX_INTERFACE_3D_H_ +#define INCLUDE_ALPHA_COMPLEX_INTERFACE_3D_H_ + +#include "Alpha_complex_factory.h" +#include + +#include "Simplex_tree_interface.h" + +#include +#include +#include +#include // for std::unique_ptr + +namespace Gudhi { + +namespace alpha_complex { + +class Alpha_complex_interface_3d { + public: + Alpha_complex_interface_3d(const std::vector>& points, + const std::vector& weights, + bool fast_version, bool exact_version) + : empty_point_set_(points.size() == 0) { + const bool weighted = (weights.size() > 0); + if (fast_version) + if (weighted) + alpha_ptr_ = std::make_unique>(points, weights); + else + alpha_ptr_ = std::make_unique>(points); + else if (exact_version) + if (weighted) + alpha_ptr_ = std::make_unique>(points, weights); + else + alpha_ptr_ = std::make_unique>(points); + else + if (weighted) + alpha_ptr_ = std::make_unique>(points, weights); + else + alpha_ptr_ = std::make_unique>(points); + } + + std::vector get_point(int vh) { + return alpha_ptr_->get_point(vh); + } + + void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square) { + // Nothing to be done in case of an empty point set + if (!empty_point_set_) + alpha_ptr_->create_simplex_tree(simplex_tree, max_alpha_square, false); + } + + private: + std::unique_ptr alpha_ptr_; + bool empty_point_set_; +}; + +} // namespace alpha_complex + +} // namespace Gudhi + +#endif // INCLUDE_ALPHA_COMPLEX_INTERFACE_3D_H_ -- cgit v1.2.3 From d79ef2f79c33d8e8b8fd88e16f30e16433ab6644 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 7 Apr 2021 16:47:34 +0200 Subject: alpha complex python module requires cgal 5.1 for weighted version. Alpha complex factory does not require a weighted specific version for alpha complex dD --- src/python/CMakeLists.txt | 12 ++-- src/python/include/Alpha_complex_factory.h | 102 ++++++++------------------- src/python/include/Alpha_complex_interface.h | 13 ++-- 3 files changed, 46 insertions(+), 81 deletions(-) (limited to 'src/python/include') diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 307181b7..0739d7b5 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -156,13 +156,15 @@ if(PYTHONINTERP_FOUND) set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'nerve_gic', ") endif () if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'alpha_complex', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'alpha_complex_3d', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'subsampling', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'tangential_complex', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'euclidean_witness_complex', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'euclidean_strong_witness_complex', ") endif () + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'alpha_complex', ") + endif () if(CGAL_FOUND) # Add CGAL compilation args @@ -345,13 +347,15 @@ if(PYTHONINTERP_FOUND) # Test examples - if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) # Bottleneck and Alpha add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py" -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3) + endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) # Tangential add_test(NAME tangential_complex_plain_homology_from_off_file_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -421,7 +425,7 @@ if(PYTHONINTERP_FOUND) add_gudhi_py_test(test_cover_complex) endif (NOT CGAL_VERSION VERSION_LESS 4.11.0) - if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) # Alpha add_test(NAME alpha_complex_from_points_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -433,7 +437,7 @@ if(PYTHONINTERP_FOUND) ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py" --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) add_gudhi_py_test(test_alpha_complex) - endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) # Euclidean witness diff --git a/src/python/include/Alpha_complex_factory.h b/src/python/include/Alpha_complex_factory.h index 5d3bfb65..7d45af7c 100644 --- a/src/python/include/Alpha_complex_factory.h +++ b/src/python/include/Alpha_complex_factory.h @@ -31,9 +31,11 @@ namespace Gudhi { namespace alpha_complex { +// template Functor that transforms a CGAL point to a vector of double as expected by cython template struct Point_cgal_to_cython; +// Specialized Unweighted Functor template struct Point_cgal_to_cython { std::vector operator()(CgalPointType const& point) const @@ -46,6 +48,7 @@ struct Point_cgal_to_cython { } }; +// Specialized Weighted Functor template struct Point_cgal_to_cython { std::vector operator()(CgalPointType const& weighted_point) const @@ -59,15 +62,7 @@ struct Point_cgal_to_cython { } }; -template -std::vector pt_cgal_to_cython(CgalPointType const& point) { - std::vector vd; - vd.reserve(point.dimension()); - for (auto coord = point.cartesian_begin(); coord != point.cartesian_end(); coord++) - vd.push_back(CGAL::to_double(*coord)); - return vd; -} - +// Function that transforms a cython point (aka. a vector of double) to a CGAL point template static CgalPointType pt_cython_to_cgal(std::vector const& vec) { return CgalPointType(vec.size(), vec.begin(), vec.end()); @@ -83,20 +78,29 @@ class Abstract_alpha_complex { virtual ~Abstract_alpha_complex() = default; }; +template class Exact_alpha_complex_dD final : public Abstract_alpha_complex { private: using Kernel = CGAL::Epeck_d; - using Point = typename Kernel::Point_d; + using Bare_point = typename Kernel::Point_d; + using Point = std::conditional_t; public: Exact_alpha_complex_dD(const std::vector>& points, bool exact_version) : exact_version_(exact_version), - alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal)) { + alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal)) { + } + + Exact_alpha_complex_dD(const std::vector>& points, + const std::vector& weights, bool exact_version) + : exact_version_(exact_version), + alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal), weights) { } virtual std::vector get_point(int vh) override { - Point const& point = alpha_complex_.get_point(vh); - return pt_cgal_to_cython(point); + // Can be a Weighted or a Bare point in function of Weighted + return Point_cgal_to_cython()(alpha_complex_.get_point(vh)); } virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, @@ -106,76 +110,32 @@ class Exact_alpha_complex_dD final : public Abstract_alpha_complex { private: bool exact_version_; - Alpha_complex alpha_complex_; + Alpha_complex alpha_complex_; }; +template class Inexact_alpha_complex_dD final : public Abstract_alpha_complex { private: using Kernel = CGAL::Epick_d; - using Point = typename Kernel::Point_d; + using Bare_point = typename Kernel::Point_d; + using Point = std::conditional_t; public: Inexact_alpha_complex_dD(const std::vector>& points, bool exact_version) : exact_version_(exact_version), - alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal)) { - } - - virtual std::vector get_point(int vh) override { - Point const& point = alpha_complex_.get_point(vh); - return pt_cgal_to_cython(point); - } - virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, - bool default_filtration_value) override { - return alpha_complex_.create_complex(*simplex_tree, max_alpha_square, exact_version_, default_filtration_value); - } - - private: - bool exact_version_; - Alpha_complex alpha_complex_; -}; - -class Exact_weighted_alpha_complex_dD final : public Abstract_alpha_complex { - private: - using Kernel = CGAL::Epeck_d; - using Point = typename Kernel::Point_d; - - public: - Exact_weighted_alpha_complex_dD(const std::vector>& points, - const std::vector& weights, bool exact_version) - : exact_version_(exact_version), - alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal), weights) { - } - - virtual std::vector get_point(int vh) override { - Point const& point = alpha_complex_.get_point(vh).point(); - return pt_cgal_to_cython(point); - } - - virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, - bool default_filtration_value) override { - return alpha_complex_.create_complex(*simplex_tree, max_alpha_square, exact_version_, default_filtration_value); + alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal)) { } - private: - bool exact_version_; - Alpha_complex alpha_complex_; -}; - -class Inexact_weighted_alpha_complex_dD final : public Abstract_alpha_complex { - private: - using Kernel = CGAL::Epick_d; - using Point = typename Kernel::Point_d; - - public: - Inexact_weighted_alpha_complex_dD(const std::vector>& points, - const std::vector& weights, bool exact_version) + Inexact_alpha_complex_dD(const std::vector>& points, + const std::vector& weights, bool exact_version) : exact_version_(exact_version), - alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal), weights) { + alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal), weights) { } virtual std::vector get_point(int vh) override { - Point const& point = alpha_complex_.get_point(vh).point(); - return pt_cgal_to_cython(point); + // Can be a Weighted or a Bare point in function of Weighted + return Point_cgal_to_cython()(alpha_complex_.get_point(vh)); } virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, bool default_filtration_value) override { @@ -184,7 +144,7 @@ class Inexact_weighted_alpha_complex_dD final : public Abstract_alpha_complex { private: bool exact_version_; - Alpha_complex alpha_complex_; + Alpha_complex alpha_complex_; }; template @@ -207,8 +167,8 @@ class Alpha_complex_3D final : public Abstract_alpha_complex { } virtual std::vector get_point(int vh) override { - Point const& point = alpha_complex_.get_point(vh); - return Point_cgal_to_cython()(point); + // Can be a Weighted or a Bare point in function of Weighted + return Point_cgal_to_cython()(alpha_complex_.get_point(vh)); } virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, diff --git a/src/python/include/Alpha_complex_interface.h b/src/python/include/Alpha_complex_interface.h index 31a8147b..ed243f19 100644 --- a/src/python/include/Alpha_complex_interface.h +++ b/src/python/include/Alpha_complex_interface.h @@ -31,17 +31,18 @@ class Alpha_complex_interface { const std::vector& weights, bool fast_version, bool exact_version) : empty_point_set_(points.size() == 0) { + const bool weighted = (weights.size() > 0); if (fast_version) { - if (weights.size() == 0) { - alpha_ptr_ = std::make_unique(points, exact_version); + if (weighted) { + alpha_ptr_ = std::make_unique>(points, weights, exact_version); } else { - alpha_ptr_ = std::make_unique(points, weights, exact_version); + alpha_ptr_ = std::make_unique>(points, exact_version); } } else { - if (weights.size() == 0) { - alpha_ptr_ = std::make_unique(points, exact_version); + if (weighted) { + alpha_ptr_ = std::make_unique>(points, weights, exact_version); } else { - alpha_ptr_ = std::make_unique(points, weights, exact_version); + alpha_ptr_ = std::make_unique>(points, exact_version); } } } -- cgit v1.2.3 From 2f507728035c76f16c732b911c52a9118a9b52dd Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 9 Jun 2021 09:57:26 +0200 Subject: code review: constify auto --- src/python/include/Alpha_complex_factory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/python/include') diff --git a/src/python/include/Alpha_complex_factory.h b/src/python/include/Alpha_complex_factory.h index 7d45af7c..fbbf8896 100644 --- a/src/python/include/Alpha_complex_factory.h +++ b/src/python/include/Alpha_complex_factory.h @@ -53,7 +53,7 @@ template struct Point_cgal_to_cython { std::vector operator()(CgalPointType const& weighted_point) const { - auto point = weighted_point.point(); + const auto& point = weighted_point.point(); std::vector vd; vd.reserve(point.dimension()); for (auto coord = point.cartesian_begin(); coord != point.cartesian_end(); coord++) -- cgit v1.2.3 From f70e6f26f329428184fc5cf935ad4dfc20648bfb Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 1 Jul 2021 17:30:38 +0200 Subject: Revert AlphaComplex3D. To be done with periodic --- .../example/Alpha_complex_3d_from_points.cpp | 29 ++-- .../Weighted_alpha_complex_3d_from_points.cpp | 29 ++-- src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 19 +-- .../test/Alpha_complex_3d_unit_test.cpp | 30 ---- .../test/Weighted_alpha_complex_unit_test.cpp | 2 +- src/python/CMakeLists.txt | 2 - src/python/doc/alpha_complex_ref.rst | 6 - src/python/doc/alpha_complex_user.rst | 14 -- src/python/gudhi/alpha_complex_3d.pyx | 135 ----------------- src/python/include/Alpha_complex_factory.h | 35 ----- src/python/test/test_alpha_complex_3d.py | 159 --------------------- 11 files changed, 42 insertions(+), 418 deletions(-) delete mode 100644 src/python/gudhi/alpha_complex_3d.pyx delete mode 100755 src/python/test/test_alpha_complex_3d.py (limited to 'src/python/include') diff --git a/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp index dd3c0225..a2c85138 100644 --- a/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_3d_from_points.cpp @@ -34,22 +34,23 @@ int main(int argc, char **argv) { Alpha_complex_3d alpha_complex_from_points(points); Gudhi::Simplex_tree<> simplex; - alpha_complex_from_points.create_complex(simplex); - // ---------------------------------------------------------------------------- - // Display information about the alpha complex - // ---------------------------------------------------------------------------- - std::clog << "Alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() - << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; + if (alpha_complex_from_points.create_complex(simplex)) { + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::clog << "Alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() + << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; - std::clog << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; - for (auto f_simplex : simplex.filtration_simplex_range()) { - std::clog << " ( "; - for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { - std::clog << vertex << " "; + std::clog << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : simplex.filtration_simplex_range()) { + std::clog << " ( "; + for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { + std::clog << vertex << " "; + } + std::clog << ") -> " + << "[" << simplex.filtration(f_simplex) << "] "; + std::clog << std::endl; } - std::clog << ") -> " - << "[" << simplex.filtration(f_simplex) << "] "; - std::clog << std::endl; } return 0; } diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp index 507d6413..ee12d418 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp @@ -30,22 +30,23 @@ int main(int argc, char **argv) { Weighted_alpha_complex_3d alpha_complex_from_points(weighted_points); Gudhi::Simplex_tree<> simplex; - alpha_complex_from_points.create_complex(simplex); - // ---------------------------------------------------------------------------- - // Display information about the alpha complex - // ---------------------------------------------------------------------------- - std::clog << "Weighted alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() - << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; + if (alpha_complex_from_points.create_complex(simplex)) { + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::clog << "Weighted alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() + << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; - std::clog << "Iterator on weighted alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; - for (auto f_simplex : simplex.filtration_simplex_range()) { - std::clog << " ( "; - for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { - std::clog << vertex << " "; + std::clog << "Iterator on weighted alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : simplex.filtration_simplex_range()) { + std::clog << " ( "; + for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { + std::clog << vertex << " "; + } + std::clog << ") -> " + << "[" << simplex.filtration(f_simplex) << "] "; + std::clog << std::endl; } - std::clog << ") -> " - << "[" << simplex.filtration(f_simplex) << "] "; - std::clog << std::endl; } return 0; } diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index 73f9dd41..4e5fc933 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -48,7 +48,6 @@ #include // for std::unique_ptr #include // for std::conditional and std::enable_if #include // for numeric_limits<> -#include // for domain_error and invalid_argument // Make compilation fail - required for external projects - https://github.com/GUDHI/gudhi-devel/issues/10 #if CGAL_VERSION_NR < 1041101000 @@ -429,18 +428,19 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_ * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$, and there is very * little point using anything else since it does not save time. * - * @exception invalid_argument In debug mode, if `complex` given as argument is not empty. - * @exception domain_error If `points` given in the constructor are on a 2d plane. + * @return true if creation succeeds, false otherwise. * * @pre The simplicial complex must be empty (no vertices). * */ template - void create_complex(SimplicialComplexForAlpha3d& complex, + bool create_complex(SimplicialComplexForAlpha3d& complex, Filtration_value max_alpha_square = std::numeric_limits::infinity()) { - GUDHI_CHECK(complex.num_vertices() == 0, - std::invalid_argument("Alpha_complex_3d create_complex - The complex given as argument is not empty")); + if (complex.num_vertices() > 0) { + std::cerr << "Alpha_complex_3d create_complex - complex is not empty\n"; + return false; // ----- >> + } using Complex_vertex_handle = typename SimplicialComplexForAlpha3d::Vertex_handle; using Simplex_tree_vector_vertex = std::vector; @@ -461,8 +461,10 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_ #ifdef DEBUG_TRACES std::clog << "filtration_with_alpha_values returns : " << objects.size() << " objects" << std::endl; #endif // DEBUG_TRACES - if (objects.size() == 0) - throw std::domain_error("Alpha_complex_3d create_complex - no triangulation as points are on a 2d plane"); + if (objects.size() == 0) { + std::cerr << "Alpha_complex_3d create_complex - no triangulation as points are on a 2d plane\n"; + return false; // ----- >> + } using Alpha_value_iterator = typename std::vector::const_iterator; Alpha_value_iterator alpha_value_iterator = alpha_values.begin(); @@ -557,6 +559,7 @@ Weighted_alpha_complex_3d::Weighted_point_3 wp0(Weighted_alpha_complex_3d::Bare_ // Remove all simplices that have a filtration value greater than max_alpha_square complex.prune_above_filtration(max_alpha_square); // -------------------------------------------------------------------------------------------- + return true; } /** \brief get_point returns the point corresponding to the vertex given as parameter. diff --git a/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp index 94021954..a4ecb6ad 100644 --- a/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_3d_unit_test.cpp @@ -11,7 +11,6 @@ #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE "alpha_complex_3d" #include -#include #include // float comparison #include @@ -37,7 +36,6 @@ using Safe_alpha_complex_3d = using Exact_alpha_complex_3d = Gudhi::alpha_complex::Alpha_complex_3d; - template std::vector get_points() { std::vector points; @@ -199,31 +197,3 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_3d_from_points) { ++safe_sh; } } - -typedef boost::mpl::list list_of_alpha_variants; - -BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_3d_exceptions_points_on_plane, Alpha, list_of_alpha_variants) { - std::vector points_on_plane; - points_on_plane.emplace_back(1.0, 1.0 , 0.0); - points_on_plane.emplace_back(7.0, 0.0 , 0.0); - points_on_plane.emplace_back(4.0, 6.0 , 0.0); - points_on_plane.emplace_back(9.0, 6.0 , 0.0); - points_on_plane.emplace_back(0.0, 14.0, 0.0); - points_on_plane.emplace_back(2.0, 19.0, 0.0); - points_on_plane.emplace_back(9.0, 17.0, 0.0); - - Alpha alpha_complex(points_on_plane); - Gudhi::Simplex_tree<> stree; - - BOOST_CHECK_THROW(alpha_complex.create_complex(stree), std::domain_error); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_3d_exceptions_non_empty_simplex_tree, Alpha, list_of_alpha_variants) { - Alpha alpha_complex(get_points()); - Gudhi::Simplex_tree<> stree; - stree.insert_simplex_and_subfaces({2,1,0}, 3.0); - -#ifdef GUDHI_DEBUG - BOOST_CHECK_THROW(alpha_complex.create_complex(stree), std::invalid_argument); -#endif // GUDHI_DEBUG -} \ No newline at end of file diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index 4e1a38df..875704ee 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { // Weighted alpha complex for 3D version Exact_weighted_alpha_complex_3d alpha_complex_3D_from_weighted_points(w_points_3); Gudhi::Simplex_tree<> w_simplex_3; - alpha_complex_3D_from_weighted_points.create_complex(w_simplex_3); + BOOST_CHECK(alpha_complex_3D_from_weighted_points.create_complex(w_simplex_3)); std::clog << "Iterator on weighted alpha complex 3D simplices in the filtration order, with [filtration value]:" << std::endl; diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 669239b8..bfa78131 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -62,7 +62,6 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'subsampling', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'tangential_complex', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'alpha_complex', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'alpha_complex_3d', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'euclidean_witness_complex', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'euclidean_strong_witness_complex', ") # Modules that should not be auto-imported in __init__.py @@ -158,7 +157,6 @@ if(PYTHONINTERP_FOUND) set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'nerve_gic', ") endif () if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'alpha_complex_3d', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'subsampling', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'tangential_complex', ") set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'euclidean_witness_complex', ") diff --git a/src/python/doc/alpha_complex_ref.rst b/src/python/doc/alpha_complex_ref.rst index 49321368..eaa72551 100644 --- a/src/python/doc/alpha_complex_ref.rst +++ b/src/python/doc/alpha_complex_ref.rst @@ -11,9 +11,3 @@ Alpha complex reference manual :undoc-members: .. automethod:: gudhi.AlphaComplex.__init__ - -.. autoclass:: gudhi.AlphaComplex3D - :members: - :undoc-members: - - .. automethod:: gudhi.AlphaComplex3D.__init__ diff --git a/src/python/doc/alpha_complex_user.rst b/src/python/doc/alpha_complex_user.rst index d7b09246..db0ccdc9 100644 --- a/src/python/doc/alpha_complex_user.rst +++ b/src/python/doc/alpha_complex_user.rst @@ -254,17 +254,3 @@ Then, it computes the persistence diagram and displays it: dgm = stree.persistence() gd.plot_persistence_diagram(dgm, legend = True) plt.show() - -3d specific version -^^^^^^^^^^^^^^^^^^^ - -:Requires: `Eigen `_ :math:`\geq` 3.1.0 and `CGAL `_ :math:`\geq` 4.11.0. - -A specific module for Alpha complex is available in 3d (cf. :class:`~gudhi.AlphaComplex3D`) and -allows to construct standard and weighted versions of alpha complexes. - -Remark -"""""" - -* Contrary to the dD version, with the 3d version, the vertices in the output simplex tree are not guaranteed to match - the order of the input points. One can use :func:`~gudhi.AlphaComplex3D.get_point` to get the initial point back. diff --git a/src/python/gudhi/alpha_complex_3d.pyx b/src/python/gudhi/alpha_complex_3d.pyx deleted file mode 100644 index 578011a7..00000000 --- a/src/python/gudhi/alpha_complex_3d.pyx +++ /dev/null @@ -1,135 +0,0 @@ -# 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) 2021 Inria -# -# Modification(s): -# - YYYY/MM Author: Description of the modification - -from __future__ import print_function -from cython cimport numeric -from libcpp.vector cimport vector -from libcpp.utility cimport pair -from libcpp.string cimport string -from libcpp cimport bool -from libc.stdint cimport intptr_t -import errno -import os -import warnings - -from gudhi.simplex_tree cimport * -from gudhi.simplex_tree import SimplexTree -from gudhi import read_points_from_off_file - -__author__ = "Vincent Rouvreau" -__copyright__ = "Copyright (C) 2021 Inria" -__license__ = "GPL v3" - -cdef extern from "Alpha_complex_interface_3d.h" namespace "Gudhi": - cdef cppclass Alpha_complex_interface_3d "Gudhi::alpha_complex::Alpha_complex_interface_3d": - Alpha_complex_interface_3d(vector[vector[double]] points, vector[double] weights, bool fast_version, bool exact_version) nogil except + - vector[double] get_point(int vertex) nogil except + - void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) nogil except + - -# AlphaComplex3D python interface -cdef class AlphaComplex3D: - """AlphaComplex3D is a simplicial complex constructed from the finite cells of a Delaunay Triangulation. - - The filtration value of each simplex is computed as the square of the circumradius of the simplex if the - circumsphere is empty (the simplex is then said to be Gabriel), and as the minimum of the filtration values of the - codimension 1 cofaces that make it not Gabriel otherwise. - - All simplices that have a filtration value strictly greater than a given alpha squared value are not inserted into - the complex. - - .. note:: - - When AlphaComplex3D is constructed with an infinite value of alpha, the complex is a Delaunay complex. - - .. warning:: - - Contrary to the dD version, with the 3d version, the vertices in the output simplex tree are not guaranteed to - match the order of the input points. One can use :func:`~gudhi.AlphaComplex3D.get_point` to get the initial - point back. - """ - - cdef Alpha_complex_interface_3d * this_ptr - - # Fake constructor that does nothing but documenting the constructor - def __init__(self, points=[], weights=[], precision='safe'): - """AlphaComplex3D constructor. - - :param points: A list of points in 3d. - :type points: Iterable[Iterable[float]] - - :param weights: A list of weights. If set, the number of weights must correspond to the number of points. - :type weights: Iterable[float] - - :param precision: Alpha complex precision can be 'fast', 'safe' or 'exact'. Default is 'safe'. - :type precision: string - - :raises ValueError: If the given points are not in 3d. - :raises ValueError: In case of inconsistency between the number of points and weights. - """ - - # The real cython constructor - def __cinit__(self, points = [], weights=[], precision = 'safe'): - assert precision in ['fast', 'safe', 'exact'], "Alpha complex precision can only be 'fast', 'safe' or 'exact'" - cdef bool fast = precision == 'fast' - cdef bool exact = precision == 'exact' - - if len(points) > 0: - if len(points[0]) != 3: - raise ValueError("AlphaComplex3D only accepts 3d points as an input") - - # weights are set but is inconsistent with the number of points - if len(weights) != 0 and len(weights) != len(points): - raise ValueError("Inconsistency between the number of points and weights") - - # need to copy the points to use them without the gil - cdef vector[vector[double]] pts - cdef vector[double] wgts - pts = points - wgts = weights - with nogil: - self.this_ptr = new Alpha_complex_interface_3d(pts, wgts, fast, exact) - - def __dealloc__(self): - if self.this_ptr != NULL: - del self.this_ptr - - def __is_defined(self): - """Returns true if AlphaComplex3D pointer is not NULL. - """ - return self.this_ptr != NULL - - def get_point(self, vertex): - """This function returns the point corresponding to a given vertex from the :class:`~gudhi.SimplexTree`. - - :param vertex: The vertex. - :type vertex: int - :rtype: list of float - :returns: the point. - """ - return self.this_ptr.get_point(vertex) - - def create_simplex_tree(self, max_alpha_square = float('inf')): - """ - :param max_alpha_square: The maximum alpha square threshold the simplices shall not exceed. Default is set to - infinity, and there is very little point using anything else since it does not save time. - :type max_alpha_square: float - :returns: A simplex tree created from the Delaunay Triangulation. - :rtype: SimplexTree - - :raises ValueError: If the points given at construction time are on a plane. - """ - stree = SimplexTree() - cdef double mas = max_alpha_square - cdef intptr_t stree_int_ptr=stree.thisptr - with nogil: - self.this_ptr.create_simplex_tree(stree_int_ptr, - mas) - return stree diff --git a/src/python/include/Alpha_complex_factory.h b/src/python/include/Alpha_complex_factory.h index fbbf8896..298469fe 100644 --- a/src/python/include/Alpha_complex_factory.h +++ b/src/python/include/Alpha_complex_factory.h @@ -147,41 +147,6 @@ class Inexact_alpha_complex_dD final : public Abstract_alpha_complex { Alpha_complex alpha_complex_; }; -template -class Alpha_complex_3D final : public Abstract_alpha_complex { - private: - using Bare_point = typename Alpha_complex_3d::Bare_point_3; - using Point = typename Alpha_complex_3d::Point_3; - - static Bare_point pt_cython_to_cgal_3(std::vector const& vec) { - return Bare_point(vec[0], vec[1], vec[2]); - } - - public: - Alpha_complex_3D(const std::vector>& points) - : alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal_3)) { - } - - Alpha_complex_3D(const std::vector>& points, const std::vector& weights) - : alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal_3), weights) { - } - - virtual std::vector get_point(int vh) override { - // Can be a Weighted or a Bare point in function of Weighted - return Point_cgal_to_cython()(alpha_complex_.get_point(vh)); - } - - virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, - bool default_filtration_value) override { - alpha_complex_.create_complex(*simplex_tree, max_alpha_square); - return true; - } - - private: - Alpha_complex_3d alpha_complex_; -}; - - } // namespace alpha_complex } // namespace Gudhi diff --git a/src/python/test/test_alpha_complex_3d.py b/src/python/test/test_alpha_complex_3d.py deleted file mode 100755 index a5d9373b..00000000 --- a/src/python/test/test_alpha_complex_3d.py +++ /dev/null @@ -1,159 +0,0 @@ -""" 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) 2021 Inria - - Modification(s): - - YYYY/MM Author: Description of the modification -""" - -from gudhi import AlphaComplex3D -import pytest -import numpy as np - -try: - # python3 - from itertools import zip_longest -except ImportError: - # python2 - from itertools import izip_longest as zip_longest - - - -def _empty_alpha(precision): - alpha_complex = AlphaComplex3D(precision = precision) - assert alpha_complex.__is_defined() == True - -def _one_3d_point_alpha(precision): - alpha_complex = AlphaComplex3D(points=[[0, 0, 0]], precision = precision) - assert alpha_complex.__is_defined() == True - -def test_empty_alpha(): - for precision in ['fast', 'safe', 'exact']: - _empty_alpha(precision) - _one_3d_point_alpha(precision) - -def _infinite_alpha(precision): - point_list = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]] - alpha_complex = AlphaComplex3D(points=point_list, precision = precision) - assert alpha_complex.__is_defined() == True - - stree = alpha_complex.create_simplex_tree() - assert stree.__is_persistence_defined() == False - - assert stree.num_simplices() == 51 - assert stree.num_vertices() == len(point_list) - - for filtration in stree.get_filtration(): - if len(filtration[0]) == 1: - assert filtration[1] == 0. - if len(filtration[0]) == 4: - assert filtration[1] == 0.75 - - for idx in range(len(point_list)): - pt_idx = point_list.index(alpha_complex.get_point(idx)) - assert pt_idx >= 0 - assert pt_idx < len(point_list) - - with pytest.raises(IndexError): - alpha_complex.get_point(len(point_list)) - -def test_infinite_alpha(): - for precision in ['fast', 'safe', 'exact']: - _infinite_alpha(precision) - -def _filtered_alpha(precision): - point_list = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]] - filtered_alpha = AlphaComplex3D(points=point_list, precision = precision) - - stree = filtered_alpha.create_simplex_tree(max_alpha_square=0.25) - - assert stree.num_simplices() == 20 - assert stree.num_vertices() == len(point_list) - - for filtration in stree.get_filtration(): - if len(filtration[0]) == 1: - assert filtration[1] == 0. - elif len(filtration[0]) == 2: - assert filtration[1] == 0.25 - else: - assert False - - for idx in range(len(point_list)): - pt_idx = point_list.index(filtered_alpha.get_point(idx)) - assert pt_idx >= 0 - assert pt_idx < len(point_list) - - with pytest.raises(IndexError): - filtered_alpha.get_point(len(point_list)) - -def test_filtered_alpha(): - for precision in ['fast', 'safe', 'exact']: - _filtered_alpha(precision) - -def _3d_points_on_a_plane(precision): - alpha = AlphaComplex3D(points = [[1.0, 1.0 , 0.0], - [7.0, 0.0 , 0.0], - [4.0, 6.0 , 0.0], - [9.0, 6.0 , 0.0], - [0.0, 14.0, 0.0], - [2.0, 19.0, 0.0], - [9.0, 17.0, 0.0]], precision = precision) - - with pytest.raises(ValueError): - stree = alpha.create_simplex_tree() - -def test_3d_points_on_a_plane(): - for precision in ['fast', 'safe', 'exact']: - _3d_points_on_a_plane(precision) - -def test_inconsistency_points_and_weights(): - points = [[1.0, 1.0 , 1.0], - [7.0, 0.0 , 2.0], - [4.0, 6.0 , 0.0], - [9.0, 6.0 , 1.0], - [0.0, 14.0, 2.0], - [2.0, 19.0, 0.0], - [9.0, 17.0, 1.0]] - with pytest.raises(ValueError): - # 7 points, 8 weights, on purpose - alpha = AlphaComplex3D(points = points, - weights = [1., 2., 3., 4., 5., 6., 7., 8.]) - - with pytest.raises(ValueError): - # 7 points, 6 weights, on purpose - alpha = AlphaComplex3D(points = points, - weights = [1., 2., 3., 4., 5., 6.]) - -def _weighted_doc_example(precision): - pts = [[ 1., -1., -1.], - [-1., 1., -1.], - [-1., -1., 1.], - [ 1., 1., 1.], - [ 2., 2., 2.]] - wgts = [4., 4., 4., 4., 1.] - alpha = AlphaComplex3D(points = pts, weights = wgts, precision = precision) - stree = alpha.create_simplex_tree() - - # Needs to retrieve points as points are shuffled - get_idx = lambda idx: pts.index(alpha.get_point(idx)) - indices = [get_idx(x) for x in range(len(pts))] - - assert stree.filtration([indices[x] for x in [0, 1, 2, 3]]) == pytest.approx(-1.) - assert stree.filtration([indices[x] for x in [0, 1, 3, 4]]) == pytest.approx(95.) - assert stree.filtration([indices[x] for x in [0, 2, 3, 4]]) == pytest.approx(95.) - assert stree.filtration([indices[x] for x in [1, 2, 3, 4]]) == pytest.approx(95.) - -def test_weighted_doc_example(): - for precision in ['fast', 'safe', 'exact']: - _weighted_doc_example(precision) - -def test_points_not_in_3d(): - with pytest.raises(ValueError): - alpha = AlphaComplex3D(points = np.random.rand(6,2)) - with pytest.raises(ValueError): - alpha = AlphaComplex3D(points = np.random.rand(6,4)) - - alpha = AlphaComplex3D(points = np.random.rand(6,3)) - assert alpha.__is_defined() == True \ No newline at end of file -- cgit v1.2.3 From 1617cac6fe6333b2e63f9931399a27643dad45ac Mon Sep 17 00:00:00 2001 From: VincentRouvreau Date: Mon, 6 Sep 2021 15:51:20 +0200 Subject: Only dD version of Alpha complex for python --- src/python/include/Alpha_complex_interface_3d.h | 71 ------------------------- 1 file changed, 71 deletions(-) delete mode 100644 src/python/include/Alpha_complex_interface_3d.h (limited to 'src/python/include') diff --git a/src/python/include/Alpha_complex_interface_3d.h b/src/python/include/Alpha_complex_interface_3d.h deleted file mode 100644 index bb66b8e1..00000000 --- a/src/python/include/Alpha_complex_interface_3d.h +++ /dev/null @@ -1,71 +0,0 @@ -/* 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) 2021 Inria - * - * Modification(s): - * - YYYY/MM Author: Description of the modification - */ - -#ifndef INCLUDE_ALPHA_COMPLEX_INTERFACE_3D_H_ -#define INCLUDE_ALPHA_COMPLEX_INTERFACE_3D_H_ - -#include "Alpha_complex_factory.h" -#include - -#include "Simplex_tree_interface.h" - -#include -#include -#include -#include // for std::unique_ptr - -namespace Gudhi { - -namespace alpha_complex { - -class Alpha_complex_interface_3d { - public: - Alpha_complex_interface_3d(const std::vector>& points, - const std::vector& weights, - bool fast_version, bool exact_version) - : empty_point_set_(points.size() == 0) { - const bool weighted = (weights.size() > 0); - if (fast_version) - if (weighted) - alpha_ptr_ = std::make_unique>(points, weights); - else - alpha_ptr_ = std::make_unique>(points); - else if (exact_version) - if (weighted) - alpha_ptr_ = std::make_unique>(points, weights); - else - alpha_ptr_ = std::make_unique>(points); - else - if (weighted) - alpha_ptr_ = std::make_unique>(points, weights); - else - alpha_ptr_ = std::make_unique>(points); - } - - std::vector get_point(int vh) { - return alpha_ptr_->get_point(vh); - } - - void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square) { - // Nothing to be done in case of an empty point set - if (!empty_point_set_) - alpha_ptr_->create_simplex_tree(simplex_tree, max_alpha_square, false); - } - - private: - std::unique_ptr alpha_ptr_; - bool empty_point_set_; -}; - -} // namespace alpha_complex - -} // namespace Gudhi - -#endif // INCLUDE_ALPHA_COMPLEX_INTERFACE_3D_H_ -- cgit v1.2.3 From 11b8a288946c953472165ffbb5dbfbeb5ca64d26 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Mon, 8 Nov 2021 10:03:24 +0100 Subject: code review: factorization - Point_cgal_to_cython weighted version calls unweighted version --- src/python/include/Alpha_complex_factory.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/python/include') diff --git a/src/python/include/Alpha_complex_factory.h b/src/python/include/Alpha_complex_factory.h index 298469fe..8f820fc9 100644 --- a/src/python/include/Alpha_complex_factory.h +++ b/src/python/include/Alpha_complex_factory.h @@ -54,11 +54,7 @@ struct Point_cgal_to_cython { std::vector operator()(CgalPointType const& weighted_point) const { const auto& point = weighted_point.point(); - std::vector vd; - vd.reserve(point.dimension()); - for (auto coord = point.cartesian_begin(); coord != point.cartesian_end(); coord++) - vd.push_back(CGAL::to_double(*coord)); - return vd; + return Point_cgal_to_cython()(point); } }; -- cgit v1.2.3 From 72a56067c5a6f105ff60996e7257063505030e73 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Wed, 19 Jan 2022 09:50:13 +0100 Subject: Code review: exact_version was useless in Inexact_alpha_complex_dD --- src/python/include/Alpha_complex_factory.h | 14 +++++--------- src/python/include/Alpha_complex_interface.h | 4 ++-- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'src/python/include') diff --git a/src/python/include/Alpha_complex_factory.h b/src/python/include/Alpha_complex_factory.h index 8f820fc9..14ec1f86 100644 --- a/src/python/include/Alpha_complex_factory.h +++ b/src/python/include/Alpha_complex_factory.h @@ -118,15 +118,12 @@ class Inexact_alpha_complex_dD final : public Abstract_alpha_complex { typename Kernel::Point_d>; public: - Inexact_alpha_complex_dD(const std::vector>& points, bool exact_version) - : exact_version_(exact_version), - alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal)) { + Inexact_alpha_complex_dD(const std::vector>& points) + : alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal)) { } - Inexact_alpha_complex_dD(const std::vector>& points, - const std::vector& weights, bool exact_version) - : exact_version_(exact_version), - alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal), weights) { + Inexact_alpha_complex_dD(const std::vector>& points, const std::vector& weights) + : alpha_complex_(boost::adaptors::transform(points, pt_cython_to_cgal), weights) { } virtual std::vector get_point(int vh) override { @@ -135,11 +132,10 @@ class Inexact_alpha_complex_dD final : public Abstract_alpha_complex { } virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, bool default_filtration_value) override { - return alpha_complex_.create_complex(*simplex_tree, max_alpha_square, exact_version_, default_filtration_value); + return alpha_complex_.create_complex(*simplex_tree, max_alpha_square, false, default_filtration_value); } private: - bool exact_version_; Alpha_complex alpha_complex_; }; diff --git a/src/python/include/Alpha_complex_interface.h b/src/python/include/Alpha_complex_interface.h index ed243f19..188036ed 100644 --- a/src/python/include/Alpha_complex_interface.h +++ b/src/python/include/Alpha_complex_interface.h @@ -34,9 +34,9 @@ class Alpha_complex_interface { const bool weighted = (weights.size() > 0); if (fast_version) { if (weighted) { - alpha_ptr_ = std::make_unique>(points, weights, exact_version); + alpha_ptr_ = std::make_unique>(points, weights); } else { - alpha_ptr_ = std::make_unique>(points, exact_version); + alpha_ptr_ = std::make_unique>(points); } } else { if (weighted) { -- cgit v1.2.3 From e88833431fbdd2b58b00fe3d3cf84973700477b3 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Wed, 26 Jan 2022 09:49:20 +0100 Subject: Code review: Remove empty_point_set_ that can be deduced from num_vertices (new method in Alpha_complex -> Abstract_alpha_complex -> In/Exact_alpha_complex_dD -> Alpha_complex_interface --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 12 +++++++++++- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 15 +++++++++++++++ src/python/include/Alpha_complex_factory.h | 10 ++++++++++ src/python/include/Alpha_complex_interface.h | 6 ++---- 4 files changed, 38 insertions(+), 5 deletions(-) (limited to 'src/python/include') diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index e03bb161..028ec9bb 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -20,6 +20,7 @@ #include #include // isnan, fmax #include // for std::unique_ptr +#include // for std::size_t #include #include // aka. Weighted Delaunay triangulation @@ -213,6 +214,15 @@ class Alpha_complex { Alpha_complex (Alpha_complex&& other) = delete; Alpha_complex& operator= (Alpha_complex&& other) = delete; + /** \brief Returns the number of finite vertices in the triangulation. + */ + std::size_t num_vertices() const { + if (triangulation_ == nullptr) + return 0; + else + return triangulation_->number_of_vertices(); + } + /** \brief get_point returns the point corresponding to the vertex given as parameter. * * @param[in] vertex Vertex handle of the point to retrieve. @@ -373,7 +383,7 @@ class Alpha_complex { // -------------------------------------------------------------------------------------------- // Simplex_tree construction from loop on triangulation finite full cells list - if (triangulation_->number_of_vertices() > 0) { + if (num_vertices() > 0) { for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) { diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 4b37e4bd..f74ad217 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -56,6 +56,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_OFF_file, TestedKernel, list_of Gudhi::Simplex_tree<> simplex_tree_60; BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_60, max_alpha_square_value)); + std::clog << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == 7); + std::clog << "simplex_tree_60.dimension()=" << simplex_tree_60.dimension() << std::endl; BOOST_CHECK(simplex_tree_60.dimension() == 2); @@ -72,6 +75,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_OFF_file, TestedKernel, list_of Gudhi::Simplex_tree<> simplex_tree_59; BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_59, max_alpha_square_value)); + std::clog << "alpha_complex_from_file.num_vertices()=" << alpha_complex_from_file.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_file.num_vertices() == 7); + std::clog << "simplex_tree_59.dimension()=" << simplex_tree_59.dimension() << std::endl; BOOST_CHECK(simplex_tree_59.dimension() == 2); @@ -120,6 +126,9 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { Gudhi::Simplex_tree<> simplex_tree; BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree)); + std::clog << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() == points.size()); + // Another way to check num_simplices std::clog << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; int num_simplices = 0; @@ -240,6 +249,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_empty_points, TestedKernel, lis // ---------------------------------------------------------------------------- Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); + std::clog << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() == points.size()); + // Test to the limit BOOST_CHECK_THROW (alpha_complex_from_points.get_point(0), std::out_of_range); @@ -291,6 +303,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_with_duplicated_points, TestedKernel std::clog << "create_complex" << std::endl; BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree)); + std::clog << "alpha_complex_from_points.num_vertices()=" << alpha_complex_from_points.num_vertices() << std::endl; + BOOST_CHECK(alpha_complex_from_points.num_vertices() < points.size()); + std::clog << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; BOOST_CHECK(simplex_tree.num_vertices() < points.size()); diff --git a/src/python/include/Alpha_complex_factory.h b/src/python/include/Alpha_complex_factory.h index 14ec1f86..3d20aa8f 100644 --- a/src/python/include/Alpha_complex_factory.h +++ b/src/python/include/Alpha_complex_factory.h @@ -70,6 +70,8 @@ class Abstract_alpha_complex { virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, bool default_filtration_value) = 0; + + virtual std::size_t num_vertices() const = 0; virtual ~Abstract_alpha_complex() = default; }; @@ -104,6 +106,10 @@ class Exact_alpha_complex_dD final : public Abstract_alpha_complex { return alpha_complex_.create_complex(*simplex_tree, max_alpha_square, exact_version_, default_filtration_value); } + virtual std::size_t num_vertices() const { + return alpha_complex_.num_vertices(); + } + private: bool exact_version_; Alpha_complex alpha_complex_; @@ -135,6 +141,10 @@ class Inexact_alpha_complex_dD final : public Abstract_alpha_complex { return alpha_complex_.create_complex(*simplex_tree, max_alpha_square, false, default_filtration_value); } + virtual std::size_t num_vertices() const { + return alpha_complex_.num_vertices(); + } + private: Alpha_complex alpha_complex_; }; diff --git a/src/python/include/Alpha_complex_interface.h b/src/python/include/Alpha_complex_interface.h index 188036ed..671af4a4 100644 --- a/src/python/include/Alpha_complex_interface.h +++ b/src/python/include/Alpha_complex_interface.h @@ -29,8 +29,7 @@ class Alpha_complex_interface { public: Alpha_complex_interface(const std::vector>& points, const std::vector& weights, - bool fast_version, bool exact_version) - : empty_point_set_(points.size() == 0) { + bool fast_version, bool exact_version) { const bool weighted = (weights.size() > 0); if (fast_version) { if (weighted) { @@ -54,13 +53,12 @@ class Alpha_complex_interface { void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, bool default_filtration_value) { // Nothing to be done in case of an empty point set - if (!empty_point_set_) + if (alpha_ptr_->num_vertices() > 0) alpha_ptr_->create_simplex_tree(simplex_tree, max_alpha_square, default_filtration_value); } private: std::unique_ptr alpha_ptr_; - bool empty_point_set_; }; } // namespace alpha_complex -- cgit v1.2.3