12#ifndef ALPHA_COMPLEX_3D_H_ 
   13#define ALPHA_COMPLEX_3D_H_ 
   15#include <boost/variant.hpp> 
   16#include <boost/range/size.hpp> 
   17#include <boost/range/combine.hpp> 
   18#include <boost/range/adaptor/transformed.hpp> 
   20#include <gudhi/Debug_utils.h> 
   21#include <gudhi/Alpha_complex_options.h> 
   23#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> 
   24#include <CGAL/Exact_predicates_exact_constructions_kernel.h> 
   25#include <CGAL/Delaunay_triangulation_3.h> 
   26#include <CGAL/Periodic_3_Delaunay_triangulation_traits_3.h> 
   27#include <CGAL/Periodic_3_Delaunay_triangulation_3.h> 
   28#include <CGAL/Periodic_3_regular_triangulation_traits_3.h> 
   29#include <CGAL/Periodic_3_regular_triangulation_3.h> 
   30#include <CGAL/Regular_triangulation_3.h> 
   31#include <CGAL/Alpha_shape_3.h> 
   32#include <CGAL/Alpha_shape_cell_base_3.h> 
   33#include <CGAL/Alpha_shape_vertex_base_3.h> 
   35#include <CGAL/Object.h> 
   36#include <CGAL/tuple.h> 
   37#include <CGAL/iterator.h> 
   38#include <CGAL/version.h>   
   40#include <boost/container/static_vector.hpp> 
   44#include <unordered_map> 
   52#if CGAL_VERSION_NR < 1041101000 
   53# error Alpha_complex_3d is only available for CGAL >= 4.11 
   58namespace alpha_complex {
 
   65template <complexity Complexity>
 
   66struct Value_from_iterator {
 
   67  template <
typename Iterator>
 
   68  static double perform(Iterator it) {
 
   70    return CGAL::to_double(*it);
 
   76  template <
typename Iterator>
 
   77  static double perform(Iterator it) {
 
   78    return CGAL::to_double(it->exact());
 
  117template <complexity Complexity = complexity::SAFE, 
bool Weighted = false, 
bool Periodic = false>
 
  132  using Predicates = 
typename std::conditional<(Complexity == 
complexity::FAST),
 
  133                                               CGAL::Exact_predicates_inexact_constructions_kernel,
 
  134                                               CGAL::Exact_predicates_exact_constructions_kernel>::type;
 
  137  template <
typename Predicates, 
bool Weighted_version, 
bool Periodic_version>
 
  140  template <
typename Predicates, 
bool Is_periodic>
 
  141  struct Kernel_3<Predicates, Is_periodic, false> {
 
  142    using Kernel = Predicates;
 
  145  template <
typename Predicates>
 
  146  struct Kernel_3<Predicates, false, true> {
 
  147    using Kernel = CGAL::Periodic_3_Delaunay_triangulation_traits_3<Predicates>;
 
  149  template <
typename Predicates>
 
  150  struct Kernel_3<Predicates, true, true> {
 
  151    using Kernel = CGAL::Periodic_3_regular_triangulation_traits_3<Predicates>;
 
  155  using Kernel = 
typename Kernel_3<Predicates, Weighted, Periodic>::Kernel;
 
  158  using TdsVb = 
typename std::conditional<Periodic, CGAL::Periodic_3_triangulation_ds_vertex_base_3<>,
 
  159                                          CGAL::Triangulation_ds_vertex_base_3<>>::type;
 
  161  using Tvb = 
typename std::conditional<Weighted, CGAL::Regular_triangulation_vertex_base_3<Kernel, TdsVb>,
 
  162                                        CGAL::Triangulation_vertex_base_3<Kernel, TdsVb>>::type;
 
  164  using Vb = CGAL::Alpha_shape_vertex_base_3<Kernel, Tvb>;
 
  166  using TdsCb = 
typename std::conditional<Periodic, CGAL::Periodic_3_triangulation_ds_cell_base_3<>,
 
  167                                          CGAL::Triangulation_ds_cell_base_3<>>::type;
 
  169  using Tcb = 
typename std::conditional<Weighted, CGAL::Regular_triangulation_cell_base_3<Kernel, TdsCb>,
 
  170                                        CGAL::Triangulation_cell_base_3<Kernel, TdsCb>>::type;
 
  172  using Cb = CGAL::Alpha_shape_cell_base_3<Kernel, Tcb>;
 
  173  using Tds = CGAL::Triangulation_data_structure_3<Vb, Cb>;
 
  176  template <
typename Kernel, 
typename Tds, 
bool Weighted_version, 
bool Periodic_version>
 
  177  struct Triangulation_3 {};
 
  179  template <
typename Kernel, 
typename Tds>
 
  180  struct Triangulation_3<Kernel, Tds, false, false> {
 
  181    using Dt = CGAL::Delaunay_triangulation_3<Kernel, Tds>;
 
  184  template <
typename Kernel, 
typename Tds>
 
  185  struct Triangulation_3<Kernel, Tds, true, false> {
 
  186    using Dt = CGAL::Regular_triangulation_3<Kernel, Tds>;
 
  189  template <
typename Kernel, 
typename Tds>
 
  190  struct Triangulation_3<Kernel, Tds, false, true> {
 
  191    using Dt = CGAL::Periodic_3_Delaunay_triangulation_3<Kernel, Tds>;
 
  194  template <
typename Kernel, 
typename Tds>
 
  195  struct Triangulation_3<Kernel, Tds, true, true> {
 
  196    using Dt = CGAL::Periodic_3_regular_triangulation_3<Kernel, Tds>;
 
  207  using Dt = 
typename Triangulation_3<Kernel, Tds, Weighted, Periodic>::Dt;
 
  219  using FT = 
typename Alpha_shape_3::FT;
 
  243  using Weighted_point_3 = 
typename Triangulation_3<Kernel, Tds, Weighted, Periodic>::Weighted_point_3;
 
  248  using Point_3 = 
typename Alpha_shape_3::Point;
 
  252      CGAL::Dispatch_output_iterator<CGAL::cpp11::tuple<CGAL::Object, FT>,
 
  253                                     CGAL::cpp11::tuple<std::back_insert_iterator<std::vector<CGAL::Object>>,
 
  254                                                        std::back_insert_iterator<std::vector<FT>>>>;
 
  256  using Cell_handle = 
typename Alpha_shape_3::Cell_handle;
 
  257  using Facet = 
typename Alpha_shape_3::Facet;
 
  258  using Edge = 
typename Alpha_shape_3::Edge;
 
  259  using Alpha_vertex_handle = 
typename Alpha_shape_3::Vertex_handle;
 
  260  using Vertex_list = boost::container::static_vector<Alpha_vertex_handle, 4>;
 
  272  template <
typename InputPo
intRange>
 
  274    static_assert(!Periodic, 
"This constructor is not available for periodic versions of Alpha_complex_3d");
 
  276    alpha_shape_3_ptr_ = std::make_unique<Alpha_shape_3>(
 
  277        std::begin(points), std::end(points), 0, Alpha_shape_3::GENERAL);
 
  294  template <
typename InputPo
intRange, 
typename WeightRange>
 
  296    static_assert(Weighted, 
"This constructor is not available for non-weighted versions of Alpha_complex_3d");
 
  297    static_assert(!Periodic, 
"This constructor is not available for periodic versions of Alpha_complex_3d");
 
  299    GUDHI_CHECK(boost::size(weights) == boost::size(points),
 
  300                std::invalid_argument(
"Points number in range different from weights range number"));
 
  302    auto weighted_points_3 = boost::range::combine(points, weights)
 
  303      | boost::adaptors::transformed([](
auto const&t){
return Weighted_point_3(boost::get<0>(t), boost::get<1>(t));});
 
  305    alpha_shape_3_ptr_ = std::make_unique<Alpha_shape_3>(
 
  306        std::begin(weighted_points_3), std::end(weighted_points_3), 0, Alpha_shape_3::GENERAL);
 
  329  template <
typename InputPo
intRange>
 
  331                   FT z_min, 
FT x_max, 
FT y_max, 
FT z_max) {
 
  332    static_assert(Periodic, 
"This constructor is not available for non-periodic versions of Alpha_complex_3d");
 
  335        (x_max - x_min == y_max - y_min) && (x_max - x_min == z_max - z_min) && (z_max - z_min == y_max - y_min),
 
  336        std::invalid_argument(
"The size of the cuboid in every directions is not the same."));
 
  339    Dt pdt(
typename Kernel::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max));
 
  341    pdt.insert(std::begin(points), std::end(points), 
true);
 
  343    if (!pdt.is_triangulation_in_1_sheet()) {
 
  344      throw std::invalid_argument(
"Unable to construct a triangulation within a single periodic domain.");
 
  346    pdt.convert_to_1_sheeted_covering();
 
  350    alpha_shape_3_ptr_ = std::make_unique<Alpha_shape_3>(pdt, 0, Alpha_shape_3::GENERAL);
 
  377  template <
typename InputPo
intRange, 
typename WeightRange>
 
  379                   FT z_min, 
FT x_max, 
FT y_max, 
FT z_max) {
 
  380    static_assert(Weighted, 
"This constructor is not available for non-weighted versions of Alpha_complex_3d");
 
  381    static_assert(Periodic, 
"This constructor is not available for non-periodic versions of Alpha_complex_3d");
 
  383    GUDHI_CHECK(boost::size(weights) == boost::size(points),
 
  384                std::invalid_argument(
"Points number in range different from weights range number"));
 
  387        (x_max - x_min == y_max - y_min) && (x_max - x_min == z_max - z_min) && (z_max - z_min == y_max - y_min),
 
  388        std::invalid_argument(
"The size of the cuboid in every directions is not the same."));
 
  392    FT maximal_possible_weight = 0.015625 * (x_max - x_min) * (x_max - x_min);
 
  395    auto weighted_points_3 = boost::range::combine(points, weights)
 
  396      | boost::adaptors::transformed([=](
auto const&t){
 
  397          auto w = boost::get<1>(t);
 
  398          GUDHI_CHECK((w < maximal_possible_weight) && (w >= 0),
 
  399              std::invalid_argument(
"Invalid weight " + std::to_string(w) +
 
  400                ". Must be non-negative and less than maximal possible weight = 1/64*cuboid length squared."));
 
  405    Dt pdt(
typename Kernel::Iso_cuboid_3(x_min, y_min, z_min, x_max, y_max, z_max));
 
  407    pdt.insert(std::begin(weighted_points_3), std::end(weighted_points_3), 
true);
 
  409    if (!pdt.is_triangulation_in_1_sheet()) {
 
  410      throw std::invalid_argument(
"Unable to construct a triangulation within a single periodic domain.");
 
  412    pdt.convert_to_1_sheeted_covering();
 
  416    alpha_shape_3_ptr_ = std::make_unique<Alpha_shape_3>(pdt, 0, Alpha_shape_3::GENERAL);
 
  436                      Filtration_value max_alpha_square = std::numeric_limits<Filtration_value>::infinity()) {
 
  438      std::cerr << 
"Alpha_complex_3d create_complex - complex is not empty\n";
 
  443    using Simplex_tree_vector_vertex = std::vector<Complex_vertex_handle>;
 
  446    std::size_t count_vertices = 0;
 
  447    std::size_t count_edges = 0;
 
  448    std::size_t count_facets = 0;
 
  449    std::size_t count_cells = 0;
 
  451    std::vector<CGAL::Object> objects;
 
  452    std::vector<FT> alpha_values;
 
  454    Dispatch dispatcher = CGAL::dispatch_output<CGAL::Object, FT>(std::back_inserter(objects),
 
  455                                                                                std::back_inserter(alpha_values));
 
  457    alpha_shape_3_ptr_->filtration_with_alpha_values(dispatcher);
 
  459    std::clog << 
"filtration_with_alpha_values returns : " << objects.size() << 
" objects" << std::endl;
 
  461    if (objects.size() == 0) {
 
  462      std::cerr << 
"Alpha_complex_3d create_complex - no triangulation as points are on a 2d plane\n";
 
  466    using Alpha_value_iterator = 
typename std::vector<FT>::const_iterator;
 
  467    Alpha_value_iterator alpha_value_iterator = alpha_values.begin();
 
  468    for (
auto object_iterator : objects) {
 
  469      Vertex_list vertex_list;
 
  472      if (
const Cell_handle* cell = CGAL::object_cast<Cell_handle>(&object_iterator)) {
 
  473        for (
auto i = 0; i < 4; i++) {
 
  475          std::clog << 
"from cell[" << i << 
"] - Point coordinates (" << (*cell)->vertex(i)->point() << 
")" 
  478          vertex_list.push_back((*cell)->vertex(i));
 
  483      } 
else if (
const Facet* facet = CGAL::object_cast<Facet>(&object_iterator)) {
 
  484        for (
auto i = 0; i < 4; i++) {
 
  485          if ((*facet).second != i) {
 
  487            std::clog << 
"from facet=[" << i << 
"] - Point coordinates (" << (*facet).first->vertex(i)->point() << 
")" 
  490            vertex_list.push_back((*facet).first->vertex(i));
 
  496      } 
else if (
const Edge* edge = CGAL::object_cast<Edge>(&object_iterator)) {
 
  497        for (
auto i : {(*edge).second, (*edge).third}) {
 
  499          std::clog << 
"from edge[" << i << 
"] - Point coordinates (" << (*edge).first->vertex(i)->point() << 
")" 
  502          vertex_list.push_back((*edge).first->vertex(i));
 
  507      } 
else if (
const Alpha_vertex_handle* vertex = CGAL::object_cast<Alpha_vertex_handle>(&object_iterator)) {
 
  510        std::clog << 
"from vertex - Point coordinates (" << (*vertex)->point() << 
")" << std::endl;
 
  512        vertex_list.push_back((*vertex));
 
  515      Simplex_tree_vector_vertex the_simplex;
 
  516      for (
auto the_alpha_shape_vertex : vertex_list) {
 
  517        auto the_map_iterator = map_cgal_simplex_tree.find(the_alpha_shape_vertex);
 
  518        if (the_map_iterator == map_cgal_simplex_tree.end()) {
 
  520          Complex_vertex_handle vertex = map_cgal_simplex_tree.size();
 
  522          std::clog << 
"Point (" << the_alpha_shape_vertex->point() << 
") not found - insert new vertex id " << vertex
 
  525          the_simplex.push_back(vertex);
 
  526          map_cgal_simplex_tree.emplace(the_alpha_shape_vertex, vertex);
 
  529          Complex_vertex_handle vertex = the_map_iterator->second;
 
  531          std::clog << 
"Point (" << the_alpha_shape_vertex->point() << 
") found as vertex id " << vertex << std::endl;
 
  533          the_simplex.push_back(vertex);
 
  537      Filtration_value filtr = Value_from_iterator<Complexity>::perform(alpha_value_iterator);
 
  540      std::clog << 
"filtration = " << filtr << std::endl;
 
  543      GUDHI_CHECK(alpha_value_iterator != alpha_values.end(), 
"CGAL provided more simplices than values");
 
  544      ++alpha_value_iterator;
 
  548    std::clog << 
"vertices \t" << count_vertices << std::endl;
 
  549    std::clog << 
"edges \t\t" << count_edges << std::endl;
 
  550    std::clog << 
"facets \t\t" << count_facets << std::endl;
 
  551    std::clog << 
"cells \t\t" << count_cells << std::endl;
 
  571    if (map_cgal_simplex_tree.size() != cgal_vertex_iterator_vector.size()) {
 
  572      cgal_vertex_iterator_vector.resize(map_cgal_simplex_tree.size());
 
  573      for (
auto map_iterator : map_cgal_simplex_tree) {
 
  574        cgal_vertex_iterator_vector[map_iterator.second] = map_iterator.first;
 
  578    auto cgal_vertex_iterator = cgal_vertex_iterator_vector.at(vertex);
 
  579    return cgal_vertex_iterator->point();
 
  584  std::unique_ptr<Alpha_shape_3> alpha_shape_3_ptr_;
 
  587  std::unordered_map<Alpha_vertex_handle, std::size_t> map_cgal_simplex_tree;
 
  589  std::vector<Alpha_vertex_handle> cgal_vertex_iterator_vector;
 
Alpha complex data structure for 3d specific case.
Definition: Alpha_complex_3d.h:118
CGAL::Alpha_shape_3< Dt > Alpha_shape_3
The CGAL 3D Alpha Shapes type.
Definition: Alpha_complex_3d.h:215
Alpha_complex_3d(const InputPointRange &points)
Alpha_complex constructor from a list of points.
Definition: Alpha_complex_3d.h:273
bool create_complex(SimplicialComplexForAlpha3d &complex, Filtration_value max_alpha_square=std::numeric_limits< Filtration_value >::infinity())
Inserts all Delaunay triangulation into the simplicial complex. It also computes the filtration value...
Definition: Alpha_complex_3d.h:435
Alpha_complex_3d(const InputPointRange &points, WeightRange weights, FT x_min, FT y_min, FT z_min, FT x_max, FT y_max, FT z_max)
Alpha_complex constructor from a list of points, associated weights and an iso-cuboid coordinates.
Definition: Alpha_complex_3d.h:378
Alpha_complex_3d(const InputPointRange &points, WeightRange weights)
Alpha_complex constructor from a list of points and associated weights.
Definition: Alpha_complex_3d.h:295
typename Kernel::Point_3 Bare_point_3
Gives public access to the Bare_point_3 (bare aka. unweighed) type. Here is a Bare_point_3 constructo...
Definition: Alpha_complex_3d.h:230
typename Triangulation_3< Kernel, Tds, Weighted, Periodic >::Weighted_point_3 Weighted_point_3
Gives public access to the Weighted_point_3 type. A Weighted point can be constructed as follows:
Definition: Alpha_complex_3d.h:243
typename Alpha_shape_3::Point Point_3
Alpha_complex_3d::Point_3 type is either a Alpha_complex_3d::Bare_point_3 (Weighted = false) or a Alp...
Definition: Alpha_complex_3d.h:248
typename Alpha_shape_3::FT FT
The alpha values type. Must be compatible with double.
Definition: Alpha_complex_3d.h:219
Alpha_complex_3d(const InputPointRange &points, FT x_min, FT y_min, FT z_min, FT x_max, FT y_max, FT z_max)
Alpha_complex constructor from a list of points and an iso-cuboid coordinates.
Definition: Alpha_complex_3d.h:330
const Point_3 & get_point(std::size_t vertex)
get_point returns the point corresponding to the vertex given as parameter.
Definition: Alpha_complex_3d.h:570
complexity
Alpha complex complexity template parameter possible values.
Definition: Alpha_complex_options.h:23
Value type for a filtration function on a cell complex.
Definition: FiltrationValue.h:20
The concept SimplicialComplexForAlpha3d describes the requirements for a type to implement a simplici...
Definition: SimplicialComplexForAlpha3d.h:21
void make_filtration_non_decreasing()
void insert_simplex(std::vector< Vertex_handle > const &vertex_range, Filtration_value filtration)
Inserts a simplex from a given simplex (represented by a vector of Vertex_handle) in the simplicial c...
unspecified Filtration_value
Definition: SimplicialComplexForAlpha3d.h:25
unspecified Vertex_handle
Definition: SimplicialComplexForAlpha3d.h:23
void prune_above_filtration(Filtration_value filtration)
std::size_t num_vertices()