summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorGard Spreemann <gspreemann@gmail.com>2017-04-20 11:10:45 +0200
committerGard Spreemann <gspreemann@gmail.com>2017-04-20 11:10:45 +0200
commit8d7329f3e5ad843e553c3c5503cecc28ef2eead6 (patch)
tree6d80d83a7c4bcd3296e12a28404bfe84ef84ed55 /include
parent55c7181126aa7defce38c9b82872d14223d4c1dd (diff)
GUDHI 2.0.0 as released by upstream in a tarball.upstream/2.0.0
Diffstat (limited to 'include')
-rw-r--r--include/gudhi/Active_witness/Active_witness.h67
-rw-r--r--include/gudhi/Active_witness/Active_witness_iterator.h108
-rw-r--r--include/gudhi/Alpha_complex.h233
-rw-r--r--include/gudhi/Alpha_complex.h~417
-rw-r--r--include/gudhi/Bottleneck.h115
-rw-r--r--include/gudhi/Clock.h48
-rw-r--r--include/gudhi/Debug_utils.h2
-rw-r--r--include/gudhi/Edge_contraction.h2
-rw-r--r--include/gudhi/Euclidean_strong_witness_complex.h104
-rw-r--r--include/gudhi/Euclidean_witness_complex.h106
-rw-r--r--include/gudhi/Graph_matching.h174
-rw-r--r--include/gudhi/Internal_point.h91
-rw-r--r--include/gudhi/Kd_tree_search.h264
-rw-r--r--include/gudhi/Landmark_choice_by_furthest_point.h105
-rw-r--r--include/gudhi/Landmark_choice_by_random_point.h96
-rw-r--r--include/gudhi/Neighbors_finder.h192
-rw-r--r--include/gudhi/Null_output_iterator.h48
-rw-r--r--include/gudhi/Persistence_graph.h188
-rw-r--r--include/gudhi/Persistent_cohomology.h26
-rw-r--r--include/gudhi/Points_3D_off_io.h4
-rw-r--r--include/gudhi/Points_off_io.h13
-rw-r--r--include/gudhi/Rips_complex.h185
-rw-r--r--include/gudhi/Simplex_tree.h2
-rw-r--r--include/gudhi/Skeleton_blocker.h219
-rw-r--r--include/gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h53
-rw-r--r--include/gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h14
-rw-r--r--include/gudhi/Skeleton_blocker/Skeleton_blocker_off_io.h11
-rw-r--r--include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h13
-rw-r--r--include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h38
-rw-r--r--include/gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h12
-rw-r--r--include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h49
-rw-r--r--include/gudhi/Skeleton_blocker/internal/Top_faces.h5
-rw-r--r--include/gudhi/Skeleton_blocker/internal/Trie.h9
-rw-r--r--include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_blockers_iterators.h3
-rw-r--r--include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_edges_iterators.h3
-rw-r--r--include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h2
-rw-r--r--include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h38
-rw-r--r--include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_triangles_iterators.h14
-rw-r--r--include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_vertices_iterators.h12
-rw-r--r--include/gudhi/Skeleton_blocker_complex.h33
-rw-r--r--include/gudhi/Skeleton_blocker_geometric_complex.h3
-rw-r--r--include/gudhi/Skeleton_blocker_link_complex.h30
-rw-r--r--include/gudhi/Skeleton_blocker_simplifiable_complex.h13
-rw-r--r--include/gudhi/Strong_witness_complex.h185
-rw-r--r--include/gudhi/Tangential_complex.h2276
-rw-r--r--include/gudhi/Tangential_complex/Simplicial_complex.h539
-rw-r--r--include/gudhi/Tangential_complex/config.h43
-rw-r--r--include/gudhi/Tangential_complex/utilities.h195
-rw-r--r--include/gudhi/Test.h105
-rw-r--r--include/gudhi/Witness_complex.h333
-rw-r--r--include/gudhi/Witness_complex/all_faces_in.h55
-rw-r--r--include/gudhi/choose_n_farthest_points.h133
-rw-r--r--include/gudhi/console_color.h97
-rw-r--r--include/gudhi/distance_functions.h40
-rw-r--r--include/gudhi/graph_simplicial_complex.h59
-rw-r--r--include/gudhi/pick_n_random_points.h86
-rw-r--r--include/gudhi/random_point_generators.h474
-rw-r--r--include/gudhi/reader_utils.h166
-rw-r--r--include/gudhi/sparsify_point_set.h113
-rw-r--r--include/gudhi_patches/Bottleneck_distance_CGAL_patches.txt3
-rw-r--r--include/gudhi_patches/CGAL/Convex_hull.h56
-rw-r--r--include/gudhi_patches/CGAL/Delaunay_triangulation.h933
-rw-r--r--include/gudhi_patches/CGAL/Epeck_d.h53
-rw-r--r--include/gudhi_patches/CGAL/Epick_d.h71
-rw-r--r--include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h320
-rw-r--r--include/gudhi_patches/CGAL/Kd_tree.h582
-rw-r--r--include/gudhi_patches/CGAL/Kd_tree_node.h586
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h177
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h344
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h40
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h117
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h33
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h79
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h93
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h33
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h95
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h330
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h50
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h49
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h137
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h199
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h104
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h102
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h298
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h134
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h175
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h162
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h188
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h59
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h159
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h88
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h66
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h66
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h121
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h132
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h205
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h165
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h213
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h76
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h211
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h201
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h164
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h58
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h164
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h46
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h145
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h181
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h167
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h305
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h131
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h284
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h120
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h133
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h130
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h266
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h129
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h1355
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h40
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h363
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/static_int.h61
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h104
-rw-r--r--include/gudhi_patches/CGAL/NewKernel_d/utils.h306
-rw-r--r--include/gudhi_patches/CGAL/Orthogonal_incremental_neighbor_search.h620
-rw-r--r--include/gudhi_patches/CGAL/Regular_triangulation.h1169
-rw-r--r--include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h288
-rw-r--r--include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h99
-rw-r--r--include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h71
-rw-r--r--include/gudhi_patches/CGAL/Triangulation.h1424
-rw-r--r--include/gudhi_patches/CGAL/Triangulation_data_structure.h1603
-rw-r--r--include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h311
-rw-r--r--include/gudhi_patches/CGAL/Triangulation_ds_vertex.h154
-rw-r--r--include/gudhi_patches/CGAL/Triangulation_face.h111
-rw-r--r--include/gudhi_patches/CGAL/Triangulation_full_cell.h148
-rw-r--r--include/gudhi_patches/CGAL/Triangulation_vertex.h128
-rw-r--r--include/gudhi_patches/CGAL/argument_swaps.h88
-rw-r--r--include/gudhi_patches/CGAL/determinant_of_vectors.h117
-rw-r--r--include/gudhi_patches/CGAL/internal/Combination_enumerator.h148
-rw-r--r--include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h116
-rw-r--r--include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h49
-rw-r--r--include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h154
-rw-r--r--include/gudhi_patches/CGAL/internal/Triangulation/utilities.h154
-rw-r--r--include/gudhi_patches/CGAL/iterator_from_indices.h75
-rw-r--r--include/gudhi_patches/CGAL/transforming_iterator.h123
-rw-r--r--include/gudhi_patches/CGAL/transforming_pair_iterator.h127
-rw-r--r--include/gudhi_patches/CGAL/typeset.h117
-rw-r--r--include/gudhi_patches/Tangential_complex_CGAL_patches.txt82
146 files changed, 26039 insertions, 1457 deletions
diff --git a/include/gudhi/Active_witness/Active_witness.h b/include/gudhi/Active_witness/Active_witness.h
new file mode 100644
index 00000000..d41a6811
--- /dev/null
+++ b/include/gudhi/Active_witness/Active_witness.h
@@ -0,0 +1,67 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2016 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACTIVE_WITNESS_ACTIVE_WITNESS_H_
+#define ACTIVE_WITNESS_ACTIVE_WITNESS_H_
+
+#include <gudhi/Active_witness/Active_witness_iterator.h>
+#include <list>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+ /* \class Active_witness
+ * \brief Class representing a list of nearest neighbors to a given witness.
+ * \details Every element is a pair of a landmark identifier and the squared distance to it.
+ */
+template< typename Id_distance_pair,
+ typename INS_range >
+class Active_witness {
+ public:
+ typedef Active_witness<Id_distance_pair, INS_range> ActiveWitness;
+ typedef typename INS_range::iterator INS_iterator;
+ typedef Active_witness_iterator< ActiveWitness, Id_distance_pair, INS_iterator > iterator;
+ typedef typename std::list<Id_distance_pair> Table;
+
+ Table nearest_landmark_table_;
+ INS_range search_range_;
+ INS_iterator iterator_next_;
+ INS_iterator iterator_end_;
+
+ Active_witness(const INS_range& search_range)
+ : search_range_(search_range), iterator_next_(search_range_.begin()), iterator_end_(search_range_.end()) {
+ }
+
+ iterator begin() {
+ return iterator(this, nearest_landmark_table_.begin());
+ }
+
+ iterator end() {
+ return iterator(this);
+ }
+};
+
+} // namespace witness_complex
+} // namespace Gudhi
+
+#endif // ACTIVE_WITNESS_ACTIVE_WITNESS_H_
diff --git a/include/gudhi/Active_witness/Active_witness_iterator.h b/include/gudhi/Active_witness/Active_witness_iterator.h
new file mode 100644
index 00000000..0a05173a
--- /dev/null
+++ b/include/gudhi/Active_witness/Active_witness_iterator.h
@@ -0,0 +1,108 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2016 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACTIVE_WITNESS_ACTIVE_WITNESS_ITERATOR_H_
+#define ACTIVE_WITNESS_ACTIVE_WITNESS_ITERATOR_H_
+
+#include <boost/iterator/iterator_facade.hpp>
+#include <list>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+/* \brief Iterator in the nearest landmark list.
+ * \details After the iterator reaches the end of the list,
+ * the list is augmented by a (nearest landmark, distance) pair if possible.
+ * If all the landmarks are present in the list, iterator returns the specific end value
+ * of the corresponding 'Active_witness' object.
+ */
+template< typename Active_witness,
+ typename Id_distance_pair,
+ typename INS_iterator >
+class Active_witness_iterator
+ : public boost::iterator_facade< Active_witness_iterator <Active_witness, Id_distance_pair, INS_iterator>,
+ Id_distance_pair const,
+ boost::forward_traversal_tag,
+ Id_distance_pair const> {
+ friend class boost::iterator_core_access;
+
+ typedef typename std::list<Id_distance_pair>::iterator Pair_iterator;
+ typedef typename Gudhi::witness_complex::Active_witness_iterator<Active_witness,
+ Id_distance_pair,
+ INS_iterator> Iterator;
+
+ Active_witness *aw_;
+ Pair_iterator lh_; // landmark handle
+ bool is_end_; // true only if the pointer is end and there are no more neighbors to add
+
+ public:
+ Active_witness_iterator(Active_witness* aw)
+ : aw_(aw), lh_(aw_->nearest_landmark_table_.end()), is_end_(true) {
+ }
+
+ Active_witness_iterator(Active_witness* aw, const Pair_iterator& lh)
+ : aw_(aw), lh_(lh) {
+ is_end_ = false;
+ if (lh_ == aw_->nearest_landmark_table_.end()) {
+ if (aw_->iterator_next_ == aw_->iterator_end_) {
+ is_end_ = true;
+ } else {
+ aw_->nearest_landmark_table_.push_back(*aw_->iterator_next_);
+ lh_ = --aw_->nearest_landmark_table_.end();
+ ++(aw_->iterator_next_);
+ }
+ }
+ }
+
+ private :
+ Id_distance_pair& dereference() const {
+ return *lh_;
+ }
+
+ bool equal(const Iterator& other) const {
+ return (is_end_ == other.is_end_) || (lh_ == other.lh_);
+ }
+
+ void increment() {
+ // the neighbor search can't be at the end iterator of a list
+ GUDHI_CHECK(!is_end_ && lh_ != aw_->nearest_landmark_table_.end(),
+ std::logic_error("Wrong active witness increment."));
+ // if the id of the current landmark is the same as the last one
+
+ lh_++;
+ if (lh_ == aw_->nearest_landmark_table_.end()) {
+ if (aw_->iterator_next_ == aw_->iterator_end_) {
+ is_end_ = true;
+ } else {
+ aw_->nearest_landmark_table_.push_back(*aw_->iterator_next_);
+ lh_ = std::prev(aw_->nearest_landmark_table_.end());
+ ++(aw_->iterator_next_);
+ }
+ }
+ }
+};
+
+} // namespace witness_complex
+} // namespace Gudhi
+
+#endif // ACTIVE_WITNESS_ACTIVE_WITNESS_ITERATOR_H_
diff --git a/include/gudhi/Alpha_complex.h b/include/gudhi/Alpha_complex.h
index 2c95ceb4..1ff95c3d 100644
--- a/include/gudhi/Alpha_complex.h
+++ b/include/gudhi/Alpha_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): Vincent Rouvreau
*
- * Copyright (C) 2015 INRIA Saclay (France)
+ * Copyright (C) 2015 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,9 +23,6 @@
#ifndef ALPHA_COMPLEX_H_
#define ALPHA_COMPLEX_H_
-// to construct a simplex_tree from Delaunay_triangulation
-#include <gudhi/graph_simplicial_complex.h>
-#include <gudhi/Simplex_tree.h>
#include <gudhi/Debug_utils.h>
// to construct Alpha_complex from a OFF file of points
#include <gudhi/Points_off_io.h>
@@ -36,6 +33,7 @@
#include <CGAL/Delaunay_triangulation.h>
#include <CGAL/Epick_d.h>
#include <CGAL/Spatial_sort_traits_adapter_d.h>
+#include <CGAL/property_map.h> // for CGAL::Identity_property_map
#include <iostream>
#include <vector>
@@ -57,9 +55,9 @@ namespace alpha_complex {
* \ingroup alpha_complex
*
* \details
- * The data structure can be constructed from a CGAL Delaunay triangulation (for more informations on CGAL Delaunay
- * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) or from
- * an OFF file (cf. Points_off_reader).
+ * The data structure is constructing a CGAL Delaunay triangulation (for more informations on CGAL Delaunay
+ * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) from a
+ * range of points or from an OFF file (cf. Points_off_reader).
*
* Please refer to \ref alpha_complex for examples.
*
@@ -74,7 +72,7 @@ namespace alpha_complex {
*
*/
template<class Kernel = CGAL::Epick_d<CGAL::Dynamic_dimension_tag>>
-class Alpha_complex : public Simplex_tree<> {
+class Alpha_complex {
public:
// Add an int in TDS to save point index in the structure
typedef CGAL::Triangulation_data_structure<typename Kernel::Dimension,
@@ -90,13 +88,6 @@ class Alpha_complex : public Simplex_tree<> {
typedef Kernel Geom_traits;
private:
- // From Simplex_tree
- // Type required to insert into a simplex_tree (with or without subfaces).
- typedef std::vector<Vertex_handle> Vector_vertex;
-
- // Simplex_result is the type returned from simplex_tree insert function.
- typedef typename std::pair<Simplex_handle, bool> Simplex_result;
-
typedef typename Kernel::Compute_squared_radius_d Squared_Radius;
typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel;
typedef typename Kernel::Point_dimension_d Point_Dimension;
@@ -111,7 +102,7 @@ class Alpha_complex : public Simplex_tree<> {
typedef typename Delaunay_triangulation::size_type size_type;
// Map type to switch from simplex tree vertex handle to CGAL vertex iterator.
- typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Vector_vertex_iterator;
+ typedef typename std::map< std::size_t, CGAL_vertex_iterator > Vector_vertex_iterator;
private:
/** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator.
@@ -124,16 +115,15 @@ class Alpha_complex : public Simplex_tree<> {
public:
/** \brief Alpha_complex constructor from an OFF file name.
- * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize
+ *
+ * Uses the Points_off_reader to construct the Delaunay triangulation required to initialize
* the Alpha_complex.
*
* Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous.
*
* @param[in] off_file_name OFF file [path and] name.
- * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$.
*/
- Alpha_complex(const std::string& off_file_name,
- Filtration_value max_alpha_square = std::numeric_limits<Filtration_value>::infinity())
+ Alpha_complex(const std::string& off_file_name)
: triangulation_(nullptr) {
Gudhi::Points_off_reader<Point_d> off_reader(off_file_name);
if (!off_reader.is_valid()) {
@@ -141,7 +131,7 @@ class Alpha_complex : public Simplex_tree<> {
exit(-1); // ----- >>
}
- init_from_range(off_reader.get_point_cloud(), max_alpha_square);
+ init_from_range(off_reader.get_point_cloud());
}
/** \brief Alpha_complex constructor from a list of points.
@@ -149,23 +139,17 @@ class Alpha_complex : public Simplex_tree<> {
* Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous.
*
* @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d
- * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$.
*
* The type InputPointRange must be a range for which std::begin and
* std::end return input iterators on a Kernel::Point_d.
- *
- * @post Compare num_simplices with InputPointRange points number (not the same in case of duplicate points).
*/
template<typename InputPointRange >
- Alpha_complex(const InputPointRange& points,
- Filtration_value max_alpha_square = std::numeric_limits<Filtration_value>::infinity())
+ Alpha_complex(const InputPointRange& points)
: triangulation_(nullptr) {
- init_from_range(points, max_alpha_square);
+ init_from_range(points);
}
- /** \brief Alpha_complex destructor.
- *
- * @warning Deletes the Delaunay triangulation.
+ /** \brief Alpha_complex destructor deletes the Delaunay triangulation.
*/
~Alpha_complex() {
delete triangulation_;
@@ -183,15 +167,24 @@ class Alpha_complex : public Simplex_tree<> {
* @return The point found.
* @exception std::out_of_range In case vertex is not found (cf. std::vector::at).
*/
- Point_d get_point(Vertex_handle vertex) const {
+ const Point_d& get_point(std::size_t vertex) const {
return vertex_handle_to_iterator_.at(vertex)->point();
}
+ /** \brief number_of_vertices returns the number of vertices (same as the number of points).
+ *
+ * @return The number of vertices.
+ */
+ const std::size_t number_of_vertices() const {
+ return vertex_handle_to_iterator_.size();
+ }
+
private:
template<typename InputPointRange >
- void init_from_range(const InputPointRange& points, Filtration_value max_alpha_square) {
+ void init_from_range(const InputPointRange& points) {
auto first = std::begin(points);
auto last = std::end(points);
+
if (first != last) {
// point_dimension function initialization
Point_Dimension point_dimension = kernel_.point_dimension_d_object();
@@ -199,90 +192,107 @@ class Alpha_complex : public Simplex_tree<> {
// Delaunay triangulation is point dimension.
triangulation_ = new Delaunay_triangulation(point_dimension(*first));
- std::vector<Point_d> points(first, last);
+ std::vector<Point_d> point_cloud(first, last);
// Creates a vector {0, 1, ..., N-1}
std::vector<std::ptrdiff_t> indices(boost::counting_iterator<std::ptrdiff_t>(0),
- boost::counting_iterator<std::ptrdiff_t>(points.size()));
+ boost::counting_iterator<std::ptrdiff_t>(point_cloud.size()));
+
+ typedef boost::iterator_property_map<typename std::vector<Point_d>::iterator,
+ CGAL::Identity_property_map<std::ptrdiff_t>> Point_property_map;
+ typedef CGAL::Spatial_sort_traits_adapter_d<Kernel, Point_property_map> Search_traits_d;
- // Sort indices considering CGAL spatial sort
- typedef CGAL::Spatial_sort_traits_adapter_d<Kernel, Point_d*> Search_traits_d;
- spatial_sort(indices.begin(), indices.end(), Search_traits_d(&(points[0])));
+ CGAL::spatial_sort(indices.begin(), indices.end(), Search_traits_d(std::begin(point_cloud)));
typename Delaunay_triangulation::Full_cell_handle hint;
for (auto index : indices) {
- typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(points[index], hint);
+ typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(point_cloud[index], hint);
// Save index value as data to retrieve it after insertion
pos->data() = index;
hint = pos->full_cell();
}
- init(max_alpha_square);
+ // --------------------------------------------------------------------------------------------
+ // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa
+ // Loop on triangulation vertices list
+ for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) {
+ if (!triangulation_->is_infinite(*vit)) {
+#ifdef DEBUG_TRACES
+ std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl;
+#endif // DEBUG_TRACES
+ vertex_handle_to_iterator_.emplace(vit->data(), vit);
+ }
+ }
+ // --------------------------------------------------------------------------------------------
}
}
- /** \brief Initialize the Alpha_complex from the Delaunay triangulation.
+ public:
+ template <typename SimplicialComplexForAlpha>
+ bool create_complex(SimplicialComplexForAlpha& complex) {
+ typedef typename SimplicialComplexForAlpha::Filtration_value Filtration_value;
+ return create_complex(complex, std::numeric_limits<Filtration_value>::infinity());
+ }
+
+ /** \brief Inserts all Delaunay triangulation into the simplicial complex.
+ * It also computes the filtration values accordingly to the \ref createcomplexalgorithm
*
- * @param[in] max_alpha_square maximum for alpha square value.
+ * \tparam SimplicialComplexForAlpha must meet `SimplicialComplexForAlpha` concept.
*
- * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more
- * than 0.
+ * @param[in] complex SimplicialComplexForAlpha to be created.
+ * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$.
+ *
+ * @return true if creation succeeds, false otherwise.
+ *
+ * @pre Delaunay triangulation must be already constructed with dimension strictly greater than 0.
+ * @pre The simplicial complex must be empty (no vertices)
*
* Initialization can be launched once.
*/
- void init(Filtration_value max_alpha_square) {
+ template <typename SimplicialComplexForAlpha, typename Filtration_value>
+ bool create_complex(SimplicialComplexForAlpha& complex, Filtration_value max_alpha_square) {
+ // From SimplicialComplexForAlpha type required to insert into a simplicial complex (with or without subfaces).
+ typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle;
+ typedef typename SimplicialComplexForAlpha::Simplex_handle Simplex_handle;
+ typedef std::vector<Vertex_handle> Vector_vertex;
+
if (triangulation_ == nullptr) {
- std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation\n";
- return; // ----- >>
- }
- if (triangulation_->number_of_vertices() < 1) {
- std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices\n";
- return; // ----- >>
+ std::cerr << "Alpha_complex cannot create_complex from a NULL triangulation\n";
+ return false; // ----- >>
}
if (triangulation_->maximal_dimension() < 1) {
- std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation\n";
- return; // ----- >>
+ std::cerr << "Alpha_complex cannot create_complex from a zero-dimension triangulation\n";
+ return false; // ----- >>
}
- if (num_vertices() > 0) {
- std::cerr << "Alpha_complex init - Cannot init twice\n";
- return; // ----- >>
+ if (complex.num_vertices() > 0) {
+ std::cerr << "Alpha_complex create_complex - complex is not empty\n";
+ return false; // ----- >>
}
- set_dimension(triangulation_->maximal_dimension());
-
- // --------------------------------------------------------------------------------------------
- // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa
- // Loop on triangulation vertices list
- for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) {
- if (!triangulation_->is_infinite(*vit)) {
-#ifdef DEBUG_TRACES
- std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl;
-#endif // DEBUG_TRACES
- vertex_handle_to_iterator_.emplace(vit->data(), vit);
- }
- }
- // --------------------------------------------------------------------------------------------
+ complex.set_dimension(triangulation_->maximal_dimension());
// --------------------------------------------------------------------------------------------
// Simplex_tree construction from loop on triangulation finite full cells list
- for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) {
- Vector_vertex vertexVector;
+ if (triangulation_->number_of_vertices() > 0) {
+ for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) {
+ Vector_vertex vertexVector;
#ifdef DEBUG_TRACES
- std::cout << "Simplex_tree insertion ";
+ std::cout << "Simplex_tree insertion ";
#endif // DEBUG_TRACES
- for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) {
- if (*vit != nullptr) {
+ for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) {
+ if (*vit != nullptr) {
#ifdef DEBUG_TRACES
- std::cout << " " << (*vit)->data();
+ std::cout << " " << (*vit)->data();
#endif // DEBUG_TRACES
- // Vector of vertex construction for simplex_tree structure
- vertexVector.push_back((*vit)->data());
+ // Vector of vertex construction for simplex_tree structure
+ vertexVector.push_back((*vit)->data());
+ }
}
- }
#ifdef DEBUG_TRACES
- std::cout << std::endl;
+ std::cout << std::endl;
#endif // DEBUG_TRACES
- // Insert each simplex and its subfaces in the simplex tree - filtration is NaN
- insert_simplex_and_subfaces(vertexVector, std::numeric_limits<double>::quiet_NaN());
+ // Insert each simplex and its subfaces in the simplex tree - filtration is NaN
+ complex.insert_simplex_and_subfaces(vertexVector, std::numeric_limits<double>::quiet_NaN());
+ }
}
// --------------------------------------------------------------------------------------------
@@ -290,16 +300,16 @@ class Alpha_complex : public Simplex_tree<> {
// Will be re-used many times
Vector_of_CGAL_points pointVector;
// ### For i : d -> 0
- for (int decr_dim = dimension(); decr_dim >= 0; decr_dim--) {
+ for (int decr_dim = triangulation_->maximal_dimension(); decr_dim >= 0; decr_dim--) {
// ### Foreach Sigma of dim i
- for (auto f_simplex : skeleton_simplex_range(decr_dim)) {
- int f_simplex_dim = dimension(f_simplex);
+ for (Simplex_handle f_simplex : complex.skeleton_simplex_range(decr_dim)) {
+ int f_simplex_dim = complex.dimension(f_simplex);
if (decr_dim == f_simplex_dim) {
pointVector.clear();
#ifdef DEBUG_TRACES
std::cout << "Sigma of dim " << decr_dim << " is";
#endif // DEBUG_TRACES
- for (auto vertex : simplex_vertex_range(f_simplex)) {
+ for (auto vertex : complex.simplex_vertex_range(f_simplex)) {
pointVector.push_back(get_point(vertex));
#ifdef DEBUG_TRACES
std::cout << " " << vertex;
@@ -309,7 +319,7 @@ class Alpha_complex : public Simplex_tree<> {
std::cout << std::endl;
#endif // DEBUG_TRACES
// ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma)
- if (std::isnan(filtration(f_simplex))) {
+ if (std::isnan(complex.filtration(f_simplex))) {
Filtration_value alpha_complex_filtration = 0.0;
// No need to compute squared_radius on a single point - alpha is 0.0
if (f_simplex_dim > 0) {
@@ -318,12 +328,12 @@ class Alpha_complex : public Simplex_tree<> {
alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end());
}
- assign_filtration(f_simplex, alpha_complex_filtration);
+ complex.assign_filtration(f_simplex, alpha_complex_filtration);
#ifdef DEBUG_TRACES
- std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl;
+ std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << complex.filtration(f_simplex) << std::endl;
#endif // DEBUG_TRACES
}
- propagate_alpha_filtration(f_simplex, decr_dim);
+ propagate_alpha_filtration(complex, f_simplex, decr_dim);
}
}
}
@@ -331,36 +341,41 @@ class Alpha_complex : public Simplex_tree<> {
// --------------------------------------------------------------------------------------------
// As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension
- bool modified_filt = make_filtration_non_decreasing();
+ complex.make_filtration_non_decreasing();
// Remove all simplices that have a filtration value greater than max_alpha_square
- // Remark: prune_above_filtration does not require initialize_filtration to be done before.
- modified_filt |= prune_above_filtration(max_alpha_square);
- if (modified_filt) {
- initialize_filtration();
- }
+ complex.prune_above_filtration(max_alpha_square);
// --------------------------------------------------------------------------------------------
+ return true;
}
- template<typename Simplex_handle>
- void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) {
+ private:
+ template <typename SimplicialComplexForAlpha, typename Simplex_handle>
+ void propagate_alpha_filtration(SimplicialComplexForAlpha& complex, Simplex_handle f_simplex, int decr_dim) {
+ // From SimplicialComplexForAlpha type required to assign filtration values.
+ typedef typename SimplicialComplexForAlpha::Filtration_value Filtration_value;
+#ifdef DEBUG_TRACES
+ typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle;
+#endif // DEBUG_TRACES
+
// ### Foreach Tau face of Sigma
- for (auto f_boundary : boundary_simplex_range(f_simplex)) {
+ for (auto f_boundary : complex.boundary_simplex_range(f_simplex)) {
#ifdef DEBUG_TRACES
std::cout << " | --------------------------------------------------\n";
std::cout << " | Tau ";
- for (auto vertex : simplex_vertex_range(f_boundary)) {
+ for (auto vertex : complex.simplex_vertex_range(f_boundary)) {
std::cout << vertex << " ";
}
std::cout << "is a face of Sigma\n";
- std::cout << " | isnan(filtration(Tau)=" << std::isnan(filtration(f_boundary)) << std::endl;
+ std::cout << " | isnan(complex.filtration(Tau)=" << std::isnan(complex.filtration(f_boundary)) << std::endl;
#endif // DEBUG_TRACES
// ### If filt(Tau) is not NaN
- if (!std::isnan(filtration(f_boundary))) {
+ if (!std::isnan(complex.filtration(f_boundary))) {
// ### filt(Tau) = fmin(filt(Tau), filt(Sigma))
- Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex));
- assign_filtration(f_boundary, alpha_complex_filtration);
+ Filtration_value alpha_complex_filtration = fmin(complex.filtration(f_boundary),
+ complex.filtration(f_simplex));
+ complex.assign_filtration(f_boundary, alpha_complex_filtration);
#ifdef DEBUG_TRACES
- std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl;
+ std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << complex.filtration(f_boundary) << std::endl;
#endif // DEBUG_TRACES
// ### Else
} else {
@@ -372,12 +387,12 @@ class Alpha_complex : public Simplex_tree<> {
#ifdef DEBUG_TRACES
Vertex_handle vertexForGabriel = Vertex_handle();
#endif // DEBUG_TRACES
- for (auto vertex : simplex_vertex_range(f_boundary)) {
+ for (auto vertex : complex.simplex_vertex_range(f_boundary)) {
pointVector.push_back(get_point(vertex));
}
// Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function
Point_d point_for_gabriel;
- for (auto vertex : simplex_vertex_range(f_simplex)) {
+ for (auto vertex : complex.simplex_vertex_range(f_simplex)) {
point_for_gabriel = get_point(vertex);
if (std::find(pointVector.begin(), pointVector.end(), point_for_gabriel) == pointVector.end()) {
#ifdef DEBUG_TRACES
@@ -398,10 +413,10 @@ class Alpha_complex : public Simplex_tree<> {
// ### If Tau is not Gabriel of Sigma
if (false == is_gab) {
// ### filt(Tau) = filt(Sigma)
- Filtration_value alpha_complex_filtration = filtration(f_simplex);
- assign_filtration(f_boundary, alpha_complex_filtration);
+ Filtration_value alpha_complex_filtration = complex.filtration(f_simplex);
+ complex.assign_filtration(f_boundary, alpha_complex_filtration);
#ifdef DEBUG_TRACES
- std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl;
+ std::cout << " | filt(Tau) = filt(Sigma) = " << complex.filtration(f_boundary) << std::endl;
#endif // DEBUG_TRACES
}
}
diff --git a/include/gudhi/Alpha_complex.h~ b/include/gudhi/Alpha_complex.h~
deleted file mode 100644
index a1900cb9..00000000
--- a/include/gudhi/Alpha_complex.h~
+++ /dev/null
@@ -1,417 +0,0 @@
-/* This file is part of the Gudhi Library. The Gudhi library
- * (Geometric Understanding in Higher Dimensions) is a generic C++
- * library for computational topology.
- *
- * Author(s): Vincent Rouvreau
- *
- * Copyright (C) 2015 INRIA Saclay (France)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef ALPHA_COMPLEX_H_
-#define ALPHA_COMPLEX_H_
-
-// to construct a simplex_tree from Delaunay_triangulation
-#include <gudhi/graph_simplicial_complex.h>
-#include <gudhi/Simplex_tree.h>
-#include <gudhi/Debug_utils.h>
-// to construct Alpha_complex from a OFF file of points
-#include <gudhi/Points_off_io.h>
-
-#include <stdlib.h>
-#include <math.h> // isnan, fmax
-
-#include <CGAL/Delaunay_triangulation.h>
-#include <CGAL/Epick_d.h>
-#include <CGAL/Spatial_sort_traits_adapter_d.h>
-
-#include <iostream>
-#include <vector>
-#include <string>
-#include <limits> // NaN
-#include <map>
-#include <utility> // std::pair
-#include <stdexcept>
-#include <numeric> // for std::iota
-
-namespace Gudhi {
-
-namespace alphacomplex {
-
-/**
- * \class Alpha_complex Alpha_complex.h gudhi/Alpha_complex.h
- * \brief Alpha complex data structure.
- *
- * \ingroup alpha_complex
- *
- * \details
- * The data structure can be constructed from a CGAL Delaunay triangulation (for more informations on CGAL Delaunay
- * triangulation, please refer to the corresponding chapter in page http://doc.cgal.org/latest/Triangulation/) or from
- * an OFF file (cf. Points_off_reader).
- *
- * Please refer to \ref alpha_complex for examples.
- *
- * The complex is a template class requiring an Epick_d <a target="_blank"
- * href="http://doc.cgal.org/latest/Kernel_d/index.html#Chapter_dD_Geometry_Kernel">dD Geometry Kernel</a>
- * \cite cgal:s-gkd-15b from CGAL as template, default value is <a target="_blank"
- * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a>
- * < <a target="_blank" href="http://doc.cgal.org/latest/Kernel_23/classCGAL_1_1Dynamic__dimension__tag.html">
- * CGAL::Dynamic_dimension_tag </a> >
- *
- * \remark When Alpha_complex is constructed with an infinite value of alpha, the complex is a Delaunay complex.
- *
- */
-template<class Kernel = CGAL::Epick_d<CGAL::Dynamic_dimension_tag>>
-class Alpha_complex : public Simplex_tree<> {
- public:
- // Add an int in TDS to save point index in the structure
- typedef CGAL::Triangulation_data_structure<typename Kernel::Dimension,
- CGAL::Triangulation_vertex<Kernel, std::ptrdiff_t>,
- CGAL::Triangulation_full_cell<Kernel> > TDS;
- /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/
- typedef CGAL::Delaunay_triangulation<Kernel, TDS> Delaunay_triangulation;
-
- /** \brief A point in Euclidean space.*/
- typedef typename Kernel::Point_d Point_d;
- /** \brief Geometric traits class that provides the geometric types and predicates needed by Delaunay
- * triangulations.*/
- typedef Kernel Geom_traits;
-
- private:
- // From Simplex_tree
- // Type required to insert into a simplex_tree (with or without subfaces).
- typedef std::vector<Vertex_handle> Vector_vertex;
-
- // Simplex_result is the type returned from simplex_tree insert function.
- typedef typename std::pair<Simplex_handle, bool> Simplex_result;
-
- typedef typename Kernel::Compute_squared_radius_d Squared_Radius;
- typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel;
- typedef typename Kernel::Point_dimension_d Point_Dimension;
-
- // Type required to compute squared radius, or side of bounded sphere on a vector of points.
- typedef typename std::vector<Point_d> Vector_of_CGAL_points;
-
- // Vertex_iterator type from CGAL.
- typedef typename Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator;
-
- // size_type type from CGAL.
- typedef typename Delaunay_triangulation::size_type size_type;
-
- // Map type to switch from simplex tree vertex handle to CGAL vertex iterator.
- typedef typename std::map< Vertex_handle, CGAL_vertex_iterator > Vector_vertex_iterator;
-
- private:
- /** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator.
- * Vertex handles are inserted sequentially, starting at 0.*/
- Vector_vertex_iterator vertex_handle_to_iterator_;
- /** \brief Pointer on the CGAL Delaunay triangulation.*/
- Delaunay_triangulation* triangulation_;
- /** \brief Kernel for triangulation_ functions access.*/
- Kernel kernel_;
-
- public:
- /** \brief Alpha_complex constructor from an OFF file name.
- * Uses the Delaunay_triangulation_off_reader to construct the Delaunay triangulation required to initialize
- * the Alpha_complex.
- *
- * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous.
- *
- * @param[in] off_file_name OFF file [path and] name.
- * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$.
- */
- Alpha_complex(const std::string& off_file_name,
- Filtration_value max_alpha_square = std::numeric_limits<Filtration_value>::infinity())
- : triangulation_(nullptr) {
- Gudhi::Points_off_reader<Point_d> off_reader(off_file_name);
- if (!off_reader.is_valid()) {
- std::cerr << "Alpha_complex - Unable to read file " << off_file_name << "\n";
- exit(-1); // ----- >>
- }
-
- init_from_range(off_reader.get_point_cloud(), max_alpha_square);
- }
-
- /** \brief Alpha_complex constructor from a list of points.
- *
- * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous.
- *
- * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d
- * @param[in] max_alpha_square maximum for alpha square value. Default value is +\f$\infty\f$.
- *
- * The type InputPointRange must be a range for which std::begin and
- * std::end return input iterators on a Kernel::Point_d.
- *
- * @post Compare num_simplices with InputPointRange points number (not the same in case of duplicate points).
- */
- template<typename InputPointRange >
- Alpha_complex(const InputPointRange& points,
- Filtration_value max_alpha_square = std::numeric_limits<Filtration_value>::infinity())
- : triangulation_(nullptr) {
- init_from_range(points, max_alpha_square);
- }
-
- /** \brief Alpha_complex destructor.
- *
- * @warning Deletes the Delaunay triangulation.
- */
- ~Alpha_complex() {
- delete triangulation_;
- }
-
- // Forbid copy/move constructor/assignment operator
- Alpha_complex(const Alpha_complex& other) = delete;
- Alpha_complex& operator= (const Alpha_complex& other) = delete;
- Alpha_complex (Alpha_complex&& other) = delete;
- Alpha_complex& operator= (Alpha_complex&& other) = delete;
-
- /** \brief get_point returns the point corresponding to the vertex given as parameter.
- *
- * @param[in] vertex Vertex handle of the point to retrieve.
- * @return The point found.
- * @exception std::out_of_range In case vertex is not found (cf. std::vector::at).
- */
- Point_d get_point(Vertex_handle vertex) const {
- return vertex_handle_to_iterator_.at(vertex)->point();
- }
-
- private:
- template<typename InputPointRange >
- void init_from_range(const InputPointRange& points, Filtration_value max_alpha_square) {
- auto first = std::begin(points);
- auto last = std::end(points);
- if (first != last) {
- // point_dimension function initialization
- Point_Dimension point_dimension = kernel_.point_dimension_d_object();
-
- // Delaunay triangulation is point dimension.
- triangulation_ = new Delaunay_triangulation(point_dimension(*first));
-
- std::vector<Point_d> points(first, last);
-
- // Creates a vector {0, 1, ..., N-1}
- std::vector<std::ptrdiff_t> indices(boost::counting_iterator<std::ptrdiff_t>(0),
- boost::counting_iterator<std::ptrdiff_t>(points.size()));
-
- // Sort indices considering CGAL spatial sort
- typedef CGAL::Spatial_sort_traits_adapter_d<Kernel, Point_d*> Search_traits_d;
- spatial_sort(indices.begin(), indices.end(), Search_traits_d(&(points[0])));
-
- typename Delaunay_triangulation::Full_cell_handle hint;
- for (auto index : indices) {
- typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(points[index], hint);
- // Save index value as data to retrieve it after insertion
- pos->data() = index;
- hint = pos->full_cell();
- }
- init(max_alpha_square);
- }
- }
-
- /** \brief Initialize the Alpha_complex from the Delaunay triangulation.
- *
- * @param[in] max_alpha_square maximum for alpha square value.
- *
- * @warning Delaunay triangulation must be already constructed with at least one vertex and dimension must be more
- * than 0.
- *
- * Initialization can be launched once.
- */
- void init(Filtration_value max_alpha_square) {
- if (triangulation_ == nullptr) {
- std::cerr << "Alpha_complex init - Cannot init from a NULL triangulation\n";
- return; // ----- >>
- }
- if (triangulation_->number_of_vertices() < 1) {
- std::cerr << "Alpha_complex init - Cannot init from a triangulation without vertices\n";
- return; // ----- >>
- }
- if (triangulation_->maximal_dimension() < 1) {
- std::cerr << "Alpha_complex init - Cannot init from a zero-dimension triangulation\n";
- return; // ----- >>
- }
- if (num_vertices() > 0) {
- std::cerr << "Alpha_complex init - Cannot init twice\n";
- return; // ----- >>
- }
-
- set_dimension(triangulation_->maximal_dimension());
-
- // --------------------------------------------------------------------------------------------
- // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa
- // Loop on triangulation vertices list
- for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) {
- if (!triangulation_->is_infinite(*vit)) {
-#ifdef DEBUG_TRACES
- std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl;
-#endif // DEBUG_TRACES
- vertex_handle_to_iterator_.emplace(vit->data(), vit);
- }
- }
- // --------------------------------------------------------------------------------------------
-
- // --------------------------------------------------------------------------------------------
- // Simplex_tree construction from loop on triangulation finite full cells list
- for (auto cit = triangulation_->finite_full_cells_begin(); cit != triangulation_->finite_full_cells_end(); ++cit) {
- Vector_vertex vertexVector;
-#ifdef DEBUG_TRACES
- std::cout << "Simplex_tree insertion ";
-#endif // DEBUG_TRACES
- for (auto vit = cit->vertices_begin(); vit != cit->vertices_end(); ++vit) {
- if (*vit != nullptr) {
-#ifdef DEBUG_TRACES
- std::cout << " " << (*vit)->data();
-#endif // DEBUG_TRACES
- // Vector of vertex construction for simplex_tree structure
- vertexVector.push_back((*vit)->data());
- }
- }
-#ifdef DEBUG_TRACES
- std::cout << std::endl;
-#endif // DEBUG_TRACES
- // Insert each simplex and its subfaces in the simplex tree - filtration is NaN
- insert_simplex_and_subfaces(vertexVector, std::numeric_limits<double>::quiet_NaN());
- }
- // --------------------------------------------------------------------------------------------
-
- // --------------------------------------------------------------------------------------------
- // Will be re-used many times
- Vector_of_CGAL_points pointVector;
- // ### For i : d -> 0
- for (int decr_dim = dimension(); decr_dim >= 0; decr_dim--) {
- // ### Foreach Sigma of dim i
- for (auto f_simplex : skeleton_simplex_range(decr_dim)) {
- int f_simplex_dim = dimension(f_simplex);
- if (decr_dim == f_simplex_dim) {
- pointVector.clear();
-#ifdef DEBUG_TRACES
- std::cout << "Sigma of dim " << decr_dim << " is";
-#endif // DEBUG_TRACES
- for (auto vertex : simplex_vertex_range(f_simplex)) {
- pointVector.push_back(get_point(vertex));
-#ifdef DEBUG_TRACES
- std::cout << " " << vertex;
-#endif // DEBUG_TRACES
- }
-#ifdef DEBUG_TRACES
- std::cout << std::endl;
-#endif // DEBUG_TRACES
- // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma)
- if (isnan(filtration(f_simplex))) {
- Filtration_value alpha_complex_filtration = 0.0;
- // No need to compute squared_radius on a single point - alpha is 0.0
- if (f_simplex_dim > 0) {
- // squared_radius function initialization
- Squared_Radius squared_radius = kernel_.compute_squared_radius_d_object();
-
- alpha_complex_filtration = squared_radius(pointVector.begin(), pointVector.end());
- }
- assign_filtration(f_simplex, alpha_complex_filtration);
-#ifdef DEBUG_TRACES
- std::cout << "filt(Sigma) is NaN : filt(Sigma) =" << filtration(f_simplex) << std::endl;
-#endif // DEBUG_TRACES
- }
- propagate_alpha_filtration(f_simplex, decr_dim);
- }
- }
- }
- // --------------------------------------------------------------------------------------------
-
- // --------------------------------------------------------------------------------------------
- // As Alpha value is an approximation, we have to make filtration non decreasing while increasing the dimension
- bool modified_filt = make_filtration_non_decreasing();
- // Remove all simplices that have a filtration value greater than max_alpha_square
- // Remark: prune_above_filtration does not require initialize_filtration to be done before.
- modified_filt |= prune_above_filtration(max_alpha_square);
- if (modified_filt) {
- initialize_filtration();
- }
- // --------------------------------------------------------------------------------------------
- }
-
- template<typename Simplex_handle>
- void propagate_alpha_filtration(Simplex_handle f_simplex, int decr_dim) {
- // ### Foreach Tau face of Sigma
- for (auto f_boundary : boundary_simplex_range(f_simplex)) {
-#ifdef DEBUG_TRACES
- std::cout << " | --------------------------------------------------\n";
- std::cout << " | Tau ";
- for (auto vertex : simplex_vertex_range(f_boundary)) {
- std::cout << vertex << " ";
- }
- std::cout << "is a face of Sigma\n";
- std::cout << " | isnan(filtration(Tau)=" << isnan(filtration(f_boundary)) << std::endl;
-#endif // DEBUG_TRACES
- // ### If filt(Tau) is not NaN
- if (!isnan(filtration(f_boundary))) {
- // ### filt(Tau) = fmin(filt(Tau), filt(Sigma))
- Filtration_value alpha_complex_filtration = fmin(filtration(f_boundary), filtration(f_simplex));
- assign_filtration(f_boundary, alpha_complex_filtration);
-#ifdef DEBUG_TRACES
- std::cout << " | filt(Tau) = fmin(filt(Tau), filt(Sigma)) = " << filtration(f_boundary) << std::endl;
-#endif // DEBUG_TRACES
- // ### Else
- } else {
- // No need to compute is_gabriel for dimension <= 2
- // i.e. : Sigma = (3,1) => Tau = 1
- if (decr_dim > 1) {
- // insert the Tau points in a vector for is_gabriel function
- Vector_of_CGAL_points pointVector;
-#ifdef DEBUG_TRACES
- Vertex_handle vertexForGabriel = Vertex_handle();
-#endif // DEBUG_TRACES
- for (auto vertex : simplex_vertex_range(f_boundary)) {
- pointVector.push_back(get_point(vertex));
- }
- // Retrieve the Sigma point that is not part of Tau - parameter for is_gabriel function
- Point_d point_for_gabriel;
- for (auto vertex : simplex_vertex_range(f_simplex)) {
- point_for_gabriel = get_point(vertex);
- if (std::find(pointVector.begin(), pointVector.end(), point_for_gabriel) == pointVector.end()) {
-#ifdef DEBUG_TRACES
- // vertex is not found in Tau
- vertexForGabriel = vertex;
-#endif // DEBUG_TRACES
- // No need to continue loop
- break;
- }
- }
- // is_gabriel function initialization
- Is_Gabriel is_gabriel = kernel_.side_of_bounded_sphere_d_object();
- bool is_gab = is_gabriel(pointVector.begin(), pointVector.end(), point_for_gabriel)
- != CGAL::ON_BOUNDED_SIDE;
-#ifdef DEBUG_TRACES
- std::cout << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << vertexForGabriel << std::endl;
-#endif // DEBUG_TRACES
- // ### If Tau is not Gabriel of Sigma
- if (false == is_gab) {
- // ### filt(Tau) = filt(Sigma)
- Filtration_value alpha_complex_filtration = filtration(f_simplex);
- assign_filtration(f_boundary, alpha_complex_filtration);
-#ifdef DEBUG_TRACES
- std::cout << " | filt(Tau) = filt(Sigma) = " << filtration(f_boundary) << std::endl;
-#endif // DEBUG_TRACES
- }
- }
- }
- }
- }
-};
-
-} // namespace alphacomplex
-
-} // namespace Gudhi
-
-#endif // ALPHA_COMPLEX_H_
diff --git a/include/gudhi/Bottleneck.h b/include/gudhi/Bottleneck.h
new file mode 100644
index 00000000..b90a0ee0
--- /dev/null
+++ b/include/gudhi/Bottleneck.h
@@ -0,0 +1,115 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author: Francois Godi
+ *
+ * Copyright (C) 2015 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BOTTLENECK_H_
+#define BOTTLENECK_H_
+
+#include <gudhi/Graph_matching.h>
+
+#include <vector>
+#include <algorithm> // for max
+#include <limits> // for numeric_limits
+
+#include <cmath>
+
+namespace Gudhi {
+
+namespace persistence_diagram {
+
+double bottleneck_distance_approx(Persistence_graph& g, double e) {
+ double b_lower_bound = 0.;
+ double b_upper_bound = g.diameter_bound();
+ const double alpha = std::pow(g.size(), 1. / 5.);
+ Graph_matching m(g);
+ Graph_matching biggest_unperfect(g);
+ while (b_upper_bound - b_lower_bound > 2 * e) {
+ double step = b_lower_bound + (b_upper_bound - b_lower_bound) / alpha;
+ if (step <= b_lower_bound || step >= b_upper_bound) // Avoid precision problem
+ break;
+ m.set_r(step);
+ while (m.multi_augment()) {}; // compute a maximum matching (in the graph corresponding to the current r)
+ if (m.perfect()) {
+ m = biggest_unperfect;
+ b_upper_bound = step;
+ } else {
+ biggest_unperfect = m;
+ b_lower_bound = step;
+ }
+ }
+ return (b_lower_bound + b_upper_bound) / 2.;
+}
+
+double bottleneck_distance_exact(Persistence_graph& g) {
+ std::vector<double> sd = g.sorted_distances();
+ long lower_bound_i = 0;
+ long upper_bound_i = sd.size() - 1;
+ const double alpha = std::pow(g.size(), 1. / 5.);
+ Graph_matching m(g);
+ Graph_matching biggest_unperfect(g);
+ while (lower_bound_i != upper_bound_i) {
+ long step = lower_bound_i + static_cast<long> ((upper_bound_i - lower_bound_i - 1) / alpha);
+ m.set_r(sd.at(step));
+ while (m.multi_augment()) {}; // compute a maximum matching (in the graph corresponding to the current r)
+ if (m.perfect()) {
+ m = biggest_unperfect;
+ upper_bound_i = step;
+ } else {
+ biggest_unperfect = m;
+ lower_bound_i = step + 1;
+ }
+ }
+ return sd.at(lower_bound_i);
+}
+
+/** \brief Function to compute the Bottleneck distance between two persistence diagrams.
+ *
+ * \tparam Persistence_diagram1,Persistence_diagram2
+ * models of the concept `PersistenceDiagram`.
+ * \param[in] e
+ * \parblock
+ * If `e` is 0, this uses an expensive algorithm to compute the exact distance.
+ *
+ * If `e` is not 0, it asks for an additive `e`-approximation, and currently
+ * also allows a small multiplicative error (the last 2 or 3 bits of the
+ * mantissa may be wrong). This version of the algorithm takes advantage of the
+ * limited precision of `double` and is usually a lot faster to compute,
+ * whatever the value of `e`.
+ *
+ * Thus, by default, `e` is the smallest positive double.
+ * \endparblock
+ *
+ * \ingroup bottleneck_distance
+ */
+template<typename Persistence_diagram1, typename Persistence_diagram2>
+double bottleneck_distance(const Persistence_diagram1 &diag1, const Persistence_diagram2 &diag2,
+ double e = std::numeric_limits<double>::min()) {
+ Persistence_graph g(diag1, diag2, e);
+ if (g.bottleneck_alive() == std::numeric_limits<double>::infinity())
+ return std::numeric_limits<double>::infinity();
+ return std::max(g.bottleneck_alive(), e == 0. ? bottleneck_distance_exact(g) : bottleneck_distance_approx(g, e));
+}
+
+} // namespace persistence_diagram
+
+} // namespace Gudhi
+
+#endif // BOTTLENECK_H_
diff --git a/include/gudhi/Clock.h b/include/gudhi/Clock.h
index 04c6ffb9..77f196ca 100644
--- a/include/gudhi/Clock.h
+++ b/include/gudhi/Clock.h
@@ -27,47 +27,55 @@
#include <string>
+namespace Gudhi {
+
class Clock {
public:
- Clock() : end_called(false) {
- startTime = boost::posix_time::microsec_clock::local_time();
- }
-
- Clock(const std::string& msg_) {
- end_called = false;
- begin();
- msg = msg_;
- }
+ // Construct and start the timer
+ Clock(const std::string& msg_ = std::string())
+ : startTime(boost::posix_time::microsec_clock::local_time()),
+ end_called(false),
+ msg(msg_) { }
+ // Restart the timer
void begin() const {
end_called = false;
startTime = boost::posix_time::microsec_clock::local_time();
}
+ // Stop the timer
void end() const {
end_called = true;
endTime = boost::posix_time::microsec_clock::local_time();
}
+ std::string message() const {
+ return msg;
+ }
+
+ // Print current value to std::cout
void print() const {
std::cout << *this << std::endl;
}
friend std::ostream& operator<<(std::ostream& stream, const Clock& clock) {
- if (!clock.end_called)
- clock.end();
+ if (!clock.msg.empty())
+ stream << clock.msg << ": ";
- if (!clock.end_called) {
- stream << "end not called";
- } else {
- stream << clock.msg << ":" << clock.num_seconds() << "s";
- }
+ stream << clock.num_seconds() << "s";
return stream;
}
+ // Get the number of seconds between the timer start and:
+ // - the last call of end() if it was called
+ // - or now otherwise. In this case, the timer is not stopped.
double num_seconds() const {
- if (!end_called) return -1;
- return (endTime - startTime).total_milliseconds() / 1000.;
+ if (!end_called) {
+ auto end = boost::posix_time::microsec_clock::local_time();
+ return (end - startTime).total_milliseconds() / 1000.;
+ } else {
+ return (endTime - startTime).total_milliseconds() / 1000.;
+ }
}
private:
@@ -76,4 +84,6 @@ class Clock {
std::string msg;
};
-#endif // CLOCK_H_
+} // namespace Gudhi
+
+#endif // CLOCK_H_
diff --git a/include/gudhi/Debug_utils.h b/include/gudhi/Debug_utils.h
index 7573a9db..8ed3b7b3 100644
--- a/include/gudhi/Debug_utils.h
+++ b/include/gudhi/Debug_utils.h
@@ -33,8 +33,10 @@
// Could assert in release mode, but cmake sets NDEBUG (for "NO DEBUG") in this mode, means assert does nothing.
#ifdef GUDHI_DEBUG
#define GUDHI_CHECK(expression, excpt) if ((expression) == 0) throw excpt
+ #define GUDHI_CHECK_code(CODE) CODE
#else
#define GUDHI_CHECK(expression, excpt) (void) 0
+ #define GUDHI_CHECK_code(CODE)
#endif
#define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)" << std::endl
diff --git a/include/gudhi/Edge_contraction.h b/include/gudhi/Edge_contraction.h
index 5af13c3e..61f2d945 100644
--- a/include/gudhi/Edge_contraction.h
+++ b/include/gudhi/Edge_contraction.h
@@ -41,7 +41,7 @@ namespace contraction {
\author David Salinas
-\section Introduction
+\section edgecontractionintroduction Introduction
The purpose of this package is to offer a user-friendly interface for edge contraction simplification of huge simplicial complexes.
It uses the \ref skbl data-structure whose size remains small during simplification
diff --git a/include/gudhi/Euclidean_strong_witness_complex.h b/include/gudhi/Euclidean_strong_witness_complex.h
new file mode 100644
index 00000000..fb669ef8
--- /dev/null
+++ b/include/gudhi/Euclidean_strong_witness_complex.h
@@ -0,0 +1,104 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2015 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EUCLIDEAN_STRONG_WITNESS_COMPLEX_H_
+#define EUCLIDEAN_STRONG_WITNESS_COMPLEX_H_
+
+#include <gudhi/Strong_witness_complex.h>
+#include <gudhi/Active_witness/Active_witness.h>
+#include <gudhi/Kd_tree_search.h>
+
+#include <utility>
+#include <vector>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+/**
+ * \private
+ * \class Euclidean_strong_witness_complex
+ * \brief Constructs strong witness complex for given sets of witnesses and landmarks in Euclidean space.
+ * \ingroup witness_complex
+ *
+ * \tparam Kernel_ requires a <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class.
+ */
+template< class Kernel_ >
+class Euclidean_strong_witness_complex
+ : public Strong_witness_complex<std::vector<typename Gudhi::spatial_searching::Kd_tree_search<Kernel_,
+ std::vector<typename Kernel_::Point_d>>::INS_range>> {
+ private:
+ typedef Kernel_ K;
+ typedef typename K::Point_d Point_d;
+ typedef std::vector<Point_d> Point_range;
+ typedef Gudhi::spatial_searching::Kd_tree_search<Kernel_, Point_range> Kd_tree;
+ typedef typename Kd_tree::INS_range Nearest_landmark_range;
+ typedef typename std::vector<Nearest_landmark_range> Nearest_landmark_table;
+
+ typedef typename Nearest_landmark_range::Point_with_transformed_distance Id_distance_pair;
+ typedef typename Id_distance_pair::first_type Landmark_id;
+ typedef Landmark_id Vertex_handle;
+
+ private:
+ Point_range landmarks_;
+ Kd_tree landmark_tree_;
+ using Strong_witness_complex<Nearest_landmark_table>::nearest_landmark_table_;
+
+ public:
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /* @name Constructor
+ */
+
+ //@{
+
+ /**
+ * \brief Initializes member variables before constructing simplicial complex.
+ * \details Records landmarks from the range 'landmarks' into a
+ * table internally, as well as witnesses from the range 'witnesses'.
+ * Both ranges should have value_type Kernel_::Point_d.
+ */
+ template< typename LandmarkRange,
+ typename WitnessRange >
+ Euclidean_strong_witness_complex(const LandmarkRange & landmarks,
+ const WitnessRange & witnesses)
+ : landmarks_(std::begin(landmarks), std::end(landmarks)), landmark_tree_(landmarks_) {
+ nearest_landmark_table_.reserve(boost::size(witnesses));
+ for (auto w : witnesses)
+ nearest_landmark_table_.push_back(landmark_tree_.query_incremental_nearest_neighbors(w));
+ }
+
+ /** \brief Returns the point corresponding to the given vertex.
+ */
+ template <typename Vertex_handle>
+ Point_d get_point(Vertex_handle vertex) const {
+ return landmarks_[vertex];
+ }
+
+ //@}
+};
+
+} // namespace witness_complex
+
+} // namespace Gudhi
+
+#endif // EUCLIDEAN_STRONG_WITNESS_COMPLEX_H_
diff --git a/include/gudhi/Euclidean_witness_complex.h b/include/gudhi/Euclidean_witness_complex.h
new file mode 100644
index 00000000..6afe9a5d
--- /dev/null
+++ b/include/gudhi/Euclidean_witness_complex.h
@@ -0,0 +1,106 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2015 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EUCLIDEAN_WITNESS_COMPLEX_H_
+#define EUCLIDEAN_WITNESS_COMPLEX_H_
+
+#include <gudhi/Witness_complex.h>
+#include <gudhi/Active_witness/Active_witness.h>
+#include <gudhi/Kd_tree_search.h>
+
+#include <utility>
+#include <vector>
+#include <list>
+#include <limits>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+/**
+ * \private
+ * \class Euclidean_witness_complex
+ * \brief Constructs (weak) witness complex for given sets of witnesses and landmarks in Euclidean space.
+ * \ingroup witness_complex
+ *
+ * \tparam Kernel_ requires a <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class.
+ */
+template< class Kernel_ >
+class Euclidean_witness_complex
+ : public Witness_complex<std::vector<typename Gudhi::spatial_searching::Kd_tree_search<Kernel_,
+ std::vector<typename Kernel_::Point_d>>::INS_range>> {
+ private:
+ typedef Kernel_ K;
+ typedef typename K::Point_d Point_d;
+ typedef std::vector<Point_d> Point_range;
+ typedef Gudhi::spatial_searching::Kd_tree_search<Kernel_, Point_range> Kd_tree;
+ typedef typename Kd_tree::INS_range Nearest_landmark_range;
+ typedef typename std::vector<Nearest_landmark_range> Nearest_landmark_table;
+
+ typedef typename Nearest_landmark_range::Point_with_transformed_distance Id_distance_pair;
+ typedef typename Id_distance_pair::first_type Landmark_id;
+ typedef Landmark_id Vertex_handle;
+
+ private:
+ Point_range landmarks_;
+ Kd_tree landmark_tree_;
+ using Witness_complex<Nearest_landmark_table>::nearest_landmark_table_;
+
+ public:
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /* @name Constructor
+ */
+
+ //@{
+
+ /**
+ * \brief Initializes member variables before constructing simplicial complex.
+ * \details Records landmarks from the range 'landmarks' into a
+ * table internally, as well as witnesses from the range 'witnesses'.
+ * Both ranges should have value_type Kernel_::Point_d.
+ */
+ template< typename LandmarkRange,
+ typename WitnessRange >
+ Euclidean_witness_complex(const LandmarkRange & landmarks,
+ const WitnessRange & witnesses)
+ : landmarks_(std::begin(landmarks), std::end(landmarks)), landmark_tree_(landmarks) {
+ nearest_landmark_table_.reserve(boost::size(witnesses));
+ for (auto w : witnesses)
+ nearest_landmark_table_.push_back(landmark_tree_.query_incremental_nearest_neighbors(w));
+ }
+
+ /** \brief Returns the point corresponding to the given vertex.
+ * @param[in] vertex Vertex handle of the point to retrieve.
+ */
+ Point_d get_point(Vertex_handle vertex) const {
+ return landmarks_[vertex];
+ }
+
+ //@}
+};
+
+} // namespace witness_complex
+
+} // namespace Gudhi
+
+#endif // EUCLIDEAN_WITNESS_COMPLEX_H_
diff --git a/include/gudhi/Graph_matching.h b/include/gudhi/Graph_matching.h
new file mode 100644
index 00000000..f51e22e9
--- /dev/null
+++ b/include/gudhi/Graph_matching.h
@@ -0,0 +1,174 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author: Francois Godi
+ *
+ * Copyright (C) 2015 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRAPH_MATCHING_H_
+#define GRAPH_MATCHING_H_
+
+#include <gudhi/Neighbors_finder.h>
+
+#include <vector>
+#include <unordered_set>
+#include <algorithm>
+
+namespace Gudhi {
+
+namespace persistence_diagram {
+
+/** \internal \brief Structure representing a graph matching. The graph is a Persistence_diagrams_graph.
+ *
+ * \ingroup bottleneck_distance
+ */
+class Graph_matching {
+ public:
+ /** \internal \brief Constructor constructing an empty matching. */
+ explicit Graph_matching(Persistence_graph &g);
+ /** \internal \brief Is the matching perfect ? */
+ bool perfect() const;
+ /** \internal \brief Augments the matching with a maximal set of edge-disjoint shortest augmenting paths. */
+ bool multi_augment();
+ /** \internal \brief Sets the maximum length of the edges allowed to be added in the matching, 0 initially. */
+ void set_r(double r);
+
+ private:
+ Persistence_graph* gp;
+ double r;
+ /** \internal \brief Given a point from V, provides its matched point in U, null_point_index() if there isn't. */
+ std::vector<int> v_to_u;
+ /** \internal \brief All the unmatched points in U. */
+ std::unordered_set<int> unmatched_in_u;
+
+ /** \internal \brief Provides a Layered_neighbors_finder dividing the graph in layers. Basically a BFS. */
+ Layered_neighbors_finder layering() const;
+ /** \internal \brief Augments the matching with a simple path no longer than max_depth. Basically a DFS. */
+ bool augment(Layered_neighbors_finder & layered_nf, int u_start_index, int max_depth);
+ /** \internal \brief Update the matching with the simple augmenting path given as parameter. */
+ void update(std::vector<int> & path);
+};
+
+inline Graph_matching::Graph_matching(Persistence_graph& g)
+ : gp(&g), r(0.), v_to_u(g.size(), null_point_index()), unmatched_in_u(g.size()) {
+ for (int u_point_index = 0; u_point_index < g.size(); ++u_point_index)
+ unmatched_in_u.insert(u_point_index);
+}
+
+inline bool Graph_matching::perfect() const {
+ return unmatched_in_u.empty();
+}
+
+inline bool Graph_matching::multi_augment() {
+ if (perfect())
+ return false;
+ Layered_neighbors_finder layered_nf(layering());
+ int max_depth = layered_nf.vlayers_number()*2 - 1;
+ double rn = sqrt(gp->size());
+ // verification of a necessary criterion in order to shortcut if possible
+ if (max_depth < 0 || (unmatched_in_u.size() > rn && max_depth >= rn))
+ return false;
+ bool successful = false;
+ std::vector<int> tries(unmatched_in_u.cbegin(), unmatched_in_u.cend());
+ for (auto it = tries.cbegin(); it != tries.cend(); it++)
+ // 'augment' has side-effects which have to be always executed, don't change order
+ successful = augment(layered_nf, *it, max_depth) || successful;
+ return successful;
+}
+
+inline void Graph_matching::set_r(double r) {
+ this->r = r;
+}
+
+inline bool Graph_matching::augment(Layered_neighbors_finder & layered_nf, int u_start_index, int max_depth) {
+ // V vertices have at most one successor, thus when we backtrack from U we can directly pop_back 2 vertices.
+ std::vector<int> path;
+ path.emplace_back(u_start_index);
+ do {
+ if (static_cast<int> (path.size()) > max_depth) {
+ path.pop_back();
+ path.pop_back();
+ }
+ if (path.empty())
+ return false;
+ path.emplace_back(layered_nf.pull_near(path.back(), static_cast<int> (path.size()) / 2));
+ while (path.back() == null_point_index()) {
+ path.pop_back();
+ path.pop_back();
+ if (path.empty())
+ return false;
+ path.pop_back();
+ path.emplace_back(layered_nf.pull_near(path.back(), path.size() / 2));
+ }
+ path.emplace_back(v_to_u.at(path.back()));
+ } while (path.back() != null_point_index());
+ // if v_to_u.at(path.back()) has no successor, path.back() is an exposed vertex
+ path.pop_back();
+ update(path);
+ return true;
+}
+
+inline Layered_neighbors_finder Graph_matching::layering() const {
+ std::vector<int> u_vertices(unmatched_in_u.cbegin(), unmatched_in_u.cend());
+ std::vector<int> v_vertices;
+ Neighbors_finder nf(*gp, r);
+ for (int v_point_index = 0; v_point_index < gp->size(); ++v_point_index)
+ nf.add(v_point_index);
+ Layered_neighbors_finder layered_nf(*gp, r);
+ for (int layer = 0; !u_vertices.empty(); layer++) {
+ // one layer is one step in the BFS
+ for (auto it1 = u_vertices.cbegin(); it1 != u_vertices.cend(); ++it1) {
+ std::vector<int> u_succ(nf.pull_all_near(*it1));
+ for (auto it2 = u_succ.begin(); it2 != u_succ.end(); ++it2) {
+ layered_nf.add(*it2, layer);
+ v_vertices.emplace_back(*it2);
+ }
+ }
+ // When the above for finishes, we have progress of one half-step (from U to V) in the BFS
+ u_vertices.clear();
+ bool end = false;
+ for (auto it = v_vertices.cbegin(); it != v_vertices.cend(); it++)
+ if (v_to_u.at(*it) == null_point_index())
+ // we stop when a nearest exposed V vertex (from U exposed vertices) has been found
+ end = true;
+ else
+ u_vertices.emplace_back(v_to_u.at(*it));
+ // When the above for finishes, we have progress of one half-step (from V to U) in the BFS
+ if (end)
+ return layered_nf;
+ v_vertices.clear();
+ }
+ return layered_nf;
+}
+
+inline void Graph_matching::update(std::vector<int>& path) {
+ // Must return 1.
+ unmatched_in_u.erase(path.front());
+ for (auto it = path.cbegin(); it != path.cend(); ++it) {
+ // Be careful, the iterator is incremented twice each time
+ int tmp = *it;
+ v_to_u[*(++it)] = tmp;
+ }
+}
+
+
+} // namespace persistence_diagram
+
+} // namespace Gudhi
+
+#endif // GRAPH_MATCHING_H_
diff --git a/include/gudhi/Internal_point.h b/include/gudhi/Internal_point.h
new file mode 100644
index 00000000..0b2d26fe
--- /dev/null
+++ b/include/gudhi/Internal_point.h
@@ -0,0 +1,91 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author: Francois Godi
+ *
+ * Copyright (C) 2015 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INTERNAL_POINT_H_
+#define INTERNAL_POINT_H_
+
+namespace Gudhi {
+
+namespace persistence_diagram {
+
+/** \internal \brief Returns the used index for encoding none of the points */
+int null_point_index();
+
+/** \internal \typedef \brief Internal_point is the internal points representation, indexes used outside. */
+struct Internal_point {
+ double vec[2];
+ int point_index;
+
+ Internal_point() { }
+
+ Internal_point(double x, double y, int p_i) {
+ vec[0] = x;
+ vec[1] = y;
+ point_index = p_i;
+ }
+
+ double x() const {
+ return vec[ 0 ];
+ }
+
+ double y() const {
+ return vec[ 1 ];
+ }
+
+ double& x() {
+ return vec[ 0 ];
+ }
+
+ double& y() {
+ return vec[ 1 ];
+ }
+
+ bool operator==(const Internal_point& p) const {
+ return point_index == p.point_index;
+ }
+
+ bool operator!=(const Internal_point& p) const {
+ return !(*this == p);
+ }
+};
+
+inline int null_point_index() {
+ return -1;
+}
+
+struct Construct_coord_iterator {
+ typedef const double* result_type;
+
+ const double* operator()(const Internal_point& p) const {
+ return p.vec;
+ }
+
+ const double* operator()(const Internal_point& p, int) const {
+ return p.vec + 2;
+ }
+};
+
+} // namespace persistence_diagram
+
+} // namespace Gudhi
+
+#endif // INTERNAL_POINT_H_
diff --git a/include/gudhi/Kd_tree_search.h b/include/gudhi/Kd_tree_search.h
new file mode 100644
index 00000000..6728d56e
--- /dev/null
+++ b/include/gudhi/Kd_tree_search.h
@@ -0,0 +1,264 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KD_TREE_SEARCH_H_
+#define KD_TREE_SEARCH_H_
+
+#include <CGAL/Orthogonal_k_neighbor_search.h>
+#include <CGAL/Orthogonal_incremental_neighbor_search.h>
+#include <CGAL/Search_traits.h>
+#include <CGAL/Search_traits_adapter.h>
+#include <CGAL/property_map.h>
+
+#include <boost/property_map/property_map.hpp>
+#include <boost/iterator/counting_iterator.hpp>
+
+#include <cstddef>
+#include <vector>
+
+namespace Gudhi {
+namespace spatial_searching {
+
+
+ /**
+ * \class Kd_tree_search Kd_tree_search.h gudhi/Kd_tree_search.h
+ * \brief Spatial tree data structure to perform (approximate) nearest and farthest neighbor search.
+ *
+ * \ingroup spatial_searching
+ *
+ * \details
+ * The class Kd_tree_search is a tree-based data structure, based on
+ * <a target="_blank" href="http://doc.cgal.org/latest/Spatial_searching/index.html">CGAL dD spatial searching data structures</a>.
+ * It provides a simplified API to perform (approximate) nearest and farthest neighbor searches. Contrary to CGAL default behavior, the tree
+ * does not store the points themselves, but stores indices.
+ *
+ * There are two types of queries: the <i>k-nearest or k-farthest neighbor query</i>, where <i>k</i> is fixed and the <i>k</i> nearest
+ * or farthest points are computed right away,
+ * and the <i>incremental nearest or farthest neighbor query</i>, where no number of neighbors is provided during the call, as the
+ * neighbors will be computed incrementally when the iterator on the range is incremented.
+ *
+ * \tparam Search_traits must be a model of the <a target="_blank"
+ * href="http://doc.cgal.org/latest/Spatial_searching/classSearchTraits.html">SearchTraits</a>
+ * concept, such as the <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class, which
+ * can be static if you know the ambiant dimension at compile-time, or dynamic if you don't.
+ * \tparam Point_range is the type of the range that provides the points.
+ * It must be a range whose iterator type is a `RandomAccessIterator`.
+ */
+template <typename Search_traits, typename Point_range>
+class Kd_tree_search {
+ typedef boost::iterator_property_map<
+ typename Point_range::const_iterator,
+ CGAL::Identity_property_map<std::ptrdiff_t> > Point_property_map;
+
+ public:
+ /// The Traits.
+ typedef Search_traits Traits;
+ /// Number type used for distances.
+ typedef typename Traits::FT FT;
+ /// The point type.
+ typedef typename Point_range::value_type Point;
+
+ typedef CGAL::Search_traits<
+ FT, Point,
+ typename Traits::Cartesian_const_iterator_d,
+ typename Traits::Construct_cartesian_const_iterator_d> Traits_base;
+
+ typedef CGAL::Search_traits_adapter<
+ std::ptrdiff_t,
+ Point_property_map,
+ Traits_base> STraits;
+
+ typedef CGAL::Orthogonal_k_neighbor_search<STraits> K_neighbor_search;
+ typedef typename K_neighbor_search::Tree Tree;
+ typedef typename K_neighbor_search::Distance Distance;
+ /// \brief The range returned by a k-nearest or k-farthest neighbor search.
+ /// Its value type is `std::pair<std::size_t, FT>` where `first` is the index
+ /// of a point P and `second` is the squared distance between P and the query point.
+ typedef K_neighbor_search KNS_range;
+
+ typedef CGAL::Orthogonal_incremental_neighbor_search<
+ STraits, Distance, CGAL::Sliding_midpoint<STraits>, Tree>
+ Incremental_neighbor_search;
+ /// \brief The range returned by an incremental nearest or farthest neighbor search.
+ /// Its value type is `std::pair<std::size_t, FT>` where `first` is the index
+ /// of a point P and `second` is the squared distance between P and the query point.
+ typedef Incremental_neighbor_search INS_range;
+
+ /// \brief Constructor
+ /// @param[in] points Const reference to the point range. This range
+ /// is not copied, so it should not be destroyed or modified afterwards.
+ Kd_tree_search(Point_range const& points)
+ : m_points(points),
+ m_tree(boost::counting_iterator<std::ptrdiff_t>(0),
+ boost::counting_iterator<std::ptrdiff_t>(points.size()),
+ typename Tree::Splitter(),
+ STraits(std::begin(points))) {
+ // Build the tree now (we don't want to wait for the first query)
+ m_tree.build();
+ }
+
+ /// \brief Constructor
+ /// @param[in] points Const reference to the point range. This range
+ /// is not copied, so it should not be destroyed or modified afterwards.
+ /// @param[in] only_these_points Specifies the indices of the points that
+ /// should be actually inserted into the tree. The other points are ignored.
+ template <typename Point_indices_range>
+ Kd_tree_search(
+ Point_range const& points,
+ Point_indices_range const& only_these_points)
+ : m_points(points),
+ m_tree(
+ only_these_points.begin(), only_these_points.end(),
+ typename Tree::Splitter(),
+ STraits(std::begin(points))) {
+ // Build the tree now (we don't want to wait for the first query)
+ m_tree.build();
+ }
+
+ /// \brief Constructor
+ /// @param[in] points Const reference to the point range. This range
+ /// is not copied, so it should not be destroyed or modified afterwards.
+ /// @param[in] begin_idx, past_the_end_idx Define the subset of the points that
+ /// should be actually inserted into the tree. The other points are ignored.
+ Kd_tree_search(
+ Point_range const& points,
+ std::size_t begin_idx, std::size_t past_the_end_idx)
+ : m_points(points),
+ m_tree(
+ boost::counting_iterator<std::ptrdiff_t>(begin_idx),
+ boost::counting_iterator<std::ptrdiff_t>(past_the_end_idx),
+ typename Tree::Splitter(),
+ STraits(std::begin(points))) {
+ // Build the tree now (we don't want to wait for the first query)
+ m_tree.build();
+ }
+
+ // Be careful, this function invalidates the tree,
+ // which will be recomputed at the next query
+ void insert(std::ptrdiff_t point_idx) {
+ m_tree.insert(point_idx);
+ }
+
+ /// \brief Search for the k-nearest neighbors from a query point.
+ /// @param[in] p The query point.
+ /// @param[in] k Number of nearest points to search.
+ /// @param[in] sorted Indicates if the computed sequence of k-nearest neighbors needs to be sorted.
+ /// @param[in] eps Approximation factor.
+ /// @return A range containing the k-nearest neighbors.
+ KNS_range query_k_nearest_neighbors(const
+ Point &p,
+ unsigned int k,
+ bool sorted = true,
+ FT eps = FT(0)) const {
+ // Initialize the search structure, and search all N points
+ // Note that we need to pass the Distance explicitly since it needs to
+ // know the property map
+ K_neighbor_search search(
+ m_tree,
+ p,
+ k,
+ eps,
+ true,
+ CGAL::Distance_adapter<std::ptrdiff_t, Point_property_map, CGAL::Euclidean_distance<Traits_base> >(
+ std::begin(m_points)), sorted);
+
+ return search;
+ }
+
+ /// \brief Search incrementally for the nearest neighbors from a query point.
+ /// @param[in] p The query point.
+ /// @param[in] eps Approximation factor.
+ /// @return A range containing the neighbors sorted by their distance to p.
+ /// All the neighbors are not computed by this function, but they will be
+ /// computed incrementally when the iterator on the range is incremented.
+ INS_range query_incremental_nearest_neighbors(const Point &p, FT eps = FT(0)) const {
+ // Initialize the search structure, and search all N points
+ // Note that we need to pass the Distance explicitly since it needs to
+ // know the property map
+ Incremental_neighbor_search search(
+ m_tree,
+ p,
+ eps,
+ true,
+ CGAL::Distance_adapter<std::ptrdiff_t, Point_property_map, CGAL::Euclidean_distance<Traits_base> >(
+ std::begin(m_points)) );
+
+ return search;
+ }
+
+ /// \brief Search for the k-farthest points from a query point.
+ /// @param[in] p The query point.
+ /// @param[in] k Number of farthest points to search.
+ /// @param[in] sorted Indicates if the computed sequence of k-farthest neighbors needs to be sorted.
+ /// @param[in] eps Approximation factor.
+ /// @return A range containing the k-farthest neighbors.
+ KNS_range query_k_farthest_neighbors(const
+ Point &p,
+ unsigned int k,
+ bool sorted = true,
+ FT eps = FT(0)) const {
+ // Initialize the search structure, and search all N points
+ // Note that we need to pass the Distance explicitly since it needs to
+ // know the property map
+ K_neighbor_search search(
+ m_tree,
+ p,
+ k,
+ eps,
+ false,
+ CGAL::Distance_adapter<std::ptrdiff_t, Point_property_map, CGAL::Euclidean_distance<Traits_base> >(
+ std::begin(m_points)), sorted);
+
+ return search;
+ }
+
+ /// \brief Search incrementally for the farthest neighbors from a query point.
+ /// @param[in] p The query point.
+ /// @param[in] eps Approximation factor.
+ /// @return A range containing the neighbors sorted by their distance to p.
+ /// All the neighbors are not computed by this function, but they will be
+ /// computed incrementally when the iterator on the range is incremented.
+ INS_range query_incremental_farthest_neighbors(const Point &p, FT eps = FT(0)) const {
+ // Initialize the search structure, and search all N points
+ // Note that we need to pass the Distance explicitly since it needs to
+ // know the property map
+ Incremental_neighbor_search search(
+ m_tree,
+ p,
+ eps,
+ false,
+ CGAL::Distance_adapter<std::ptrdiff_t, Point_property_map, CGAL::Euclidean_distance<Traits_base> >(
+ std::begin(m_points)) );
+
+ return search;
+ }
+
+ private:
+ Point_range const& m_points;
+ Tree m_tree;
+};
+
+} // namespace spatial_searching
+} // namespace Gudhi
+
+#endif // KD_TREE_SEARCH_H_
diff --git a/include/gudhi/Landmark_choice_by_furthest_point.h b/include/gudhi/Landmark_choice_by_furthest_point.h
deleted file mode 100644
index df93155b..00000000
--- a/include/gudhi/Landmark_choice_by_furthest_point.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* This file is part of the Gudhi Library. The Gudhi library
- * (Geometric Understanding in Higher Dimensions) is a generic C++
- * library for computational topology.
- *
- * Author(s): Siargey Kachanovich
- *
- * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (France)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LANDMARK_CHOICE_BY_FURTHEST_POINT_H_
-#define LANDMARK_CHOICE_BY_FURTHEST_POINT_H_
-
-#include <boost/range/size.hpp>
-
-#include <limits> // for numeric_limits<>
-#include <iterator>
-#include <algorithm> // for sort
-#include <vector>
-
-namespace Gudhi {
-
-namespace witness_complex {
-
- typedef std::vector<int> typeVectorVertex;
-
- /**
- * \ingroup witness_complex
- * \brief Landmark choice strategy by iteratively adding the furthest witness from the
- * current landmark set as the new landmark.
- * \details It chooses nbL landmarks from a random access range `points` and
- * writes {witness}*{closest landmarks} matrix in `knn`.
- *
- * The type KNearestNeighbors can be seen as
- * Witness_range<Closest_landmark_range<Vertex_handle>>, where
- * Witness_range and Closest_landmark_range are random access ranges
- *
- */
-
- template <typename KNearestNeighbours,
- typename Point_random_access_range>
- void landmark_choice_by_furthest_point(Point_random_access_range const &points,
- int nbL,
- KNearestNeighbours &knn) {
- int nb_points = boost::size(points);
- assert(nb_points >= nbL);
- // distance matrix witness x landmarks
- std::vector<std::vector<double>> wit_land_dist(nb_points, std::vector<double>());
- // landmark list
- typeVectorVertex chosen_landmarks;
-
- knn = KNearestNeighbours(nb_points, std::vector<int>());
- int current_number_of_landmarks = 0; // counter for landmarks
- double curr_max_dist = 0; // used for defining the furhest point from L
- const double infty = std::numeric_limits<double>::infinity(); // infinity (see next entry)
- std::vector< double > dist_to_L(nb_points, infty); // vector of current distances to L from points
-
- // TODO(SK) Consider using rand_r(...) instead of rand(...) for improved thread safety
- // or better yet std::uniform_int_distribution
- int rand_int = rand() % nb_points;
- int curr_max_w = rand_int; // For testing purposes a pseudo-random number is used here
-
- for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) {
- // curr_max_w at this point is the next landmark
- chosen_landmarks.push_back(curr_max_w);
- unsigned i = 0;
- for (auto& p : points) {
- double curr_dist = euclidean_distance(p, *(std::begin(points) + chosen_landmarks[current_number_of_landmarks]));
- wit_land_dist[i].push_back(curr_dist);
- knn[i].push_back(current_number_of_landmarks);
- if (curr_dist < dist_to_L[i])
- dist_to_L[i] = curr_dist;
- ++i;
- }
- curr_max_dist = 0;
- for (i = 0; i < dist_to_L.size(); i++)
- if (dist_to_L[i] > curr_max_dist) {
- curr_max_dist = dist_to_L[i];
- curr_max_w = i;
- }
- }
- for (int i = 0; i < nb_points; ++i)
- std::sort(std::begin(knn[i]),
- std::end(knn[i]),
- [&wit_land_dist, i](int a, int b) {
- return wit_land_dist[i][a] < wit_land_dist[i][b]; });
- }
-
-} // namespace witness_complex
-
-} // namespace Gudhi
-
-#endif // LANDMARK_CHOICE_BY_FURTHEST_POINT_H_
diff --git a/include/gudhi/Landmark_choice_by_random_point.h b/include/gudhi/Landmark_choice_by_random_point.h
deleted file mode 100644
index ebf6aad1..00000000
--- a/include/gudhi/Landmark_choice_by_random_point.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* This file is part of the Gudhi Library. The Gudhi library
- * (Geometric Understanding in Higher Dimensions) is a generic C++
- * library for computational topology.
- *
- * Author(s): Siargey Kachanovich
- *
- * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (France)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LANDMARK_CHOICE_BY_RANDOM_POINT_H_
-#define LANDMARK_CHOICE_BY_RANDOM_POINT_H_
-
-#include <boost/range/size.hpp>
-
-#include <queue> // for priority_queue<>
-#include <utility> // for pair<>
-#include <iterator>
-#include <vector>
-#include <set>
-
-namespace Gudhi {
-
-namespace witness_complex {
-
- /**
- * \ingroup witness_complex
- * \brief Landmark choice strategy by taking random vertices for landmarks.
- * \details It chooses nbL distinct landmarks from a random access range `points`
- * and outputs a matrix {witness}*{closest landmarks} in knn.
- *
- * The type KNearestNeighbors can be seen as
- * Witness_range<Closest_landmark_range<Vertex_handle>>, where
- * Witness_range and Closest_landmark_range are random access ranges and
- * Vertex_handle is the label type of a vertex in a simplicial complex.
- * Closest_landmark_range needs to have push_back operation.
- */
-
- template <typename KNearestNeighbours,
- typename Point_random_access_range>
- void landmark_choice_by_random_point(Point_random_access_range const &points,
- int nbL,
- KNearestNeighbours &knn) {
- int nbP = boost::size(points);
- assert(nbP >= nbL);
- std::set<int> landmarks;
- int current_number_of_landmarks = 0; // counter for landmarks
-
- // TODO(SK) Consider using rand_r(...) instead of rand(...) for improved thread safety
- int chosen_landmark = rand() % nbP;
- for (current_number_of_landmarks = 0; current_number_of_landmarks != nbL; current_number_of_landmarks++) {
- while (landmarks.find(chosen_landmark) != landmarks.end())
- chosen_landmark = rand() % nbP;
- landmarks.insert(chosen_landmark);
- }
-
- int dim = boost::size(*std::begin(points));
- typedef std::pair<double, int> dist_i;
- typedef bool (*comp)(dist_i, dist_i);
- knn = KNearestNeighbours(nbP);
- for (int points_i = 0; points_i < nbP; points_i++) {
- std::priority_queue<dist_i, std::vector<dist_i>, comp> l_heap([](dist_i j1, dist_i j2) {
- return j1.first > j2.first;
- });
- std::set<int>::iterator landmarks_it;
- int landmarks_i = 0;
- for (landmarks_it = landmarks.begin(), landmarks_i = 0; landmarks_it != landmarks.end();
- ++landmarks_it, landmarks_i++) {
- dist_i dist = std::make_pair(euclidean_distance(points[points_i], points[*landmarks_it]), landmarks_i);
- l_heap.push(dist);
- }
- for (int i = 0; i < dim + 1; i++) {
- dist_i dist = l_heap.top();
- knn[points_i].push_back(dist.second);
- l_heap.pop();
- }
- }
- }
-
-} // namespace witness_complex
-
-} // namespace Gudhi
-
-#endif // LANDMARK_CHOICE_BY_RANDOM_POINT_H_
diff --git a/include/gudhi/Neighbors_finder.h b/include/gudhi/Neighbors_finder.h
new file mode 100644
index 00000000..bdc47578
--- /dev/null
+++ b/include/gudhi/Neighbors_finder.h
@@ -0,0 +1,192 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author: Francois Godi
+ *
+ * Copyright (C) 2015 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NEIGHBORS_FINDER_H_
+#define NEIGHBORS_FINDER_H_
+
+// Inclusion order is important for CGAL patch
+#include <CGAL/Kd_tree.h>
+#include <CGAL/Search_traits.h>
+
+#include <gudhi/Persistence_graph.h>
+#include <gudhi/Internal_point.h>
+
+#include <unordered_set>
+#include <vector>
+
+namespace Gudhi {
+
+namespace persistence_diagram {
+
+/** \internal \brief Variant of CGAL::Fuzzy_iso_box to ensure that the box ic closed. It isn't clear how necessary that is.
+ */
+struct Square_query {
+ typedef CGAL::Dimension_tag<2> D;
+ typedef Internal_point Point_d;
+ typedef double FT;
+ bool contains(Point_d p) const {
+ return std::abs(p.x()-c.x())<=size && std::abs(p.y()-c.y())<=size;
+ }
+ bool inner_range_intersects(CGAL::Kd_tree_rectangle<FT,D> const&r) const {
+ return
+ r.max_coord(0) >= c.x() - size &&
+ r.min_coord(0) <= c.x() + size &&
+ r.max_coord(1) >= c.y() - size &&
+ r.min_coord(1) <= c.y() + size;
+ }
+ bool outer_range_contains(CGAL::Kd_tree_rectangle<FT,D> const&r) const {
+ return
+ r.min_coord(0) >= c.x() - size &&
+ r.max_coord(0) <= c.x() + size &&
+ r.min_coord(1) >= c.y() - size &&
+ r.max_coord(1) <= c.y() + size;
+ }
+ Point_d c;
+ FT size;
+};
+
+/** \internal \brief data structure used to find any point (including projections) in V near to a query point from U
+ * (which can be a projection).
+ *
+ * V points have to be added manually using their index and before the first pull. A neighbor pulled is automatically
+ * removed.
+ *
+ * \ingroup bottleneck_distance
+ */
+class Neighbors_finder {
+ typedef CGAL::Dimension_tag<2> D;
+ typedef CGAL::Search_traits<double, Internal_point, const double*, Construct_coord_iterator, D> Traits;
+ typedef CGAL::Kd_tree<Traits> Kd_tree;
+
+ public:
+ /** \internal \brief Constructor taking the near distance definition as parameter. */
+ Neighbors_finder(const Persistence_graph& g, double r);
+ /** \internal \brief A point added will be possibly pulled. */
+ void add(int v_point_index);
+ /** \internal \brief Returns and remove a V point near to the U point given as parameter, null_point_index() if
+ * there isn't such a point. */
+ int pull_near(int u_point_index);
+ /** \internal \brief Returns and remove all the V points near to the U point given as parameter. */
+ std::vector<int> pull_all_near(int u_point_index);
+
+ private:
+ const Persistence_graph& g;
+ const double r;
+ Kd_tree kd_t;
+ std::unordered_set<int> projections_f;
+};
+
+/** \internal \brief data structure used to find any point (including projections) in V near to a query point from U
+ * (which can be a projection) in a layered graph layer given as parmeter.
+ *
+ * V points have to be added manually using their index and before the first pull. A neighbor pulled is automatically
+ * removed.
+ *
+ * \ingroup bottleneck_distance
+ */
+class Layered_neighbors_finder {
+ public:
+ /** \internal \brief Constructor taking the near distance definition as parameter. */
+ Layered_neighbors_finder(const Persistence_graph& g, double r);
+ /** \internal \brief A point added will be possibly pulled. */
+ void add(int v_point_index, int vlayer);
+ /** \internal \brief Returns and remove a V point near to the U point given as parameter, null_point_index() if
+ * there isn't such a point. */
+ int pull_near(int u_point_index, int vlayer);
+ /** \internal \brief Returns the number of layers. */
+ int vlayers_number() const;
+
+ private:
+ const Persistence_graph& g;
+ const double r;
+ std::vector<std::unique_ptr<Neighbors_finder>> neighbors_finder;
+};
+
+inline Neighbors_finder::Neighbors_finder(const Persistence_graph& g, double r) :
+ g(g), r(r), kd_t(), projections_f() { }
+
+inline void Neighbors_finder::add(int v_point_index) {
+ if (g.on_the_v_diagonal(v_point_index))
+ projections_f.emplace(v_point_index);
+ else
+ kd_t.insert(g.get_v_point(v_point_index));
+}
+
+inline int Neighbors_finder::pull_near(int u_point_index) {
+ int tmp;
+ int c = g.corresponding_point_in_v(u_point_index);
+ if (g.on_the_u_diagonal(u_point_index) && !projections_f.empty()) {
+ // Any pair of projection is at distance 0
+ tmp = *projections_f.cbegin();
+ projections_f.erase(tmp);
+ } else if (projections_f.count(c) && (g.distance(u_point_index, c) <= r)) {
+ // Is the query point near to its projection ?
+ tmp = c;
+ projections_f.erase(tmp);
+ } else {
+ // Is the query point near to a V point in the plane ?
+ Internal_point u_point = g.get_u_point(u_point_index);
+ auto neighbor = kd_t.search_any_point(Square_query{u_point, r});
+ if(!neighbor)
+ return null_point_index();
+ tmp = neighbor->point_index;
+ auto point = g.get_v_point(tmp);
+ int idx = point.point_index;
+ kd_t.remove(point, [idx](Internal_point const&p){return p.point_index == idx;});
+ }
+ return tmp;
+}
+
+inline std::vector<int> Neighbors_finder::pull_all_near(int u_point_index) {
+ std::vector<int> all_pull;
+ int last_pull = pull_near(u_point_index);
+ while (last_pull != null_point_index()) {
+ all_pull.emplace_back(last_pull);
+ last_pull = pull_near(u_point_index);
+ }
+ return all_pull;
+}
+
+inline Layered_neighbors_finder::Layered_neighbors_finder(const Persistence_graph& g, double r) :
+ g(g), r(r), neighbors_finder() { }
+
+inline void Layered_neighbors_finder::add(int v_point_index, int vlayer) {
+ for (int l = neighbors_finder.size(); l <= vlayer; l++)
+ neighbors_finder.emplace_back(std::unique_ptr<Neighbors_finder>(new Neighbors_finder(g, r)));
+ neighbors_finder.at(vlayer)->add(v_point_index);
+}
+
+inline int Layered_neighbors_finder::pull_near(int u_point_index, int vlayer) {
+ if (static_cast<int> (neighbors_finder.size()) <= vlayer)
+ return null_point_index();
+ return neighbors_finder.at(vlayer)->pull_near(u_point_index);
+}
+
+inline int Layered_neighbors_finder::vlayers_number() const {
+ return static_cast<int> (neighbors_finder.size());
+}
+
+} // namespace persistence_diagram
+
+} // namespace Gudhi
+
+#endif // NEIGHBORS_FINDER_H_
diff --git a/include/gudhi/Null_output_iterator.h b/include/gudhi/Null_output_iterator.h
new file mode 100644
index 00000000..42e6e449
--- /dev/null
+++ b/include/gudhi/Null_output_iterator.h
@@ -0,0 +1,48 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Marc Glisse
+ *
+ * Copyright (C) 2017 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NULL_OUTPUT_ITERATOR_H_
+#define NULL_OUTPUT_ITERATOR_H_
+
+#include <iterator>
+
+namespace Gudhi {
+
+/** An output iterator that ignores whatever it is given. */
+struct Null_output_iterator {
+ typedef std::output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ Null_output_iterator& operator++() {return *this;}
+ Null_output_iterator operator++(int) {return *this;}
+ struct proxy {
+ template<class T>
+ proxy& operator=(T&&){return *this;}
+ };
+ proxy operator*()const{return {};}
+};
+} // namespace Gudhi
+
+#endif // NULL_OUTPUT_ITERATOR_H_
diff --git a/include/gudhi/Persistence_graph.h b/include/gudhi/Persistence_graph.h
new file mode 100644
index 00000000..44f4b827
--- /dev/null
+++ b/include/gudhi/Persistence_graph.h
@@ -0,0 +1,188 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author: Francois Godi
+ *
+ * Copyright (C) 2015 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PERSISTENCE_GRAPH_H_
+#define PERSISTENCE_GRAPH_H_
+
+#include <gudhi/Internal_point.h>
+
+#ifdef GUDHI_USE_TBB
+#include <tbb/parallel_sort.h>
+#endif
+
+#include <vector>
+#include <algorithm>
+#include <limits> // for numeric_limits
+
+namespace Gudhi {
+
+namespace persistence_diagram {
+
+/** \internal \brief Structure representing an euclidean bipartite graph containing
+ * the points from the two persistence diagrams (including the projections).
+ *
+ * \ingroup bottleneck_distance
+ */
+class Persistence_graph {
+ public:
+ /** \internal \brief Constructor taking 2 PersistenceDiagrams (concept) as parameters. */
+ template<typename Persistence_diagram1, typename Persistence_diagram2>
+ Persistence_graph(const Persistence_diagram1& diag1, const Persistence_diagram2& diag2, double e);
+ /** \internal \brief Is the given point from U the projection of a point in V ? */
+ bool on_the_u_diagonal(int u_point_index) const;
+ /** \internal \brief Is the given point from V the projection of a point in U ? */
+ bool on_the_v_diagonal(int v_point_index) const;
+ /** \internal \brief Given a point from V, returns the corresponding (projection or projector) point in U. */
+ int corresponding_point_in_u(int v_point_index) const;
+ /** \internal \brief Given a point from U, returns the corresponding (projection or projector) point in V. */
+ int corresponding_point_in_v(int u_point_index) const;
+ /** \internal \brief Given a point from U and a point from V, returns the distance between those points. */
+ double distance(int u_point_index, int v_point_index) const;
+ /** \internal \brief Returns size = |U| = |V|. */
+ int size() const;
+ /** \internal \brief Is there as many infinite points (alive components) in both diagrams ? */
+ double bottleneck_alive() const;
+ /** \internal \brief Returns the O(n^2) sorted distances between the points. */
+ std::vector<double> sorted_distances() const;
+ /** \internal \brief Returns an upper bound for the diameter of the convex hull of all non infinite points */
+ double diameter_bound() const;
+ /** \internal \brief Returns the corresponding internal point */
+ Internal_point get_u_point(int u_point_index) const;
+ /** \internal \brief Returns the corresponding internal point */
+ Internal_point get_v_point(int v_point_index) const;
+
+ private:
+ std::vector<Internal_point> u;
+ std::vector<Internal_point> v;
+ double b_alive;
+};
+
+template<typename Persistence_diagram1, typename Persistence_diagram2>
+Persistence_graph::Persistence_graph(const Persistence_diagram1 &diag1,
+ const Persistence_diagram2 &diag2, double e)
+ : u(), v(), b_alive(0.) {
+ std::vector<double> u_alive;
+ std::vector<double> v_alive;
+ for (auto it = std::begin(diag1); it != std::end(diag1); ++it) {
+ if (std::get<1>(*it) == std::numeric_limits<double>::infinity())
+ u_alive.push_back(std::get<0>(*it));
+ else if (std::get<1>(*it) - std::get<0>(*it) > e)
+ u.push_back(Internal_point(std::get<0>(*it), std::get<1>(*it), u.size()));
+ }
+ for (auto it = std::begin(diag2); it != std::end(diag2); ++it) {
+ if (std::get<1>(*it) == std::numeric_limits<double>::infinity())
+ v_alive.push_back(std::get<0>(*it));
+ else if (std::get<1>(*it) - std::get<0>(*it) > e)
+ v.push_back(Internal_point(std::get<0>(*it), std::get<1>(*it), v.size()));
+ }
+ if (u.size() < v.size())
+ swap(u, v);
+ std::sort(u_alive.begin(), u_alive.end());
+ std::sort(v_alive.begin(), v_alive.end());
+ if (u_alive.size() != v_alive.size()) {
+ b_alive = std::numeric_limits<double>::infinity();
+ } else {
+ for (auto it_u = u_alive.cbegin(), it_v = v_alive.cbegin(); it_u != u_alive.cend(); ++it_u, ++it_v)
+ b_alive = std::max(b_alive, std::fabs(*it_u - *it_v));
+ }
+}
+
+inline bool Persistence_graph::on_the_u_diagonal(int u_point_index) const {
+ return u_point_index >= static_cast<int> (u.size());
+}
+
+inline bool Persistence_graph::on_the_v_diagonal(int v_point_index) const {
+ return v_point_index >= static_cast<int> (v.size());
+}
+
+inline int Persistence_graph::corresponding_point_in_u(int v_point_index) const {
+ return on_the_v_diagonal(v_point_index) ?
+ v_point_index - static_cast<int> (v.size()) : v_point_index + static_cast<int> (u.size());
+}
+
+inline int Persistence_graph::corresponding_point_in_v(int u_point_index) const {
+ return on_the_u_diagonal(u_point_index) ?
+ u_point_index - static_cast<int> (u.size()) : u_point_index + static_cast<int> (v.size());
+}
+
+inline double Persistence_graph::distance(int u_point_index, int v_point_index) const {
+ if (on_the_u_diagonal(u_point_index) && on_the_v_diagonal(v_point_index))
+ return 0.;
+ Internal_point p_u = get_u_point(u_point_index);
+ Internal_point p_v = get_v_point(v_point_index);
+ return std::max(std::fabs(p_u.x() - p_v.x()), std::fabs(p_u.y() - p_v.y()));
+}
+
+inline int Persistence_graph::size() const {
+ return static_cast<int> (u.size() + v.size());
+}
+
+inline double Persistence_graph::bottleneck_alive() const {
+ return b_alive;
+}
+
+inline std::vector<double> Persistence_graph::sorted_distances() const {
+ std::vector<double> distances;
+ distances.push_back(0.); // for empty diagrams
+ for (int u_point_index = 0; u_point_index < size(); ++u_point_index) {
+ distances.push_back(distance(u_point_index, corresponding_point_in_v(u_point_index)));
+ for (int v_point_index = 0; v_point_index < size(); ++v_point_index)
+ distances.push_back(distance(u_point_index, v_point_index));
+ }
+#ifdef GUDHI_USE_TBB
+ tbb::parallel_sort(distances.begin(), distances.end());
+#else
+ std::sort(distances.begin(), distances.end());
+#endif
+ return distances;
+}
+
+inline Internal_point Persistence_graph::get_u_point(int u_point_index) const {
+ if (!on_the_u_diagonal(u_point_index))
+ return u.at(u_point_index);
+ Internal_point projector = v.at(corresponding_point_in_v(u_point_index));
+ double m = (projector.x() + projector.y()) / 2.;
+ return Internal_point(m, m, u_point_index);
+}
+
+inline Internal_point Persistence_graph::get_v_point(int v_point_index) const {
+ if (!on_the_v_diagonal(v_point_index))
+ return v.at(v_point_index);
+ Internal_point projector = u.at(corresponding_point_in_u(v_point_index));
+ double m = (projector.x() + projector.y()) / 2.;
+ return Internal_point(m, m, v_point_index);
+}
+
+inline double Persistence_graph::diameter_bound() const {
+ double max = 0.;
+ for (auto it = u.cbegin(); it != u.cend(); it++)
+ max = std::max(max, it->y());
+ for (auto it = v.cbegin(); it != v.cend(); it++)
+ max = std::max(max, it->y());
+ return max;
+}
+
+} // namespace persistence_diagram
+
+} // namespace Gudhi
+
+#endif // PERSISTENCE_GRAPH_H_
diff --git a/include/gudhi/Persistent_cohomology.h b/include/gudhi/Persistent_cohomology.h
index b31df6a4..672fda48 100644
--- a/include/gudhi/Persistent_cohomology.h
+++ b/include/gudhi/Persistent_cohomology.h
@@ -110,7 +110,7 @@ class Persistent_cohomology {
cell_pool_() {
if (cpx_->num_simplices() > std::numeric_limits<Simplex_key>::max()) {
// num_simplices must be strictly lower than the limit, because a value is reserved for null_key.
- throw std::out_of_range ("The number of simplices is more than Simplex_key type numeric limit.");
+ throw std::out_of_range("The number of simplices is more than Simplex_key type numeric limit.");
}
Simplex_key idx_fil = 0;
for (auto sh : cpx_->filtration_simplex_range()) {
@@ -300,8 +300,7 @@ class Persistent_cohomology {
// with multiplicity. We used to sum the coefficients directly in
// annotations_in_boundary by using a map, we now do it later.
typedef std::pair<Column *, int> annotation_t;
- // Danger: not thread-safe!
- static std::vector<annotation_t> annotations_in_boundary;
+ thread_local std::vector<annotation_t> annotations_in_boundary;
annotations_in_boundary.clear();
int sign = 1 - 2 * (dim_sigma % 2); // \in {-1,1} provides the sign in the
// alternate sum in the boundary.
@@ -604,7 +603,7 @@ class Persistent_cohomology {
*/
std::vector<int> betti_numbers() const {
// Init Betti numbers vector with zeros until Simplicial complex dimension
- std::vector<int> betti_numbers(cpx_->dimension(), 0);
+ std::vector<int> betti_numbers(dim_max_, 0);
for (auto pair : persistent_pairs_) {
// Count never ended persistence intervals
@@ -643,8 +642,7 @@ class Persistent_cohomology {
*/
std::vector<int> persistent_betti_numbers(Filtration_value from, Filtration_value to) const {
// Init Betti numbers vector with zeros until Simplicial complex dimension
- std::vector<int> betti_numbers(cpx_->dimension(), 0);
-
+ std::vector<int> betti_numbers(dim_max_, 0);
for (auto pair : persistent_pairs_) {
// Count persistence intervals that covers the given interval
// null_simplex test : if the function is called with to=+infinity, we still get something useful. And it will
@@ -690,6 +688,22 @@ class Persistent_cohomology {
return persistent_pairs_;
}
+ /** @brief Returns persistence intervals for a given dimension.
+ * @param[in] dimension Dimension to get the birth and death pairs from.
+ * @return A vector of persistence intervals (birth and death) on a fixed dimension.
+ */
+ std::vector< std::pair< Filtration_value , Filtration_value > >
+ intervals_in_dimension(int dimension) {
+ std::vector< std::pair< Filtration_value , Filtration_value > > result;
+ // auto && pair, to avoid unnecessary copying
+ for (auto && pair : persistent_pairs_) {
+ if (cpx_->dimension(get<0>(pair)) == dimension) {
+ result.emplace_back(cpx_->filtration(get<0>(pair)), cpx_->filtration(get<1>(pair)));
+ }
+ }
+ return result;
+ }
+
private:
/*
* Structure representing a cocycle.
diff --git a/include/gudhi/Points_3D_off_io.h b/include/gudhi/Points_3D_off_io.h
index 2647f11e..b0d24998 100644
--- a/include/gudhi/Points_3D_off_io.h
+++ b/include/gudhi/Points_3D_off_io.h
@@ -132,12 +132,12 @@ class Points_3D_off_visitor_reader {
*
* @code template<class InputIterator > Point_3::Point_3(double x, double y, double z) @endcode
*
- * @section Example
+ * @section point3doffioexample Example
*
* This example loads points from an OFF file and builds a vector of CGAL points in dimension 3.
* Then, it is asked to display the points.
*
- * @include common/CGAL_3D_points_off_reader.cpp
+ * @include common/example_CGAL_3D_points_off_reader.cpp
*
* When launching:
*
diff --git a/include/gudhi/Points_off_io.h b/include/gudhi/Points_off_io.h
index 74b49386..29af8a8a 100644
--- a/include/gudhi/Points_off_io.h
+++ b/include/gudhi/Points_off_io.h
@@ -73,9 +73,8 @@ class Points_off_visitor_reader {
* @details
* Point_d must have a constructor with the following form:
*
- * @code template<class InputIterator > Point_d::Point_d(int d, InputIterator first, InputIterator last) @endcode
+ * @code template<class InputIterator > Point_d::Point_d(InputIterator first, InputIterator last) @endcode
*
- * where d is the point dimension.
*/
void point(const std::vector<double>& point) {
#ifdef DEBUG_TRACES
@@ -86,7 +85,7 @@ class Points_off_visitor_reader {
std::cout << std::endl;
#endif // DEBUG_TRACES
// Fill the point cloud
- point_cloud.push_back(Point_d(point.size(), point.begin(), point.end()));
+ point_cloud.push_back(Point_d(point.begin(), point.end()));
}
// Off_reader visitor maximal_face implementation - Only points are read
@@ -115,16 +114,16 @@ class Points_off_visitor_reader {
*
* where d is the point dimension.
*
- * \section Example
+ * \section pointoffioexample Example
*
- * This example loads points from an OFF file and builds a vector of CGAL points in dimension d.
+ * This example loads points from an OFF file and builds a vector of points (vector of double).
* Then, it is asked to display the points.
*
- * \include common/CGAL_points_off_reader.cpp
+ * \include common/example_vector_double_points_off_reader.cpp
*
* When launching:
*
- * \code $> ./cgaloffreader ../../data/points/alphacomplexdoc.off
+ * \code $> ./vector_double_off_reader ../../data/points/alphacomplexdoc.off
* \endcode
*
* the program output is:
diff --git a/include/gudhi/Rips_complex.h b/include/gudhi/Rips_complex.h
new file mode 100644
index 00000000..1e4b76a7
--- /dev/null
+++ b/include/gudhi/Rips_complex.h
@@ -0,0 +1,185 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clément Maria, Pawel Dlotko, Vincent Rouvreau
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RIPS_COMPLEX_H_
+#define RIPS_COMPLEX_H_
+
+#include <gudhi/Debug_utils.h>
+#include <gudhi/graph_simplicial_complex.h>
+
+#include <boost/graph/adjacency_list.hpp>
+
+#include <iostream>
+#include <vector>
+#include <map>
+#include <string>
+#include <limits> // for numeric_limits
+#include <utility> // for pair<>
+
+
+namespace Gudhi {
+
+namespace rips_complex {
+
+/**
+ * \class Rips_complex
+ * \brief Rips complex data structure.
+ *
+ * \ingroup rips_complex
+ *
+ * \details
+ * The data structure is a one skeleton graph, or Rips graph, containing edges when the edge length is less or equal
+ * to a given threshold. Edge length is computed from a user given point cloud with a given distance function, or a
+ * distance matrix.
+ *
+ * \tparam Filtration_value is the type used to store the filtration values of the simplicial complex.
+ */
+template<typename Filtration_value>
+class Rips_complex {
+ public:
+ /**
+ * \brief Type of the one skeleton graph stored inside the Rips complex structure.
+ */
+ typedef typename boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS
+ , boost::property < vertex_filtration_t, Filtration_value >
+ , boost::property < edge_filtration_t, Filtration_value >> OneSkeletonGraph;
+
+ private:
+ typedef int Vertex_handle;
+
+ public:
+ /** \brief Rips_complex constructor from a list of points.
+ *
+ * @param[in] points Range of points.
+ * @param[in] threshold Rips value.
+ * @param[in] distance distance function that returns a `Filtration_value` from 2 given points.
+ *
+ * \tparam ForwardPointRange must be a range for which `std::begin` and `std::end` return input iterators on a
+ * point.
+ *
+ * \tparam Distance furnishes `operator()(const Point& p1, const Point& p2)`, where
+ * `Point` is a point from the `ForwardPointRange`, and that returns a `Filtration_value`.
+ */
+ template<typename ForwardPointRange, typename Distance >
+ Rips_complex(const ForwardPointRange& points, Filtration_value threshold, Distance distance) {
+ compute_proximity_graph(points, threshold, distance);
+ }
+
+ /** \brief Rips_complex constructor from a distance matrix.
+ *
+ * @param[in] distance_matrix Range of distances.
+ * @param[in] threshold Rips value.
+ *
+ * \tparam DistanceMatrix must have a `size()` method and on which `distance_matrix[i][j]` returns
+ * the distance between points \f$i\f$ and \f$j\f$ as long as \f$ 0 \leqslant i < j \leqslant
+ * distance\_matrix.size().\f$
+ */
+ template<typename DistanceMatrix>
+ Rips_complex(const DistanceMatrix& distance_matrix, Filtration_value threshold) {
+ compute_proximity_graph(boost::irange((size_t)0, distance_matrix.size()), threshold,
+ [&](size_t i, size_t j){return distance_matrix[j][i];});
+ }
+
+ /** \brief Initializes the simplicial complex from the Rips graph and expands it until a given maximal
+ * dimension.
+ *
+ * \tparam SimplicialComplexForRips must meet `SimplicialComplexForRips` concept.
+ *
+ * @param[in] complex SimplicialComplexForRips to be created.
+ * @param[in] dim_max graph expansion for Rips until this given maximal dimension.
+ * @exception std::invalid_argument In debug mode, if `complex.num_vertices()` does not return 0.
+ *
+ */
+ template <typename SimplicialComplexForRips>
+ void create_complex(SimplicialComplexForRips& complex, int dim_max) {
+ GUDHI_CHECK(complex.num_vertices() == 0,
+ std::invalid_argument("Rips_complex::create_complex - simplicial complex is not empty"));
+
+ // insert the proximity graph in the simplicial complex
+ complex.insert_graph(rips_skeleton_graph_);
+ // expand the graph until dimension dim_max
+ complex.expansion(dim_max);
+ }
+
+ private:
+ /** \brief Computes the proximity graph of the points.
+ *
+ * If points contains n elements, the proximity graph is the graph with n vertices, and an edge [u,v] iff the
+ * distance function between points u and v is smaller than threshold.
+ *
+ * \tparam ForwardPointRange furnishes `.begin()` and `.end()`
+ * methods.
+ *
+ * \tparam Distance furnishes `operator()(const Point& p1, const Point& p2)`, where
+ * `Point` is a point from the `ForwardPointRange`, and that returns a `Filtration_value`.
+ */
+ template< typename ForwardPointRange, typename Distance >
+ void compute_proximity_graph(const ForwardPointRange& points, Filtration_value threshold,
+ Distance distance) {
+ std::vector< std::pair< Vertex_handle, Vertex_handle > > edges;
+ std::vector< Filtration_value > edges_fil;
+
+ // Compute the proximity graph of the points.
+ // If points contains n elements, the proximity graph is the graph with n vertices, and an edge [u,v] iff the
+ // distance function between points u and v is smaller than threshold.
+ // --------------------------------------------------------------------------------------------
+ // Creates the vector of edges and its filtration values (returned by distance function)
+ Vertex_handle idx_u = 0;
+ for (auto it_u = std::begin(points); it_u != std::end(points); ++it_u, ++idx_u) {
+ Vertex_handle idx_v = idx_u + 1;
+ for (auto it_v = it_u + 1; it_v != std::end(points); ++it_v, ++idx_v) {
+ Filtration_value fil = distance(*it_u, *it_v);
+ if (fil <= threshold) {
+ edges.emplace_back(idx_u, idx_v);
+ edges_fil.push_back(fil);
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------
+ // Creates the proximity graph from edges and sets the property with the filtration value.
+ // Number of points is labeled from 0 to idx_u-1
+ // --------------------------------------------------------------------------------------------
+ // Do not use : rips_skeleton_graph_ = OneSkeletonGraph(...) -> deep copy of the graph (boost graph is not
+ // move-enabled)
+ rips_skeleton_graph_.~OneSkeletonGraph();
+ new(&rips_skeleton_graph_)OneSkeletonGraph(edges.begin(), edges.end(), edges_fil.begin(), idx_u);
+
+ auto vertex_prop = boost::get(vertex_filtration_t(), rips_skeleton_graph_);
+
+ using vertex_iterator = typename boost::graph_traits<OneSkeletonGraph>::vertex_iterator;
+ vertex_iterator vi, vi_end;
+ for (std::tie(vi, vi_end) = boost::vertices(rips_skeleton_graph_);
+ vi != vi_end; ++vi) {
+ boost::put(vertex_prop, *vi, 0.);
+ }
+ }
+
+ private:
+ OneSkeletonGraph rips_skeleton_graph_;
+};
+
+} // namespace rips_complex
+
+} // namespace Gudhi
+
+#endif // RIPS_COMPLEX_H_
diff --git a/include/gudhi/Simplex_tree.h b/include/gudhi/Simplex_tree.h
index 63e3f0e5..317bce23 100644
--- a/include/gudhi/Simplex_tree.h
+++ b/include/gudhi/Simplex_tree.h
@@ -1029,7 +1029,7 @@ class Simplex_tree {
Dictionary_it next = siblings->members().begin();
++next;
- static std::vector<std::pair<Vertex_handle, Node> > inter; // static, not thread-safe.
+ thread_local std::vector<std::pair<Vertex_handle, Node> > inter;
for (Dictionary_it s_h = siblings->members().begin();
s_h != siblings->members().end(); ++s_h, ++next) {
Simplex_handle root_sh = find_vertex(s_h->first);
diff --git a/include/gudhi/Skeleton_blocker.h b/include/gudhi/Skeleton_blocker.h
index 822282fd..32fe411c 100644
--- a/include/gudhi/Skeleton_blocker.h
+++ b/include/gudhi/Skeleton_blocker.h
@@ -1,24 +1,24 @@
- /* This file is part of the Gudhi Library. The Gudhi library
- * (Geometric Understanding in Higher Dimensions) is a generic C++
- * library for computational topology.
- *
- * Author(s): David Salinas
- *
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): David Salinas
+ *
+ * Copyright (C) 2014 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
#ifndef SKELETON_BLOCKER_H_
#define SKELETON_BLOCKER_H_
@@ -37,11 +37,12 @@ namespace Gudhi {
namespace skeleton_blocker {
-/** \defgroup skbl Skeleton-Blocker
+/** \defgroup skbl Skeleton-Blocker
+@{
\author David Salinas
-\section Introduction
+\section skblintroduction Introduction
The Skeleton-Blocker data-structure proposes a light encoding for simplicial complexes by storing only an *implicit* representation of its
simplices
\cite socg_blockers_2011,\cite blockers2012.
@@ -52,7 +53,7 @@ This data-structure handles all simplicial complexes operations such as
are operations that do not require simplex enumeration such as edge iteration, link computation or simplex contraction.
-\section Definitions
+\section skbldefinitions Definitions
We recall briefly classical definitions of simplicial complexes
\cite Munkres-elementsalgtop1984.
@@ -63,7 +64,7 @@ when \f$ \tau \neq \sigma\f$ we say that \f$ \tau\f$ is a proper-face of \f$ \si
An abstract simplicial complex is a set of simplices that contains all the faces of its simplices.
The 1-skeleton of a simplicial complex (or its graph) consists of its elements of dimension lower than 2.
-*\image html "ds_representation.png" "Skeleton-blocker representation" width=20cm
+ *\image html "ds_representation.png" "Skeleton-blocker representation" width=20cm
To encode, a simplicial complex, one can encodes all its simplices.
@@ -85,7 +86,7 @@ in next figure. Storing the graph and blockers of such simplicial complexes is m
their simplices.
-*\image html "blockers_curve.png" "Number of blockers of random triangulations of 3-spheres" width=10cm
+ *\image html "blockers_curve.png" "Number of blockers of random triangulations of 3-spheres" width=10cm
@@ -107,7 +108,7 @@ and point access in addition.
-\subsection Visitor
+\subsection skblvisitor Visitor
The class Skeleton_blocker_complex has a visitor that is called when usual operations such as adding an edge or remove a vertex are called.
You may want to use this visitor to compute statistics or to update another data-structure (for instance this visitor is heavily used in the \ref contr package).
@@ -115,7 +116,7 @@ You may want to use this visitor to compute statistics or to update another data
-\section Example
+\section skblexample Example
\subsection Iterating Iterating through vertices, edges, blockers and simplices
@@ -127,46 +128,46 @@ such as the Simplex Tree. The following example computes the Euler Characteristi
of a simplicial complex.
\code{.cpp}
- typedef Skeleton_blocker_complex<Skeleton_blocker_simple_traits> Complex;
- typedef Complex::Vertex_handle Vertex_handle;
- typedef Complex::Simplex Simplex;
-
- const int n = 15;
-
- // build a full complex with 10 vertices and 2^n-1 simplices
- Complex complex;
- for(int i=0;i<n;i++)
- complex.add_vertex();
- for(int i=0;i<n;i++)
- for(int j=0;j<i;j++)
- complex.add_edge_without_blockers(Vertex_handle(i),Vertex_handle(j));
-
- // this is just to illustrate iterators, to count number of vertices
- // or edges, complex.num_vertices() and complex.num_edges() are
- // more appropriated!
- unsigned num_vertices = 0;
- for(auto v : complex.vertex_range()){
- ++num_vertices;
- }
-
- unsigned num_edges = 0;
- for(auto e : complex.edge_range())
- ++num_edges;
-
- unsigned euler = 0;
- unsigned num_simplices = 0;
- // we use a reference to a simplex instead of a copy
- // value here because a simplex is a set of integers
- // and copying it cost time
- for(const Simplex & s : complex.star_simplex_range()){
- ++num_simplices;
- if(s.dimension()%2 == 0)
- euler += 1;
- else
- euler -= 1;
- }
- std::cout << "Saw "<<num_vertices<<" vertices, "<<num_edges<<" edges and "<<num_simplices<<" simplices"<<std::endl;
- std::cout << "The Euler Characteristic is "<<euler<<std::endl;
+ typedef Skeleton_blocker_complex<Skeleton_blocker_simple_traits> Complex;
+ typedef Complex::Vertex_handle Vertex_handle;
+ typedef Complex::Simplex Simplex;
+
+ const int n = 15;
+
+ // build a full complex with 10 vertices and 2^n-1 simplices
+ Complex complex;
+ for(int i=0;i<n;i++)
+ complex.add_vertex();
+ for(int i=0;i<n;i++)
+ for(int j=0;j<i;j++)
+ complex.add_edge_without_blockers(Vertex_handle(i),Vertex_handle(j));
+
+ // this is just to illustrate iterators, to count number of vertices
+ // or edges, complex.num_vertices() and complex.num_edges() are
+ // more appropriated!
+ unsigned num_vertices = 0;
+ for(auto v : complex.vertex_range()){
+ ++num_vertices;
+ }
+
+ unsigned num_edges = 0;
+ for(auto e : complex.edge_range())
+ ++num_edges;
+
+ unsigned euler = 0;
+ unsigned num_simplices = 0;
+ // we use a reference to a simplex instead of a copy
+ // value here because a simplex is a set of integers
+ // and copying it cost time
+ for(const Simplex & s : complex.star_simplex_range()){
+ ++num_simplices;
+ if(s.dimension()%2 == 0)
+ euler += 1;
+ else
+ euler -= 1;
+ }
+ std::cout << "Saw "<<num_vertices<<" vertices, "<<num_edges<<" edges and "<<num_simplices<<" simplices"<<std::endl;
+ std::cout << "The Euler Characteristic is "<<euler<<std::endl;
\endcode
@@ -181,43 +182,43 @@ The Euler Characteristic is 1
\subsection s Constructing a skeleton-blockers from a list of maximal faces or from a list of faces
\code{.cpp}
- std::vector<Simplex> simplices;
-
- //add 4 triangles of a tetrahedron 0123
- simplices.push_back(Simplex(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2)));
- simplices.push_back(Simplex(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3)));
- simplices.push_back(Simplex(Vertex_handle(3),Vertex_handle(0),Vertex_handle(2)));
- simplices.push_back(Simplex(Vertex_handle(3),Vertex_handle(0),Vertex_handle(1)));
-
- Complex complex;
- //get complex from top faces
- make_complex_from_top_faces(complex,simplices.begin(),simplices.end());
-
- std::cout << "Simplices:"<<std::endl;
- for(const Simplex & s : complex.star_simplex_range())
- std::cout << s << " ";
- std::cout << std::endl;
-
- //One blocker as simplex 0123 is not in the complex but all its proper faces are.
- std::cout << "Blockers: "<<complex.blockers_to_string()<<std::endl;
-
- //now build a complex from its full list of simplices
- simplices.clear();
- simplices.push_back(Simplex(Vertex_handle(0)));
- simplices.push_back(Simplex(Vertex_handle(1)));
- simplices.push_back(Simplex(Vertex_handle(2)));
- simplices.push_back(Simplex(Vertex_handle(0),Vertex_handle(1)));
- simplices.push_back(Simplex(Vertex_handle(1),Vertex_handle(2)));
- simplices.push_back(Simplex(Vertex_handle(2),Vertex_handle(0)));
- complex = Complex(simplices.begin(),simplices.end());
-
- std::cout << "Simplices:"<<std::endl;
- for(const Simplex & s : complex.star_simplex_range())
- std::cout << s << " ";
- std::cout << std::endl;
-
- //One blocker as simplex 012 is not in the complex but all its proper faces are.
- std::cout << "Blockers: "<<complex.blockers_to_string()<<std::endl;
+ std::vector<Simplex> simplices;
+
+ //add 4 triangles of a tetrahedron 0123
+ simplices.push_back(Simplex(Vertex_handle(0),Vertex_handle(1),Vertex_handle(2)));
+ simplices.push_back(Simplex(Vertex_handle(1),Vertex_handle(2),Vertex_handle(3)));
+ simplices.push_back(Simplex(Vertex_handle(3),Vertex_handle(0),Vertex_handle(2)));
+ simplices.push_back(Simplex(Vertex_handle(3),Vertex_handle(0),Vertex_handle(1)));
+
+ Complex complex;
+ //get complex from top faces
+ make_complex_from_top_faces(complex,simplices.begin(),simplices.end());
+
+ std::cout << "Simplices:"<<std::endl;
+ for(const Simplex & s : complex.star_simplex_range())
+ std::cout << s << " ";
+ std::cout << std::endl;
+
+ //One blocker as simplex 0123 is not in the complex but all its proper faces are.
+ std::cout << "Blockers: "<<complex.blockers_to_string()<<std::endl;
+
+ //now build a complex from its full list of simplices
+ simplices.clear();
+ simplices.push_back(Simplex(Vertex_handle(0)));
+ simplices.push_back(Simplex(Vertex_handle(1)));
+ simplices.push_back(Simplex(Vertex_handle(2)));
+ simplices.push_back(Simplex(Vertex_handle(0),Vertex_handle(1)));
+ simplices.push_back(Simplex(Vertex_handle(1),Vertex_handle(2)));
+ simplices.push_back(Simplex(Vertex_handle(2),Vertex_handle(0)));
+ complex = Complex(simplices.begin(),simplices.end());
+
+ std::cout << "Simplices:"<<std::endl;
+ for(const Simplex & s : complex.star_simplex_range())
+ std::cout << s << " ";
+ std::cout << std::endl;
+
+ //One blocker as simplex 012 is not in the complex but all its proper faces are.
+ std::cout << "Blockers: "<<complex.blockers_to_string()<<std::endl;
\endcode
\verbatim
./SkeletonBlockerFromSimplices
@@ -236,12 +237,12 @@ The author wishes to thank Dominique Attali and André Lieutier for
their collaboration to write the two initial papers
\cite socg_blockers_2011,\cite blockers2012
about this data-structure
- and also Dominique for leaving him use a prototype.
+ and also Dominique for leaving him use a prototype.
-\copyright GNU General Public License v3.
-*/
-/** @} */ // end defgroup
+\copyright GNU General Public License v3.
+
+@} */
} // namespace skeleton_blocker
diff --git a/include/gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h b/include/gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h
index 32f40a4b..ba3636bc 100644
--- a/include/gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h
+++ b/include/gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_SKELETON_BLOCKER_COMPLEX_VISITOR_H_
#define SKELETON_BLOCKER_SKELETON_BLOCKER_COMPLEX_VISITOR_H_
@@ -27,7 +28,7 @@
namespace Gudhi {
namespace skeleton_blocker {
-// todo rajouter les const
+// TODO(DS): to be constified
/**
*@class Skeleton_blocker_complex_visitor
@@ -36,7 +37,7 @@ namespace skeleton_blocker {
template<typename Vertex_handle>
class Skeleton_blocker_complex_visitor {
public:
- virtual ~Skeleton_blocker_complex_visitor() {}
+ virtual ~Skeleton_blocker_complex_visitor() { }
virtual void on_add_vertex(Vertex_handle) = 0;
virtual void on_remove_vertex(Vertex_handle) = 0;
@@ -61,9 +62,9 @@ class Skeleton_blocker_complex_visitor {
virtual void on_swaped_edge(Vertex_handle a, Vertex_handle b,
Vertex_handle x) = 0;
virtual void on_add_blocker(
- const Skeleton_blocker_simplex<Vertex_handle>&) = 0;
+ const Skeleton_blocker_simplex<Vertex_handle>&) = 0;
virtual void on_delete_blocker(
- const Skeleton_blocker_simplex<Vertex_handle>*) = 0;
+ const Skeleton_blocker_simplex<Vertex_handle>*) = 0;
};
/**
@@ -73,24 +74,23 @@ class Skeleton_blocker_complex_visitor {
*/
template<typename Vertex_handle>
class Dummy_complex_visitor : public Skeleton_blocker_complex_visitor<
- Vertex_handle> {
+Vertex_handle> {
public:
- void on_add_vertex(Vertex_handle) {
- }
- void on_remove_vertex(Vertex_handle) {
- }
- void on_add_edge_without_blockers(Vertex_handle a, Vertex_handle b) {
- }
- void on_remove_edge(Vertex_handle a, Vertex_handle b) {
- }
- void on_changed_edge(Vertex_handle a, Vertex_handle b) {
- }
- void on_swaped_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x) {
- }
- void on_add_blocker(const Skeleton_blocker_simplex<Vertex_handle>&) {
- }
- void on_delete_blocker(const Skeleton_blocker_simplex<Vertex_handle>*) {
- }
+ void on_add_vertex(Vertex_handle) { }
+
+ void on_remove_vertex(Vertex_handle) { }
+
+ void on_add_edge_without_blockers(Vertex_handle a, Vertex_handle b) { }
+
+ void on_remove_edge(Vertex_handle a, Vertex_handle b) { }
+
+ void on_changed_edge(Vertex_handle a, Vertex_handle b) { }
+
+ void on_swaped_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x) { }
+
+ void on_add_blocker(const Skeleton_blocker_simplex<Vertex_handle>&) { }
+
+ void on_delete_blocker(const Skeleton_blocker_simplex<Vertex_handle>*) { }
};
/**
@@ -100,29 +100,36 @@ class Dummy_complex_visitor : public Skeleton_blocker_complex_visitor<
*/
template<typename Vertex_handle>
class Print_complex_visitor : public Skeleton_blocker_complex_visitor<
- Vertex_handle> {
+Vertex_handle> {
public:
void on_add_vertex(Vertex_handle v) {
std::cerr << "on_add_vertex:" << v << std::endl;
}
+
void on_remove_vertex(Vertex_handle v) {
std::cerr << "on_remove_vertex:" << v << std::endl;
}
+
void on_add_edge_without_blockers(Vertex_handle a, Vertex_handle b) {
std::cerr << "on_add_edge_without_blockers:" << a << "," << b << std::endl;
}
+
void on_remove_edge(Vertex_handle a, Vertex_handle b) {
std::cerr << "on_remove_edge:" << a << "," << b << std::endl;
}
+
void on_changed_edge(Vertex_handle a, Vertex_handle b) {
std::cerr << "on_changed_edge:" << a << "," << b << std::endl;
}
+
void on_swaped_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x) {
std::cerr << "on_swaped_edge:" << a << "," << b << "," << x << std::endl;
}
+
void on_add_blocker(const Skeleton_blocker_simplex<Vertex_handle>& b) {
std::cerr << "on_add_blocker:" << b << std::endl;
}
+
void on_delete_blocker(const Skeleton_blocker_simplex<Vertex_handle>* b) {
std::cerr << "on_delete_blocker:" << b << std::endl;
}
diff --git a/include/gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h b/include/gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h
index 3bfb5d11..d4b60613 100644
--- a/include/gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h
+++ b/include/gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_SKELETON_BLOCKER_LINK_SUPERIOR_H_
#define SKELETON_BLOCKER_SKELETON_BLOCKER_LINK_SUPERIOR_H_
@@ -36,7 +37,7 @@ template<class ComplexType> class Skeleton_blocker_sub_complex;
*/
template<typename ComplexType>
class Skeleton_blocker_link_superior : public Skeleton_blocker_link_complex<
- ComplexType> {
+ComplexType> {
typedef typename ComplexType::Edge_handle Edge_handle;
typedef typename ComplexType::boost_vertex_handle boost_vertex_handle;
@@ -54,20 +55,17 @@ class Skeleton_blocker_link_superior : public Skeleton_blocker_link_complex<
typedef typename ComplexType::Root_simplex_handle::Simplex_vertex_const_iterator IdSimplexConstIterator;
Skeleton_blocker_link_superior()
- : Skeleton_blocker_link_complex<ComplexType>(true) {
- }
+ : Skeleton_blocker_link_complex<ComplexType>(true) { }
Skeleton_blocker_link_superior(const ComplexType & parent_complex,
Simplex& alpha_parent_adress)
: Skeleton_blocker_link_complex<ComplexType>(parent_complex,
- alpha_parent_adress, true) {
- }
+ alpha_parent_adress, true) { }
Skeleton_blocker_link_superior(const ComplexType & parent_complex,
Vertex_handle a_parent_adress)
: Skeleton_blocker_link_complex<ComplexType>(parent_complex,
- a_parent_adress, true) {
- }
+ a_parent_adress, true) { }
};
} // namespace skeleton_blocker
diff --git a/include/gudhi/Skeleton_blocker/Skeleton_blocker_off_io.h b/include/gudhi/Skeleton_blocker/Skeleton_blocker_off_io.h
index ba46c49e..747e60f1 100644
--- a/include/gudhi/Skeleton_blocker/Skeleton_blocker_off_io.h
+++ b/include/gudhi/Skeleton_blocker/Skeleton_blocker_off_io.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_SKELETON_BLOCKER_OFF_IO_H_
#define SKELETON_BLOCKER_SKELETON_BLOCKER_OFF_IO_H_
@@ -49,8 +50,8 @@ class Skeleton_blocker_off_flag_visitor_reader {
load_only_points_(load_only_points) { }
void init(int dim, int num_vertices, int num_faces, int num_edges) {
- // todo do an assert to check that this number are correctly read
- // todo reserve size for vector points
+ // TODO(DS): do an assert to check that this number are correctly read
+ // TODO(DS): reserve size for vector points
}
void point(const std::vector<double>& point) {
@@ -108,7 +109,7 @@ class Skeleton_blocker_off_visitor_reader {
void done() {
complex_ = make_complex_from_top_faces<Complex>(maximal_faces_.begin(), maximal_faces_.end(),
- points_.begin(), points_.end() );
+ points_.begin(), points_.end());
}
};
@@ -140,7 +141,7 @@ class Skeleton_blocker_off_reader {
}
/**
- * return true iff reading did not meet problems.
+ * return true if reading did not meet problems.
*/
bool is_valid() const {
return valid_;
diff --git a/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h b/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h
index fb4a1106..275376e6 100644
--- a/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h
+++ b/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_geometric_traits.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_SKELETON_BLOCKER_SIMPLE_GEOMETRIC_TRAITS_H_
#define SKELETON_BLOCKER_SKELETON_BLOCKER_SIMPLE_GEOMETRIC_TRAITS_H_
@@ -39,7 +40,7 @@ namespace skeleton_blocker {
*/
template<typename GeometryTrait>
struct Skeleton_blocker_simple_geometric_traits :
- public Skeleton_blocker_simple_traits {
+public Skeleton_blocker_simple_traits {
public:
typedef GeometryTrait GT;
typedef typename GT::Point Point;
@@ -57,19 +58,20 @@ struct Skeleton_blocker_simple_geometric_traits :
Point& point() {
return point_;
}
+
const Point& point() const {
return point_;
}
};
class Simple_geometric_edge :
- public Skeleton_blocker_simple_traits::Graph_edge {
+ public Skeleton_blocker_simple_traits::Graph_edge {
int index_;
public:
Simple_geometric_edge()
: Skeleton_blocker_simple_traits::Graph_edge(),
- index_(-1) {
- }
+ index_(-1) { }
+
/**
* @brief Allows to modify the index of the edge.
* The indices of the edge are used to store heap information
@@ -78,6 +80,7 @@ struct Skeleton_blocker_simple_geometric_traits :
int& index() {
return index_;
}
+
int index() const {
return index_;
}
diff --git a/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h b/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h
index 31bec3b6..3835cf77 100644
--- a/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h
+++ b/include/gudhi/Skeleton_blocker/Skeleton_blocker_simple_traits.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_SKELETON_BLOCKER_SIMPLE_TRAITS_H_
#define SKELETON_BLOCKER_SKELETON_BLOCKER_SIMPLE_TRAITS_H_
@@ -48,9 +49,9 @@ struct Skeleton_blocker_simple_traits {
*/
struct Root_vertex_handle {
typedef int boost_vertex_handle;
+
explicit Root_vertex_handle(boost_vertex_handle val = -1)
- : vertex(val) {
- }
+ : vertex(val) { }
boost_vertex_handle vertex;
bool operator!=(const Root_vertex_handle& other) const {
@@ -65,8 +66,8 @@ struct Skeleton_blocker_simple_traits {
return this->vertex < other.vertex;
}
- friend std::ostream& operator <<(std::ostream& o,
- const Root_vertex_handle & v) {
+ friend std::ostream& operator<<(std::ostream& o,
+ const Root_vertex_handle & v) {
o << v.vertex;
return o;
}
@@ -74,11 +75,13 @@ struct Skeleton_blocker_simple_traits {
struct Vertex_handle {
typedef int boost_vertex_handle;
+
explicit Vertex_handle(boost_vertex_handle val = -1)
- : vertex(val) {
- }
+ : vertex(val) { }
- operator int() const { return static_cast<int>(vertex); }
+ operator int() const {
+ return static_cast<int> (vertex);
+ }
boost_vertex_handle vertex;
@@ -94,7 +97,7 @@ struct Skeleton_blocker_simple_traits {
return this->vertex < other.vertex;
}
- friend std::ostream& operator <<(std::ostream& o, const Vertex_handle & v) {
+ friend std::ostream& operator<<(std::ostream& o, const Vertex_handle & v) {
o << v.vertex;
return o;
}
@@ -105,21 +108,24 @@ struct Skeleton_blocker_simple_traits {
Root_vertex_handle id_;
public:
- virtual ~Graph_vertex() {
- }
+ virtual ~Graph_vertex() { }
void activate() {
is_active_ = true;
}
+
void deactivate() {
is_active_ = false;
}
+
bool is_active() const {
return is_active_;
}
+
void set_id(Root_vertex_handle i) {
id_ = i;
}
+
Root_vertex_handle get_id() const {
return id_;
}
@@ -130,7 +136,7 @@ struct Skeleton_blocker_simple_traits {
return res.str();
}
- friend std::ostream& operator <<(std::ostream& o, const Graph_vertex & v) {
+ friend std::ostream& operator<<(std::ostream& o, const Graph_vertex & v) {
o << v.to_string();
return o;
}
@@ -144,13 +150,13 @@ struct Skeleton_blocker_simple_traits {
public:
Graph_edge()
: a_(-1),
- b_(-1),
- index_(-1) {
- }
+ b_(-1),
+ index_(-1) { }
int& index() {
return index_;
}
+
int index() const {
return index_;
}
@@ -168,7 +174,7 @@ struct Skeleton_blocker_simple_traits {
return b_;
}
- friend std::ostream& operator <<(std::ostream& o, const Graph_edge & v) {
+ friend std::ostream& operator<<(std::ostream& o, const Graph_edge & v) {
o << "(" << v.a_ << "," << v.b_ << " - id = " << v.index();
return o;
}
diff --git a/include/gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h b/include/gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h
index 3c7f1dd5..aa6f2215 100644
--- a/include/gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h
+++ b/include/gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -63,7 +63,6 @@ class Skeleton_blocker_simplex {
*/
//@{
- // Skeleton_blocker_simplex():simplex_set() {}
void clear() {
simplex_set.clear();
}
@@ -89,8 +88,7 @@ class Skeleton_blocker_simplex {
add_vertex(v);
}
- void add_vertices() {
- }
+ void add_vertices() { }
/**
* Initialize a simplex with a string such as {0,1,2}
@@ -192,7 +190,6 @@ class Skeleton_blocker_simplex {
return simplex_set.crend();
}
-
typename std::set<T>::iterator begin() {
return simplex_set.begin();
}
@@ -236,6 +233,7 @@ class Skeleton_blocker_simplex {
assert(!empty());
return *(simplex_set.rbegin());
}
+
/**
* @return true iff the simplex contains the simplex a.
*/
@@ -351,8 +349,8 @@ class Skeleton_blocker_simplex {
//@}
- friend std::ostream& operator <<(std::ostream& o,
- const Skeleton_blocker_simplex & sigma) {
+ friend std::ostream& operator<<(std::ostream& o,
+ const Skeleton_blocker_simplex & sigma) {
bool first = true;
o << "{";
for (auto i : sigma) {
diff --git a/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h b/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h
index 196fe8c0..fadf6619 100644
--- a/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h
+++ b/include/gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -159,7 +159,7 @@ class Skeleton_blocker_sub_complex : public ComplexType {
if (simplex.contains(*blocker)) {
Root_simplex_handle blocker_root(parent_complex.get_id(*(blocker)));
Simplex blocker_restr(
- *(this->get_simplex_address(blocker_root)));
+ *(this->get_simplex_address(blocker_root)));
this->add_blocker(new Simplex(blocker_restr));
}
}
@@ -190,14 +190,15 @@ class Skeleton_blocker_sub_complex : public ComplexType {
// */
// boost::optional<Simplex> get_address(const Root_simplex_handle & s) const;
-// private:
+ // private:
/**
* same as get_address except that it will return a simplex in any case.
* The vertices that were not found are not added.
*/
// @remark should be private but problem with VS
+
std::vector<boost::optional<Vertex_handle> > get_addresses(
- const Root_simplex_handle & s) const {
+ const Root_simplex_handle & s) const {
std::vector < boost::optional<Vertex_handle> > res;
for (auto i : s) {
res.push_back(get_address(i));
@@ -214,14 +215,14 @@ class Skeleton_blocker_sub_complex : public ComplexType {
*/
template<typename ComplexType>
bool proper_face_in_union(
- Skeleton_blocker_sub_complex<ComplexType> & link,
- std::vector<boost::optional<typename ComplexType::Vertex_handle> > & addresses_sigma_in_link,
- int vertex_to_be_ignored) {
+ Skeleton_blocker_sub_complex<ComplexType> & link,
+ std::vector<boost::optional<typename ComplexType::Vertex_handle> > & addresses_sigma_in_link,
+ std::size_t vertex_to_be_ignored) {
// we test that all vertices of 'addresses_sigma_in_link' but 'vertex_to_be_ignored'
// are in link1 if it is the case we construct the corresponding simplex
bool vertices_sigma_are_in_link = true;
typename ComplexType::Simplex sigma_in_link;
- for (int i = 0; i < addresses_sigma_in_link.size(); ++i) {
+ for (std::size_t i = 0; i < addresses_sigma_in_link.size(); ++i) {
if (i != vertex_to_be_ignored) {
if (!addresses_sigma_in_link[i]) {
vertices_sigma_are_in_link = false;
@@ -236,43 +237,24 @@ bool proper_face_in_union(
return vertices_sigma_are_in_link && link.contains(sigma_in_link);
}
-/*
- template<typename ComplexType>
- bool
- proper_faces_in_union(Skeleton_blocker_simplex<typename ComplexType::Root_vertex_handle> & sigma, Skeleton_blocker_sub_complex<ComplexType> & link1, Skeleton_blocker_sub_complex<ComplexType> & link2)
- {
- typedef typename ComplexType::Vertex_handle Vertex_handle;
- std::vector<boost::optional<Vertex_handle> > addresses_sigma_in_link1 = link1.get_addresses(sigma);
- std::vector<boost::optional<Vertex_handle> > addresses_sigma_in_link2 = link2.get_addresses(sigma);
-
- for (int current_index = 0; current_index < addresses_sigma_in_link1.size(); ++current_index)
- {
-
- if (!proper_face_in_union(link1, addresses_sigma_in_link1, current_index)
- && !proper_face_in_union(link2, addresses_sigma_in_link2, current_index)){
- return false;
- }
- }
- return true;
- }*/
-
// Remark: this function should be friend in order to leave get_adresses private
// however doing so seemes currently not possible due to a visual studio bug c2668
// "the compiler does not support partial ordering of template functions as specified in the C++ Standard"
// http://www.serkey.com/error-c2668-ambiguous-call-to-overloaded-function-bb45ft.html
+
template<typename ComplexType>
bool proper_faces_in_union(
- Skeleton_blocker_simplex<typename ComplexType::Root_vertex_handle> & sigma,
- Skeleton_blocker_sub_complex<ComplexType> & link1,
- Skeleton_blocker_sub_complex<ComplexType> & link2) {
+ Skeleton_blocker_simplex<typename ComplexType::Root_vertex_handle> & sigma,
+ Skeleton_blocker_sub_complex<ComplexType> & link1,
+ Skeleton_blocker_sub_complex<ComplexType> & link2) {
typedef typename ComplexType::Vertex_handle Vertex_handle;
std::vector < boost::optional<Vertex_handle> > addresses_sigma_in_link1 =
link1.get_addresses(sigma);
std::vector < boost::optional<Vertex_handle> > addresses_sigma_in_link2 =
link2.get_addresses(sigma);
- for (int current_index = 0; current_index < addresses_sigma_in_link1.size();
- ++current_index) {
+ for (std::size_t current_index = 0; current_index < addresses_sigma_in_link1.size();
+ ++current_index) {
if (!proper_face_in_union(link1, addresses_sigma_in_link1, current_index)
&& !proper_face_in_union(link2, addresses_sigma_in_link2,
current_index)) {
@@ -289,4 +271,3 @@ namespace skbl = skeleton_blocker;
} // namespace Gudhi
#endif // SKELETON_BLOCKER_SKELETON_BLOCKER_SUB_COMPLEX_H_
-
diff --git a/include/gudhi/Skeleton_blocker/internal/Top_faces.h b/include/gudhi/Skeleton_blocker/internal/Top_faces.h
index 39d95661..2b681752 100644
--- a/include/gudhi/Skeleton_blocker/internal/Top_faces.h
+++ b/include/gudhi/Skeleton_blocker/internal/Top_faces.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_INTERNAL_TOP_FACES_H_
#define SKELETON_BLOCKER_INTERNAL_TOP_FACES_H_
@@ -69,4 +70,4 @@ namespace skbl = skeleton_blocker;
} // namespace Gudhi
-#endif // SKELETON_BLOCKER_INTERNAL_TOP_FACES_H_
+#endif // SKELETON_BLOCKER_INTERNAL_TOP_FACES_H_
diff --git a/include/gudhi/Skeleton_blocker/internal/Trie.h b/include/gudhi/Skeleton_blocker/internal/Trie.h
index cdc47b8a..2c9602fa 100644
--- a/include/gudhi/Skeleton_blocker/internal/Trie.h
+++ b/include/gudhi/Skeleton_blocker/internal/Trie.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,7 +21,6 @@
*
*/
-
#ifndef SKELETON_BLOCKER_INTERNAL_TRIE_H_
#define SKELETON_BLOCKER_INTERNAL_TRIE_H_
@@ -148,7 +147,7 @@ struct Trie {
}
void remove_leaf() {
- assert(is_leaf);
+ assert(is_leaf());
if (!is_root())
parent_->childs.erase(this);
}
@@ -240,7 +239,7 @@ struct Tries {
std::vector<Simplex> next_dimension_simplices() const {
std::vector<Simplex> res;
- while (!to_see_.empty() && to_see_.front()->simplex().dimension() == current_dimension_) {
+ while (!(to_see_.empty()) && (to_see_.front()->simplex().dimension() == current_dimension_)) {
res.emplace_back(to_see_.front()->simplex());
for (auto child : to_see_.front()->childs)
to_see_.push_back(child.get());
@@ -257,7 +256,7 @@ struct Tries {
private:
mutable std::deque<STrie*> to_see_;
- mutable unsigned current_dimension_ = 0;
+ mutable int current_dimension_ = 0;
std::vector<STrie*> cofaces_;
};
diff --git a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_blockers_iterators.h b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_blockers_iterators.h
index 4dbc9ed3..d2fff960 100644
--- a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_blockers_iterators.h
+++ b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_blockers_iterators.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_BLOCKERS_ITERATORS_H_
#define SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_BLOCKERS_ITERATORS_H_
diff --git a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_edges_iterators.h b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_edges_iterators.h
index 15618932..b90dcf34 100644
--- a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_edges_iterators.h
+++ b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_edges_iterators.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_EDGES_ITERATORS_H_
#define SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_EDGES_ITERATORS_H_
diff --git a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h
index cc3ed276..1351614f 100644
--- a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h
+++ b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h
index 3b941be5..2acdb555 100644
--- a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h
+++ b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_simplices_iterators.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
#define SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
@@ -68,10 +69,11 @@ public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerCo
Vertex_handle v;
std::shared_ptr<Link> link_v;
std::shared_ptr<Trie> trie;
- std::list<Trie*> nodes_to_be_seen; // todo deque
+ // TODO(DS): use a deque instead
+ std::list<Trie*> nodes_to_be_seen;
public:
- Simplex_around_vertex_iterator() : complex(0) {}
+ Simplex_around_vertex_iterator() : complex(0) { }
Simplex_around_vertex_iterator(const Complex* complex_, Vertex_handle v_) :
complex(complex_),
@@ -81,15 +83,16 @@ public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerCo
compute_trie_and_nodes_to_be_seen();
}
- // todo avoid useless copy
- // todo currently just work if copy begin iterator
+ // TODO(DS): avoid useless copy
+ // TODO(DS): currently just work if copy begin iterator
Simplex_around_vertex_iterator(const Simplex_around_vertex_iterator& other) :
complex(other.complex),
v(other.v),
link_v(other.link_v),
trie(other.trie),
nodes_to_be_seen(other.nodes_to_be_seen) {
- if (!other.is_end()) {}
+ if (!other.is_end()) {
+ }
}
/**
@@ -159,7 +162,8 @@ public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerCo
bool both_non_empty = !nodes_to_be_seen.empty() && !other.nodes_to_be_seen.empty();
- if (!both_non_empty) return false; // one is empty the other is not
+ // one is empty the other is not
+ if (!both_non_empty) return false;
bool same_node = (**(nodes_to_be_seen.begin()) == **(other.nodes_to_be_seen.begin()));
return same_node;
@@ -238,7 +242,6 @@ public boost::iterator_facade < Simplex_iterator<SkeletonBlockerComplex>
}
private:
- // todo return to private
Simplex_iterator(const Complex* complex, bool end) :
complex_(complex) {
set_end();
@@ -306,7 +309,7 @@ public boost::iterator_facade < Simplex_iterator<SkeletonBlockerComplex>
/**
* Iterator through the maximal faces of the coboundary of a simplex.
- */
+ */
template<typename SkeletonBlockerComplex, typename Link>
class Simplex_coboundary_iterator :
public boost::iterator_facade < Simplex_coboundary_iterator<SkeletonBlockerComplex, Link>
@@ -329,12 +332,12 @@ public boost::iterator_facade < Simplex_coboundary_iterator<SkeletonBlockerCompl
Complex_vertex_iterator link_vertex_end;
public:
- Simplex_coboundary_iterator() : complex(0) {}
+ Simplex_coboundary_iterator() : complex(0) { }
Simplex_coboundary_iterator(const Complex* complex_, const Simplex& sigma_) :
complex(complex_),
sigma(sigma_),
- //need only vertices of the link hence the true flag
+ // need only vertices of the link hence the true flag
link(new Link(*complex_, sigma_, false, true)) {
auto link_vertex_range = link->vertex_range();
current_vertex = link_vertex_range.begin();
@@ -347,9 +350,9 @@ public boost::iterator_facade < Simplex_coboundary_iterator<SkeletonBlockerCompl
link(other.link),
current_vertex(other.current_vertex),
link_vertex_end(other.link_vertex_end) { }
-
+
// returns an iterator to the end
- Simplex_coboundary_iterator(const Complex* complex_,const Simplex& sigma_, bool end) :
+ Simplex_coboundary_iterator(const Complex* complex_, const Simplex& sigma_, bool end) :
complex(complex_),
sigma(sigma_) {
// to represent an end iterator without having to build a useless link, we use
@@ -361,7 +364,7 @@ public boost::iterator_facade < Simplex_coboundary_iterator<SkeletonBlockerCompl
return complex->convert_handle_from_another_complex(*link, link_vh);
}
-public:
+ public:
friend std::ostream& operator<<(std::ostream& stream, const Simplex_coboundary_iterator& sci) {
return stream;
}
@@ -369,8 +372,8 @@ public:
// assume that iterator points to the same complex and comes from the same simplex
bool equal(const Simplex_coboundary_iterator& other) const {
assert(complex == other.complex && sigma == other.sigma);
- if(is_end()) return other.is_end();
- if(other.is_end()) return is_end();
+ if (is_end()) return other.is_end();
+ if (other.is_end()) return is_end();
return *current_vertex == *(other.current_vertex);
}
@@ -384,13 +387,12 @@ public:
return res;
}
-private:
+ private:
bool is_end() const {
return !link || current_vertex == link_vertex_end;
}
};
-
} // namespace skeleton_blocker
namespace skbl = skeleton_blocker;
diff --git a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_triangles_iterators.h b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_triangles_iterators.h
index b2dd9a21..736941dd 100644
--- a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_triangles_iterators.h
+++ b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_triangles_iterators.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_TRIANGLES_ITERATORS_H_
#define SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_TRIANGLES_ITERATORS_H_
@@ -135,7 +136,7 @@ typename SkeletonBlockerComplex::Simplex const
Triangle_iterator(const SkeletonBlockerComplex* complex) :
complex_(complex),
current_vertex_(complex->vertex_range().begin()),
- current_triangle_(complex, *current_vertex_), // xxx this line is problematic is the complex is empty
+ current_triangle_(complex, *current_vertex_), // this line is problematic is the complex is empty
is_end_(false) {
assert(!complex->empty());
gotoFirstTriangle();
@@ -172,7 +173,8 @@ typename SkeletonBlockerComplex::Simplex const
bool both_arent_finished = !is_finished() && !other.is_finished();
// if the two iterators are not finished, they must have the same state
return (complex_ == other.complex_) && (both_are_finished || ((both_arent_finished) &&
- current_vertex_ == other.current_vertex_ && current_triangle_ == other.current_triangle_));
+ current_vertex_ == other.current_vertex_ &&
+ current_triangle_ == other.current_triangle_));
}
Simplex dereference() const {
@@ -183,8 +185,10 @@ typename SkeletonBlockerComplex::Simplex const
// goto the next vertex that has a triangle pending or the
// end vertex iterator if none exists
void goto_next_vertex() {
- assert(current_triangle_.finished()); // we mush have consume all triangles passing through the vertex
- assert(!is_finished()); // we must not be done
+ // we must have consume all triangles passing through the vertex
+ assert(current_triangle_.finished());
+ // we must not be done
+ assert(!is_finished());
++current_vertex_;
diff --git a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_vertices_iterators.h b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_vertices_iterators.h
index f06cab71..9e9ae961 100644
--- a/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_vertices_iterators.h
+++ b/include/gudhi/Skeleton_blocker/iterators/Skeleton_blockers_vertices_iterators.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_VERTICES_ITERATORS_H_
#define SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_VERTICES_ITERATORS_H_
@@ -103,7 +104,7 @@ class Vertex_iterator : public boost::iterator_facade< Vertex_iterator <Skeleton
};
template<typename SkeletonBlockerComplex>
-class Neighbors_vertices_iterator: public boost::iterator_facade < Neighbors_vertices_iterator<SkeletonBlockerComplex>
+class Neighbors_vertices_iterator : public boost::iterator_facade < Neighbors_vertices_iterator<SkeletonBlockerComplex>
, typename SkeletonBlockerComplex::Vertex_handle const
, boost::forward_traversal_tag
, typename SkeletonBlockerComplex::Vertex_handle const> {
@@ -122,9 +123,6 @@ class Neighbors_vertices_iterator: public boost::iterator_facade < Neighbors_ver
boost_adjacency_iterator end_;
public:
- // boost_adjacency_iterator ai, ai_end;
- // for (tie(ai, ai_end) = adjacent_vertices(v.vertex, skeleton); ai != ai_end; ++ai) {
-
Neighbors_vertices_iterator() : complex(NULL) { }
Neighbors_vertices_iterator(const Complex* complex_, Vertex_handle v_) :
@@ -157,7 +155,7 @@ class Neighbors_vertices_iterator: public boost::iterator_facade < Neighbors_ver
}
private:
- // todo remove this ugly hack
+ // TODO(DS): remove this ugly hack
void set_end() {
current_ = end_;
}
@@ -170,5 +168,3 @@ namespace skbl = skeleton_blocker;
} // namespace Gudhi
#endif // SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_VERTICES_ITERATORS_H_
-
-
diff --git a/include/gudhi/Skeleton_blocker_complex.h b/include/gudhi/Skeleton_blocker_complex.h
index 7a6d1d50..4f052ba5 100644
--- a/include/gudhi/Skeleton_blocker_complex.h
+++ b/include/gudhi/Skeleton_blocker_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -211,7 +211,6 @@ class Skeleton_blocker_complex {
add_edge_without_blockers(e.first, e.second);
}
-
template<typename SimpleHandleOutputIterator>
void add_blockers(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end) {
Tries<Simplex> tries(num_vertices(), simplices_begin, simplices_end);
@@ -414,7 +413,8 @@ class Skeleton_blocker_complex {
/**
*/
bool contains_vertex(Vertex_handle u) const {
- if (u.vertex < 0 || u.vertex >= boost::num_vertices(skeleton))
+ Vertex_handle num_vertices(boost::num_vertices(skeleton));
+ if (u.vertex < 0 || u.vertex >= num_vertices)
return false;
return (*this)[u].is_active();
}
@@ -441,11 +441,11 @@ class Skeleton_blocker_complex {
* @brief Given an Id return the address of the vertex having this Id in the complex.
* @remark For a simplicial complex, the address is the id but it may not be the case for a SubComplex.
*/
- virtual boost::optional<Vertex_handle> get_address(
- Root_vertex_handle id) const {
+ virtual boost::optional<Vertex_handle> get_address(Root_vertex_handle id) const {
boost::optional<Vertex_handle> res;
- if (id.vertex < boost::num_vertices(skeleton))
- res = Vertex_handle(id.vertex); // xxx
+ int num_vertices = boost::num_vertices(skeleton);
+ if (id.vertex < num_vertices)
+ res = Vertex_handle(id.vertex);
return res;
}
@@ -560,7 +560,7 @@ class Skeleton_blocker_complex {
return res;
}
- /**
+ /**
* @brief Adds all edges of s in the complex.
*/
void add_edge(const Simplex& s) {
@@ -591,7 +591,6 @@ class Skeleton_blocker_complex {
return *edge_handle;
}
-
/**
* @brief Adds all edges of s in the complex without adding blockers.
*/
@@ -844,12 +843,13 @@ class Skeleton_blocker_complex {
boost_adjacency_iterator ai, ai_end;
for (tie(ai, ai_end) = adjacent_vertices(v.vertex, skeleton); ai != ai_end;
++ai) {
+ Vertex_handle value(*ai);
if (keep_only_superior) {
- if (*ai > v.vertex) {
- n.add_vertex(Vertex_handle(*ai));
+ if (value > v.vertex) {
+ n.add_vertex(value);
}
} else {
- n.add_vertex(Vertex_handle(*ai));
+ n.add_vertex(value);
}
}
}
@@ -929,7 +929,7 @@ class Skeleton_blocker_complex {
// xxx rename get_address et place un using dans sub_complex
boost::optional<Simplex> get_simplex_address(
- const Root_simplex_handle& s) const {
+ const Root_simplex_handle& s) const {
boost::optional<Simplex> res;
Simplex s_address;
@@ -1001,10 +1001,9 @@ class Skeleton_blocker_complex {
return std::distance(triangles.begin(), triangles.end());
}
-
/*
* @brief returns the number of simplices of a given dimension in the complex.
- */
+ */
size_t num_simplices() const {
auto simplices = complex_simplex_range();
return std::distance(simplices.begin(), simplices.end());
@@ -1012,8 +1011,8 @@ class Skeleton_blocker_complex {
/*
* @brief returns the number of simplices of a given dimension in the complex.
- */
- size_t num_simplices(unsigned dimension) const {
+ */
+ size_t num_simplices(int dimension) const {
// TODO(DS): iterator on k-simplices
size_t res = 0;
for (const auto& s : complex_simplex_range())
diff --git a/include/gudhi/Skeleton_blocker_geometric_complex.h b/include/gudhi/Skeleton_blocker_geometric_complex.h
index 1130ca9f..95331b7a 100644
--- a/include/gudhi/Skeleton_blocker_geometric_complex.h
+++ b/include/gudhi/Skeleton_blocker_geometric_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_GEOMETRIC_COMPLEX_H_
#define SKELETON_BLOCKER_GEOMETRIC_COMPLEX_H_
diff --git a/include/gudhi/Skeleton_blocker_link_complex.h b/include/gudhi/Skeleton_blocker_link_complex.h
index 1bd66289..4db075b0 100644
--- a/include/gudhi/Skeleton_blocker_link_complex.h
+++ b/include/gudhi/Skeleton_blocker_link_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_LINK_COMPLEX_H_
#define SKELETON_BLOCKER_LINK_COMPLEX_H_
@@ -39,7 +40,7 @@ template<class ComplexType> class Skeleton_blocker_sub_complex;
*/
template<typename ComplexType>
class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
- ComplexType> {
+ComplexType> {
template<typename T> friend class Skeleton_blocker_link_superior;
typedef typename ComplexType::Edge_handle Edge_handle;
@@ -60,8 +61,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
typedef typename ComplexType::Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_handle_iterator;
explicit Skeleton_blocker_link_complex(bool only_superior_vertices = false)
- : only_superior_vertices_(only_superior_vertices) {
- }
+ : only_superior_vertices_(only_superior_vertices) { }
/**
* If the parameter only_superior_vertices is true,
@@ -95,10 +95,10 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
*/
Skeleton_blocker_link_complex(const ComplexType & parent_complex,
Edge_handle edge, bool only_superior_vertices =
- false)
+ false)
: only_superior_vertices_(only_superior_vertices) {
Simplex alpha_simplex(parent_complex.first_vertex(edge),
- parent_complex.second_vertex(edge));
+ parent_complex.second_vertex(edge));
build_link(parent_complex, alpha_simplex);
}
@@ -151,7 +151,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
bool only_superior_vertices) {
// for a vertex we know exactly the number of vertices of the link (and the size of the corresponding vector
this->skeleton.m_vertices.reserve(
- parent_complex.degree(alpha_parent_adress));
+ parent_complex.degree(alpha_parent_adress));
// For all vertex 'v' in this intersection, we go through all its adjacent blockers.
// If one blocker minus 'v' is included in alpha then the vertex is not in the link complex.
@@ -169,21 +169,21 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
return;
for (auto x_link = this->vertex_range().begin();
- x_link != this->vertex_range().end(); ++x_link) {
+ x_link != this->vertex_range().end(); ++x_link) {
for (auto y_link = x_link; ++y_link != this->vertex_range().end();) {
Vertex_handle x_parent = *parent_complex.get_address(
- this->get_id(*x_link));
+ this->get_id(*x_link));
Vertex_handle y_parent = *parent_complex.get_address(
- this->get_id(*y_link));
+ this->get_id(*y_link));
if (parent_complex.contains_edge(x_parent, y_parent)) {
// we check that there is no blocker subset of alpha passing trough x and y
bool new_edge = true;
for (auto blocker_parent : parent_complex.const_blocker_range(
- x_parent)) {
+ x_parent)) {
if (!is_alpha_blocker || *blocker_parent != alpha_parent_adress) {
if (blocker_parent->contains(y_parent)) {
new_edge = !(alpha_parent_adress.contains_difference(
- *blocker_parent, x_parent, y_parent));
+ *blocker_parent, x_parent, y_parent));
if (!new_edge)
break;
}
@@ -201,8 +201,8 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
* corresponding address in 'other_complex'.
* It assumes that other_complex have a vertex 'this.get_id(address)'
*/
- boost::optional<Vertex_handle> give_equivalent_vertex(
- const ComplexType & other_complex, Vertex_handle address) const {
+ boost::optional<Vertex_handle> give_equivalent_vertex(const ComplexType & other_complex,
+ Vertex_handle address) const {
Root_vertex_handle id((*this)[address].get_id());
return other_complex.get_address(id);
}
@@ -269,7 +269,7 @@ class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
bool only_vertices = false) {
assert(is_alpha_blocker || parent_complex.contains(alpha_parent_adress));
compute_link_vertices(parent_complex, alpha_parent_adress, only_superior_vertices_);
- if(!only_vertices) {
+ if (!only_vertices) {
compute_link_edges(parent_complex, alpha_parent_adress, is_alpha_blocker);
compute_link_blockers(parent_complex, alpha_parent_adress, is_alpha_blocker);
}
diff --git a/include/gudhi/Skeleton_blocker_simplifiable_complex.h b/include/gudhi/Skeleton_blocker_simplifiable_complex.h
index 171efd4b..544e02e8 100644
--- a/include/gudhi/Skeleton_blocker_simplifiable_complex.h
+++ b/include/gudhi/Skeleton_blocker_simplifiable_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): David Salinas
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef SKELETON_BLOCKER_SIMPLIFIABLE_COMPLEX_H_
#define SKELETON_BLOCKER_SIMPLIFIABLE_COMPLEX_H_
@@ -33,7 +34,7 @@ namespace Gudhi {
namespace skeleton_blocker {
/**
- * Returns true iff the blocker 'sigma' is popable.
+ * Returns true if the blocker 'sigma' is popable.
* To define popable, let us call 'L' the complex that
* consists in the current complex without the blocker 'sigma'.
* A blocker 'sigma' is then "popable" if the link of 'sigma'
@@ -145,8 +146,7 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::remove_star(Vertex_handle v) {
* whenever the dimension of tau is at least 2.
*/
template<typename SkeletonBlockerDS>
-void Skeleton_blocker_complex<SkeletonBlockerDS>::update_blockers_after_remove_star_of_vertex_or_edge(
- const Simplex& simplex_to_be_removed) {
+void Skeleton_blocker_complex<SkeletonBlockerDS>::update_blockers_after_remove_star_of_vertex_or_edge(const Simplex& simplex_to_be_removed) {
std::list <Blocker_handle> blockers_to_update;
if (simplex_to_be_removed.empty()) return;
@@ -224,8 +224,6 @@ void Skeleton_blocker_complex<SkeletonBlockerDS>::add_simplex(const Simplex& sig
add_blockers_after_simplex_insertion(sigma);
}
-
-
template<typename SkeletonBlockerDS>
void Skeleton_blocker_complex<SkeletonBlockerDS>::add_blockers_after_simplex_insertion(Simplex sigma) {
if (sigma.dimension() < 1) return;
@@ -385,7 +383,8 @@ Skeleton_blocker_complex<SkeletonBlockerDS>::contract_edge(Vertex_handle a, Vert
template<typename SkeletonBlockerDS>
void Skeleton_blocker_complex<SkeletonBlockerDS>::get_blockers_to_be_added_after_contraction(Vertex_handle a,
- Vertex_handle b, std::set<Simplex>& blockers_to_add) {
+ Vertex_handle b,
+ std::set<Simplex>& blockers_to_add) {
blockers_to_add.clear();
typedef Skeleton_blocker_link_complex<Skeleton_blocker_complex<SkeletonBlockerDS> > LinkComplexType;
diff --git a/include/gudhi/Strong_witness_complex.h b/include/gudhi/Strong_witness_complex.h
new file mode 100644
index 00000000..a973ddb7
--- /dev/null
+++ b/include/gudhi/Strong_witness_complex.h
@@ -0,0 +1,185 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2015 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef STRONG_WITNESS_COMPLEX_H_
+#define STRONG_WITNESS_COMPLEX_H_
+
+#include <gudhi/Active_witness/Active_witness.h>
+
+#include <utility>
+#include <vector>
+#include <list>
+#include <limits>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+/* \private
+ * \class Strong_witness_complex
+ * \brief Constructs strong witness complex for a given table of nearest landmarks with respect to witnesses.
+ * \ingroup witness_complex
+ *
+ * \tparam Nearest_landmark_table_ needs to be a range of a range of pairs of nearest landmarks and distances.
+ * The class Nearest_landmark_table_::value_type must be a copiable range.
+ * The range of pairs must admit a member type 'iterator'. The dereference type
+ * of the pair range iterator needs to be 'std::pair<std::size_t, double>'.
+ */
+template< class Nearest_landmark_table_ >
+class Strong_witness_complex {
+ private:
+ typedef typename Nearest_landmark_table_::value_type Nearest_landmark_range;
+ typedef std::size_t Witness_id;
+ typedef std::size_t Landmark_id;
+ typedef std::pair<Landmark_id, double> Id_distance_pair;
+ typedef Active_witness<Id_distance_pair, Nearest_landmark_range> ActiveWitness;
+ typedef std::list< ActiveWitness > ActiveWitnessList;
+ typedef std::vector< Landmark_id > typeVectorVertex;
+ typedef std::vector<Nearest_landmark_range> Nearest_landmark_table_internal;
+ typedef Landmark_id Vertex_handle;
+
+ protected:
+ Nearest_landmark_table_internal nearest_landmark_table_;
+
+ public:
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /* @name Constructor
+ */
+
+ //@{
+
+ Strong_witness_complex() {
+ }
+
+ /**
+ * \brief Initializes member variables before constructing simplicial complex.
+ * \details Records nearest landmark table.
+ * @param[in] nearest_landmark_table needs to be a range of a range of pairs of nearest landmarks and distances.
+ * The class Nearest_landmark_table_::value_type must be a copiable range.
+ * The range of pairs must admit a member type 'iterator'. The dereference type
+ * of the pair range iterator needs to be 'std::pair<std::size_t, double>'.
+ */
+ Strong_witness_complex(Nearest_landmark_table_ const & nearest_landmark_table)
+ : nearest_landmark_table_(std::begin(nearest_landmark_table), std::end(nearest_landmark_table)) {
+ }
+
+ /** \brief Outputs the strong witness complex of relaxation 'max_alpha_square'
+ * in a simplicial complex data structure.
+ * \details The function returns true if the construction is successful and false otherwise.
+ * @param[out] complex Simplicial complex data structure, which is a model of
+ * SimplicialComplexForWitness concept.
+ * @param[in] max_alpha_square Maximal squared relaxation parameter.
+ * @param[in] limit_dimension Represents the maximal dimension of the simplicial complex
+ * (default value = no limit).
+ */
+ template < typename SimplicialComplexForWitness >
+ bool create_complex(SimplicialComplexForWitness& complex,
+ double max_alpha_square,
+ Landmark_id limit_dimension = std::numeric_limits<Landmark_id>::max()) const {
+ Landmark_id complex_dim = 0;
+ if (complex.num_vertices() > 0) {
+ std::cerr << "Strong witness complex cannot create complex - complex is not empty.\n";
+ return false;
+ }
+ if (max_alpha_square < 0) {
+ std::cerr << "Strong witness complex cannot create complex - squared relaxation parameter must be "
+ << "non-negative.\n";
+ return false;
+ }
+ if (limit_dimension < 0) {
+ std::cerr << "Strong witness complex cannot create complex - limit dimension must be non-negative.\n";
+ return false;
+ }
+ for (auto w : nearest_landmark_table_) {
+ ActiveWitness aw(w);
+ typeVectorVertex simplex;
+ typename ActiveWitness::iterator aw_it = aw.begin();
+ float lim_dist2 = aw.begin()->second + max_alpha_square;
+ while ((Landmark_id)simplex.size() <= limit_dimension && aw_it != aw.end() && aw_it->second < lim_dist2) {
+ simplex.push_back(aw_it->first);
+ complex.insert_simplex_and_subfaces(simplex, aw_it->second - aw.begin()->second);
+ aw_it++;
+ }
+ // continue inserting limD-faces of the following simplices
+ typeVectorVertex& vertices = simplex; // 'simplex' now will be called vertices
+ while (aw_it != aw.end() && aw_it->second < lim_dist2) {
+ typeVectorVertex facet = {};
+ add_all_faces_of_dimension(limit_dimension, vertices, vertices.begin(), aw_it,
+ aw_it->second - aw.begin()->second, facet, complex);
+ vertices.push_back(aw_it->first);
+ aw_it++;
+ }
+ if ((Landmark_id)simplex.size() - 1 > complex_dim)
+ complex_dim = simplex.size() - 1;
+ }
+ complex.set_dimension(complex_dim);
+ return true;
+ }
+
+ private:
+ /* \brief Adds recursively all the faces of a certain dimension dim-1 witnessed by the same witness.
+ * Iterator is needed to know until how far we can take landmarks to form simplexes.
+ * simplex is the prefix of the simplexes to insert.
+ * The landmark pointed by aw_it is added to all formed simplices.
+ */
+ template < typename SimplicialComplexForWitness >
+ void add_all_faces_of_dimension(Landmark_id dim,
+ typeVectorVertex& vertices,
+ typename typeVectorVertex::iterator curr_it,
+ typename ActiveWitness::iterator aw_it,
+ double filtration_value,
+ typeVectorVertex& simplex,
+ SimplicialComplexForWitness& sc) const {
+ if (dim > 0) {
+ while (curr_it != vertices.end()) {
+ simplex.push_back(*curr_it);
+ ++curr_it;
+ add_all_faces_of_dimension(dim-1,
+ vertices,
+ curr_it,
+ aw_it,
+ filtration_value,
+ simplex,
+ sc);
+ simplex.pop_back();
+ add_all_faces_of_dimension(dim,
+ vertices,
+ curr_it,
+ aw_it,
+ filtration_value,
+ simplex,
+ sc);
+ }
+ } else if (dim == 0) {
+ simplex.push_back(aw_it->first);
+ sc.insert_simplex_and_subfaces(simplex, filtration_value);
+ simplex.pop_back();
+ }
+ }
+ //@}
+};
+
+} // namespace witness_complex
+
+} // namespace Gudhi
+
+#endif // STRONG_WITNESS_COMPLEX_H_
diff --git a/include/gudhi/Tangential_complex.h b/include/gudhi/Tangential_complex.h
new file mode 100644
index 00000000..cfc82eb1
--- /dev/null
+++ b/include/gudhi/Tangential_complex.h
@@ -0,0 +1,2276 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TANGENTIAL_COMPLEX_H_
+#define TANGENTIAL_COMPLEX_H_
+
+#include <gudhi/Tangential_complex/config.h>
+#include <gudhi/Tangential_complex/Simplicial_complex.h>
+#include <gudhi/Tangential_complex/utilities.h>
+#include <gudhi/Kd_tree_search.h>
+#include <gudhi/console_color.h>
+#include <gudhi/Clock.h>
+#include <gudhi/Simplex_tree.h>
+
+#include <CGAL/Default.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/function_objects.h> // for CGAL::Identity
+#include <CGAL/Epick_d.h>
+#include <CGAL/Regular_triangulation_traits_adapter.h>
+#include <CGAL/Regular_triangulation.h>
+#include <CGAL/Delaunay_triangulation.h>
+#include <CGAL/Combination_enumerator.h>
+#include <CGAL/point_generators_d.h>
+
+#include <Eigen/Core>
+#include <Eigen/Eigen>
+
+#include <boost/optional.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/range/adaptor/transformed.hpp>
+#include <boost/range/counting_range.hpp>
+#include <boost/math/special_functions/factorials.hpp>
+#include <boost/container/flat_set.hpp>
+
+#include <tuple>
+#include <vector>
+#include <set>
+#include <utility>
+#include <sstream>
+#include <iostream>
+#include <limits>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <cmath> // for std::sqrt
+#include <string>
+#include <cstddef> // for std::size_t
+
+#ifdef GUDHI_USE_TBB
+#include <tbb/parallel_for.h>
+#include <tbb/combinable.h>
+#include <tbb/mutex.h>
+#endif
+
+// #define GUDHI_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3)
+
+namespace sps = Gudhi::spatial_searching;
+
+namespace Gudhi {
+
+namespace tangential_complex {
+
+using namespace internal;
+
+class Vertex_data {
+ public:
+ Vertex_data(std::size_t data = (std::numeric_limits<std::size_t>::max)())
+ : m_data(data) { }
+
+ operator std::size_t() {
+ return m_data;
+ }
+
+ operator std::size_t() const {
+ return m_data;
+ }
+
+ private:
+ std::size_t m_data;
+};
+
+/**
+ * \class Tangential_complex Tangential_complex.h gudhi/Tangential_complex.h
+ * \brief Tangential complex data structure.
+ *
+ * \ingroup tangential_complex
+ *
+ * \details
+ * The class Tangential_complex represents a tangential complex.
+ * After the computation of the complex, an optional post-processing called perturbation can
+ * be run to attempt to remove inconsistencies.
+ *
+ * \tparam Kernel_ requires a <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class, which
+ * can be static if you know the ambiant dimension at compile-time, or dynamic if you don't.
+ * \tparam DimensionTag can be either <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_23/classCGAL_1_1Dimension__tag.html">Dimension_tag<d></a>
+ * if you know the intrinsic dimension at compile-time,
+ * or <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_23/classCGAL_1_1Dynamic__dimension__tag.html">CGAL::Dynamic_dimension_tag</a>
+ * if you don't.
+ * \tparam Concurrency_tag enables sequential versus parallel computation. Possible values are `CGAL::Parallel_tag` (the default) and `CGAL::Sequential_tag`.
+ * \tparam Triangulation_ is the type used for storing the local regular triangulations. We highly recommend to use the default value (`CGAL::Regular_triangulation`).
+ *
+ */
+template
+<
+ typename Kernel_, // ambiant kernel
+ typename DimensionTag, // intrinsic dimension
+ typename Concurrency_tag = CGAL::Parallel_tag,
+ typename Triangulation_ = CGAL::Default
+>
+class Tangential_complex {
+ typedef Kernel_ K;
+ typedef typename K::FT FT;
+ typedef typename K::Point_d Point;
+ typedef typename K::Weighted_point_d Weighted_point;
+ typedef typename K::Vector_d Vector;
+
+ typedef typename CGAL::Default::Get
+ <
+ Triangulation_,
+ CGAL::Regular_triangulation
+ <
+ CGAL::Epick_d<DimensionTag>,
+ CGAL::Triangulation_data_structure
+ <
+ typename CGAL::Epick_d<DimensionTag>::Dimension,
+ CGAL::Triangulation_vertex
+ <
+ CGAL::Regular_triangulation_traits_adapter< CGAL::Epick_d<DimensionTag> >, Vertex_data
+ >,
+ CGAL::Triangulation_full_cell<CGAL::Regular_triangulation_traits_adapter< CGAL::Epick_d<DimensionTag> > >
+ >
+ >
+ >::type Triangulation;
+ typedef typename Triangulation::Geom_traits Tr_traits;
+ typedef typename Triangulation::Weighted_point Tr_point;
+ typedef typename Triangulation::Bare_point Tr_bare_point;
+ typedef typename Triangulation::Vertex_handle Tr_vertex_handle;
+ typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle;
+ typedef typename Tr_traits::Vector_d Tr_vector;
+
+#if defined(GUDHI_USE_TBB)
+ typedef tbb::mutex Mutex_for_perturb;
+ typedef Vector Translation_for_perturb;
+ typedef std::vector<Atomic_wrapper<FT> > Weights;
+#else
+ typedef Vector Translation_for_perturb;
+ typedef std::vector<FT> Weights;
+#endif
+ typedef std::vector<Translation_for_perturb> Translations_for_perturb;
+
+ // Store a local triangulation and a handle to its center vertex
+
+ struct Tr_and_VH {
+ public:
+ Tr_and_VH()
+ : m_tr(NULL) { }
+
+ Tr_and_VH(int dim)
+ : m_tr(new Triangulation(dim)) { }
+
+ ~Tr_and_VH() {
+ destroy_triangulation();
+ }
+
+ Triangulation & construct_triangulation(int dim) {
+ delete m_tr;
+ m_tr = new Triangulation(dim);
+ return tr();
+ }
+
+ void destroy_triangulation() {
+ delete m_tr;
+ m_tr = NULL;
+ }
+
+ Triangulation & tr() {
+ return *m_tr;
+ }
+
+ Triangulation const& tr() const {
+ return *m_tr;
+ }
+
+ Tr_vertex_handle const& center_vertex() const {
+ return m_center_vertex;
+ }
+
+ Tr_vertex_handle & center_vertex() {
+ return m_center_vertex;
+ }
+
+ private:
+ Triangulation* m_tr;
+ Tr_vertex_handle m_center_vertex;
+ };
+
+ public:
+ typedef Basis<K> Tangent_space_basis;
+ typedef Basis<K> Orthogonal_space_basis;
+ typedef std::vector<Tangent_space_basis> TS_container;
+ typedef std::vector<Orthogonal_space_basis> OS_container;
+
+ typedef std::vector<Point> Points;
+
+ typedef boost::container::flat_set<std::size_t> Simplex;
+ typedef std::set<Simplex> Simplex_set;
+
+ private:
+ typedef sps::Kd_tree_search<K, Points> Points_ds;
+ typedef typename Points_ds::KNS_range KNS_range;
+ typedef typename Points_ds::INS_range INS_range;
+
+ typedef std::vector<Tr_and_VH> Tr_container;
+ typedef std::vector<Vector> Vectors;
+
+ // An Incident_simplex is the list of the vertex indices
+ // except the center vertex
+ typedef boost::container::flat_set<std::size_t> Incident_simplex;
+ typedef std::vector<Incident_simplex> Star;
+ typedef std::vector<Star> Stars_container;
+
+ // For transform_iterator
+
+ static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) {
+ return vh->point();
+ }
+
+ template <typename P, typename VH>
+ static const P &vertex_handle_to_point(VH vh) {
+ return vh->point();
+ }
+
+ public:
+ typedef internal::Simplicial_complex Simplicial_complex;
+
+ /** \brief Constructor from a range of points.
+ * Points are copied into the instance, and a search data structure is initialized.
+ * Note the complex is not computed: `compute_tangential_complex` must be called after the creation
+ * of the object.
+ *
+ * @param[in] points Range of points (`Point_range::value_type` must be the same as `Kernel_::Point_d`).
+ * @param[in] intrinsic_dimension Intrinsic dimension of the manifold.
+ * @param[in] k Kernel instance.
+ */
+ template <typename Point_range>
+ Tangential_complex(Point_range points,
+ int intrinsic_dimension,
+#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+ InputIterator first_for_tse, InputIterator last_for_tse,
+#endif
+ const K &k = K()
+ )
+ : m_k(k),
+ m_intrinsic_dim(intrinsic_dimension),
+ m_ambient_dim(points.empty() ? 0 : k.point_dimension_d_object()(*points.begin())),
+ m_points(points.begin(), points.end()),
+ m_weights(m_points.size(), FT(0))
+#if defined(GUDHI_USE_TBB) && defined(GUDHI_TC_PERTURB_POSITION)
+ , m_p_perturb_mutexes(NULL)
+#endif
+ , m_points_ds(m_points)
+ , m_last_max_perturb(0.)
+ , m_are_tangent_spaces_computed(m_points.size(), false)
+ , m_tangent_spaces(m_points.size(), Tangent_space_basis())
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ , m_orth_spaces(m_points.size(), Orthogonal_space_basis())
+#endif
+#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+ , m_points_for_tse(first_for_tse, last_for_tse)
+ , m_points_ds_for_tse(m_points_for_tse)
+#endif
+ { }
+
+ /// Destructor
+ ~Tangential_complex() {
+#if defined(GUDHI_USE_TBB) && defined(GUDHI_TC_PERTURB_POSITION)
+ delete [] m_p_perturb_mutexes;
+#endif
+ }
+
+ /// Returns the intrinsic dimension of the manifold.
+ int intrinsic_dimension() const {
+ return m_intrinsic_dim;
+ }
+
+ /// Returns the ambient dimension.
+ int ambient_dimension() const {
+ return m_ambient_dim;
+ }
+
+ Points const& points() const {
+ return m_points;
+ }
+
+ /** \brief Returns the point corresponding to the vertex given as parameter.
+ *
+ * @param[in] vertex Vertex handle of the point to retrieve.
+ * @return The point found.
+ */
+ Point get_point(std::size_t vertex) const {
+ return m_points[vertex];
+ }
+
+ /** \brief Returns the perturbed position of the point corresponding to the vertex given as parameter.
+ *
+ * @param[in] vertex Vertex handle of the point to retrieve.
+ * @return The perturbed position of the point found.
+ */
+ Point get_perturbed_point(std::size_t vertex) const {
+ return compute_perturbed_point(vertex);
+ }
+
+ /// Returns the number of vertices.
+
+ std::size_t number_of_vertices() const {
+ return m_points.size();
+ }
+
+ void set_weights(const Weights& weights) {
+ m_weights = weights;
+ }
+
+ void set_tangent_planes(const TS_container& tangent_spaces
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ , const OS_container& orthogonal_spaces
+#endif
+ ) {
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ GUDHI_CHECK(
+ m_points.size() == tangent_spaces.size()
+ && m_points.size() == orthogonal_spaces.size(),
+ std::logic_error("Wrong sizes"));
+#else
+ GUDHI_CHECK(
+ m_points.size() == tangent_spaces.size(),
+ std::logic_error("Wrong sizes"));
+#endif
+ m_tangent_spaces = tangent_spaces;
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ m_orth_spaces = orthogonal_spaces;
+#endif
+ for (std::size_t i = 0; i < m_points.size(); ++i)
+ m_are_tangent_spaces_computed[i] = true;
+ }
+
+ /// Computes the tangential complex.
+ void compute_tangential_complex() {
+#ifdef GUDHI_TC_PERFORM_EXTRA_CHECKS
+ std::cerr << red << "WARNING: GUDHI_TC_PERFORM_EXTRA_CHECKS is defined. "
+ << "Computation might be slower than usual.\n" << white;
+#endif
+
+#if defined(GUDHI_TC_PROFILING) && defined(GUDHI_USE_TBB)
+ Gudhi::Clock t;
+#endif
+
+ // We need to do that because we don't want the container to copy the
+ // already-computed triangulations (while resizing) since it would
+ // invalidate the vertex handles stored beside the triangulations
+ m_triangulations.resize(m_points.size());
+ m_stars.resize(m_points.size());
+ m_squared_star_spheres_radii_incl_margin.resize(m_points.size(), FT(-1));
+#ifdef GUDHI_TC_PERTURB_POSITION
+ if (m_points.empty())
+ m_translations.clear();
+ else
+ m_translations.resize(m_points.size(),
+ m_k.construct_vector_d_object()(m_ambient_dim));
+#if defined(GUDHI_USE_TBB)
+ delete [] m_p_perturb_mutexes;
+ m_p_perturb_mutexes = new Mutex_for_perturb[m_points.size()];
+#endif
+#endif
+
+#ifdef GUDHI_USE_TBB
+ // Parallel
+ if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value) {
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, m_points.size()),
+ Compute_tangent_triangulation(*this));
+ } else {
+#endif // GUDHI_USE_TBB
+ // Sequential
+ for (std::size_t i = 0; i < m_points.size(); ++i)
+ compute_tangent_triangulation(i);
+#ifdef GUDHI_USE_TBB
+ }
+#endif // GUDHI_USE_TBB
+
+#if defined(GUDHI_TC_PROFILING) && defined(GUDHI_USE_TBB)
+ t.end();
+ std::cerr << "Tangential complex computed in " << t.num_seconds()
+ << " seconds.\n";
+#endif
+ }
+
+ /// \brief Type returned by `Tangential_complex::fix_inconsistencies_using_perturbation`.
+ struct Fix_inconsistencies_info {
+ /// `true` if all inconsistencies could be removed, `false` if the time limit has been reached before
+ bool success = false;
+ /// number of steps performed
+ unsigned int num_steps = 0;
+ /// initial number of inconsistent stars
+ std::size_t initial_num_inconsistent_stars = 0;
+ /// best number of inconsistent stars during the process
+ std::size_t best_num_inconsistent_stars = 0;
+ /// final number of inconsistent stars
+ std::size_t final_num_inconsistent_stars = 0;
+ };
+
+ /** \brief Attempts to fix inconsistencies by perturbing the point positions.
+ *
+ * @param[in] max_perturb Maximum length of the translations used by the perturbation.
+ * @param[in] time_limit Time limit in seconds. If -1, no time limit is set.
+ */
+ Fix_inconsistencies_info fix_inconsistencies_using_perturbation(double max_perturb, double time_limit = -1.) {
+ Fix_inconsistencies_info info;
+
+ if (time_limit == 0.)
+ return info;
+
+ Gudhi::Clock t;
+
+#ifdef GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES
+ std::tuple<std::size_t, std::size_t, std::size_t> stats_before =
+ number_of_inconsistent_simplices(false);
+
+ if (std::get<1>(stats_before) == 0) {
+#ifdef DEBUG_TRACES
+ std::cerr << "Nothing to fix.\n";
+#endif
+ info.success = false;
+ return info;
+ }
+#endif // GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES
+
+ m_last_max_perturb = max_perturb;
+
+ bool done = false;
+ info.best_num_inconsistent_stars = m_triangulations.size();
+ info.num_steps = 0;
+ while (!done) {
+#ifdef GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES
+ std::cerr
+ << "\nBefore fix step:\n"
+ << " * Total number of simplices in stars (incl. duplicates): "
+ << std::get<0>(stats_before) << "\n"
+ << " * Num inconsistent simplices in stars (incl. duplicates): "
+ << red << std::get<1>(stats_before) << white << " ("
+ << 100. * std::get<1>(stats_before) / std::get<0>(stats_before) << "%)\n"
+ << " * Number of stars containing inconsistent simplices: "
+ << red << std::get<2>(stats_before) << white << " ("
+ << 100. * std::get<2>(stats_before) / m_points.size() << "%)\n";
+#endif
+
+#if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)
+ std::cerr << yellow
+ << "\nAttempt to fix inconsistencies using perturbations - step #"
+ << info.num_steps + 1 << "... " << white;
+#endif
+
+ std::size_t num_inconsistent_stars = 0;
+ std::vector<std::size_t> updated_points;
+
+#ifdef GUDHI_TC_PROFILING
+ Gudhi::Clock t_fix_step;
+#endif
+
+ // Parallel
+#if defined(GUDHI_USE_TBB)
+ if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value) {
+ tbb::combinable<std::size_t> num_inconsistencies;
+ tbb::combinable<std::vector<std::size_t> > tls_updated_points;
+ tbb::parallel_for(
+ tbb::blocked_range<size_t>(0, m_triangulations.size()),
+ Try_to_solve_inconsistencies_in_a_local_triangulation(*this, max_perturb,
+ num_inconsistencies,
+ tls_updated_points));
+ num_inconsistent_stars =
+ num_inconsistencies.combine(std::plus<std::size_t>());
+ updated_points = tls_updated_points.combine(
+ [](std::vector<std::size_t> const& x,
+ std::vector<std::size_t> const& y) {
+ std::vector<std::size_t> res;
+ res.reserve(x.size() + y.size());
+ res.insert(res.end(), x.begin(), x.end());
+ res.insert(res.end(), y.begin(), y.end());
+ return res;
+ });
+ } else {
+#endif // GUDHI_USE_TBB
+ // Sequential
+ for (std::size_t i = 0; i < m_triangulations.size(); ++i) {
+ num_inconsistent_stars +=
+ try_to_solve_inconsistencies_in_a_local_triangulation(i, max_perturb,
+ std::back_inserter(updated_points));
+ }
+#if defined(GUDHI_USE_TBB)
+ }
+#endif // GUDHI_USE_TBB
+
+#ifdef GUDHI_TC_PROFILING
+ t_fix_step.end();
+#endif
+
+#if defined(GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES) || defined(DEBUG_TRACES)
+ std::cerr
+ << "\nEncountered during fix:\n"
+ << " * Num stars containing inconsistent simplices: "
+ << red << num_inconsistent_stars << white
+ << " (" << 100. * num_inconsistent_stars / m_points.size() << "%)\n";
+#endif
+
+#ifdef GUDHI_TC_PROFILING
+ std::cerr << yellow << "done in " << t_fix_step.num_seconds()
+ << " seconds.\n" << white;
+#elif defined(DEBUG_TRACES)
+ std::cerr << yellow << "done.\n" << white;
+#endif
+
+ if (num_inconsistent_stars > 0)
+ refresh_tangential_complex(updated_points);
+
+#ifdef GUDHI_TC_PERFORM_EXTRA_CHECKS
+ // Confirm that all stars were actually refreshed
+ std::size_t num_inc_1 =
+ std::get<1>(number_of_inconsistent_simplices(false));
+ refresh_tangential_complex();
+ std::size_t num_inc_2 =
+ std::get<1>(number_of_inconsistent_simplices(false));
+ if (num_inc_1 != num_inc_2)
+ std::cerr << red << "REFRESHMENT CHECK: FAILED. ("
+ << num_inc_1 << " vs " << num_inc_2 << ")\n" << white;
+ else
+ std::cerr << green << "REFRESHMENT CHECK: PASSED.\n" << white;
+#endif
+
+#ifdef GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES
+ std::tuple<std::size_t, std::size_t, std::size_t> stats_after =
+ number_of_inconsistent_simplices(false);
+
+ std::cerr
+ << "\nAfter fix:\n"
+ << " * Total number of simplices in stars (incl. duplicates): "
+ << std::get<0>(stats_after) << "\n"
+ << " * Num inconsistent simplices in stars (incl. duplicates): "
+ << red << std::get<1>(stats_after) << white << " ("
+ << 100. * std::get<1>(stats_after) / std::get<0>(stats_after) << "%)\n"
+ << " * Number of stars containing inconsistent simplices: "
+ << red << std::get<2>(stats_after) << white << " ("
+ << 100. * std::get<2>(stats_after) / m_points.size() << "%)\n";
+
+ stats_before = stats_after;
+#endif
+
+ if (info.num_steps == 0)
+ info.initial_num_inconsistent_stars = num_inconsistent_stars;
+
+ if (num_inconsistent_stars < info.best_num_inconsistent_stars)
+ info.best_num_inconsistent_stars = num_inconsistent_stars;
+
+ info.final_num_inconsistent_stars = num_inconsistent_stars;
+
+ done = (num_inconsistent_stars == 0);
+ if (!done) {
+ ++info.num_steps;
+ if (time_limit > 0. && t.num_seconds() > time_limit) {
+#ifdef DEBUG_TRACES
+ std::cerr << red << "Time limit reached.\n" << white;
+#endif
+ info.success = false;
+ return info;
+ }
+ }
+ }
+
+#ifdef DEBUG_TRACES
+ std::cerr << green << "Fixed!\n" << white;
+#endif
+ info.success = true;
+ return info;
+ }
+
+ /// \brief Type returned by `Tangential_complex::number_of_inconsistent_simplices`.
+ struct Num_inconsistencies {
+ /// Total number of simplices in stars (including duplicates that appear in several stars)
+ std::size_t num_simplices = 0;
+ /// Number of inconsistent simplices
+ std::size_t num_inconsistent_simplices = 0;
+ /// Number of stars containing at least one inconsistent simplex
+ std::size_t num_inconsistent_stars = 0;
+ };
+
+ /// Returns the number of inconsistencies
+ /// @param[in] verbose If true, outputs a message into `std::cerr`.
+
+ Num_inconsistencies
+ number_of_inconsistent_simplices(
+#ifdef DEBUG_TRACES
+ bool verbose = true
+#else
+ bool verbose = false
+#endif
+ ) const {
+ Num_inconsistencies stats;
+
+ // For each triangulation
+ for (std::size_t idx = 0; idx < m_points.size(); ++idx) {
+ bool is_star_inconsistent = false;
+
+ // For each cell
+ Star::const_iterator it_inc_simplex = m_stars[idx].begin();
+ Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
+ for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
+ // Don't check infinite cells
+ if (is_infinite(*it_inc_simplex))
+ continue;
+
+ Simplex c = *it_inc_simplex;
+ c.insert(idx); // Add the missing index
+
+ if (!is_simplex_consistent(c)) {
+ ++stats.num_inconsistent_simplices;
+ is_star_inconsistent = true;
+ }
+
+ ++stats.num_simplices;
+ }
+ stats.num_inconsistent_stars += is_star_inconsistent;
+ }
+
+ if (verbose) {
+ std::cerr
+ << "\n==========================================================\n"
+ << "Inconsistencies:\n"
+ << " * Total number of simplices in stars (incl. duplicates): "
+ << stats.num_simplices << "\n"
+ << " * Number of inconsistent simplices in stars (incl. duplicates): "
+ << stats.num_inconsistent_simplices << " ("
+ << 100. * stats.num_inconsistent_simplices / stats.num_simplices << "%)\n"
+ << " * Number of stars containing inconsistent simplices: "
+ << stats.num_inconsistent_stars << " ("
+ << 100. * stats.num_inconsistent_stars / m_points.size() << "%)\n"
+ << "==========================================================\n";
+ }
+
+ return stats;
+ }
+
+ /** \brief Exports the complex into a Simplex_tree.
+ *
+ * \tparam Simplex_tree_ must be a `Simplex_tree`.
+ *
+ * @param[out] tree The result, where each `Vertex_handle` is the index of the
+ * corresponding point in the range provided to the constructor (it can also be
+ * retrieved through the `Tangential_complex::get_point` function.
+ * @param[in] export_inconsistent_simplices Also export inconsistent simplices or not?
+ * @return The maximal dimension of the simplices.
+ */
+ template <typename Simplex_tree_>
+ int create_complex(Simplex_tree_ &tree
+ , bool export_inconsistent_simplices = true
+ /// \cond ADVANCED_PARAMETERS
+ , bool export_infinite_simplices = false
+ , Simplex_set *p_inconsistent_simplices = NULL
+ /// \endcond
+ ) const {
+#if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)
+ std::cerr << yellow
+ << "\nExporting the TC as a Simplex_tree... " << white;
+#endif
+#ifdef GUDHI_TC_PROFILING
+ Gudhi::Clock t;
+#endif
+
+ int max_dim = -1;
+
+ // For each triangulation
+ for (std::size_t idx = 0; idx < m_points.size(); ++idx) {
+ // For each cell of the star
+ Star::const_iterator it_inc_simplex = m_stars[idx].begin();
+ Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
+ for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
+ Simplex c = *it_inc_simplex;
+
+ // Don't export infinite cells
+ if (!export_infinite_simplices && is_infinite(c))
+ continue;
+
+ if (!export_inconsistent_simplices && !is_simplex_consistent(c))
+ continue;
+
+ if (static_cast<int> (c.size()) > max_dim)
+ max_dim = static_cast<int> (c.size());
+ // Add the missing center vertex
+ c.insert(idx);
+
+ // Try to insert the simplex
+ bool inserted = tree.insert_simplex_and_subfaces(c).second;
+
+ // Inconsistent?
+ if (p_inconsistent_simplices && inserted && !is_simplex_consistent(c)) {
+ p_inconsistent_simplices->insert(c);
+ }
+ }
+ }
+
+#ifdef GUDHI_TC_PROFILING
+ t.end();
+ std::cerr << yellow << "done in " << t.num_seconds()
+ << " seconds.\n" << white;
+#elif defined(DEBUG_TRACES)
+ std::cerr << yellow << "done.\n" << white;
+#endif
+
+ return max_dim;
+ }
+
+ // First clears the complex then exports the TC into it
+ // Returns the max dimension of the simplices
+ // check_lower_and_higher_dim_simplices : 0 (false), 1 (true), 2 (auto)
+ // If the check is enabled, the function:
+ // - won't insert the simplex if it is already in a higher dim simplex
+ // - will erase any lower-dim simplices that are faces of the new simplex
+ // "auto" (= 2) will enable the check as a soon as it encounters a
+ // simplex whose dimension is different from the previous ones.
+ // N.B.: The check is quite expensive.
+
+ int create_complex(Simplicial_complex &complex,
+ bool export_inconsistent_simplices = true,
+ bool export_infinite_simplices = false,
+ int check_lower_and_higher_dim_simplices = 2,
+ Simplex_set *p_inconsistent_simplices = NULL) const {
+#if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)
+ std::cerr << yellow
+ << "\nExporting the TC as a Simplicial_complex... " << white;
+#endif
+#ifdef GUDHI_TC_PROFILING
+ Gudhi::Clock t;
+#endif
+
+ int max_dim = -1;
+ complex.clear();
+
+ // For each triangulation
+ for (std::size_t idx = 0; idx < m_points.size(); ++idx) {
+ // For each cell of the star
+ Star::const_iterator it_inc_simplex = m_stars[idx].begin();
+ Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
+ for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
+ Simplex c = *it_inc_simplex;
+
+ // Don't export infinite cells
+ if (!export_infinite_simplices && is_infinite(c))
+ continue;
+
+ if (!export_inconsistent_simplices && !is_simplex_consistent(c))
+ continue;
+
+ // Unusual simplex dim?
+ if (check_lower_and_higher_dim_simplices == 2
+ && max_dim != -1
+ && static_cast<int> (c.size()) != max_dim) {
+ // Let's activate the check
+ std::cerr << red <<
+ "Info: check_lower_and_higher_dim_simplices ACTIVATED. "
+ "Export might be take some time...\n" << white;
+ check_lower_and_higher_dim_simplices = 1;
+ }
+
+ if (static_cast<int> (c.size()) > max_dim)
+ max_dim = static_cast<int> (c.size());
+ // Add the missing center vertex
+ c.insert(idx);
+
+ // Try to insert the simplex
+ bool added =
+ complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1);
+
+ // Inconsistent?
+ if (p_inconsistent_simplices && added && !is_simplex_consistent(c)) {
+ p_inconsistent_simplices->insert(c);
+ }
+ }
+ }
+
+#ifdef GUDHI_TC_PROFILING
+ t.end();
+ std::cerr << yellow << "done in " << t.num_seconds()
+ << " seconds.\n" << white;
+#elif defined(DEBUG_TRACES)
+ std::cerr << yellow << "done.\n" << white;
+#endif
+
+ return max_dim;
+ }
+
+ template<typename ProjectionFunctor = CGAL::Identity<Point> >
+ std::ostream &export_to_off(
+ const Simplicial_complex &complex, std::ostream & os,
+ Simplex_set const *p_simpl_to_color_in_red = NULL,
+ Simplex_set const *p_simpl_to_color_in_green = NULL,
+ Simplex_set const *p_simpl_to_color_in_blue = NULL,
+ ProjectionFunctor const& point_projection = ProjectionFunctor())
+ const {
+ return export_to_off(
+ os, false, p_simpl_to_color_in_red, p_simpl_to_color_in_green,
+ p_simpl_to_color_in_blue, &complex, point_projection);
+ }
+
+ template<typename ProjectionFunctor = CGAL::Identity<Point> >
+ std::ostream &export_to_off(
+ std::ostream & os, bool color_inconsistencies = false,
+ Simplex_set const *p_simpl_to_color_in_red = NULL,
+ Simplex_set const *p_simpl_to_color_in_green = NULL,
+ Simplex_set const *p_simpl_to_color_in_blue = NULL,
+ const Simplicial_complex *p_complex = NULL,
+ ProjectionFunctor const& point_projection = ProjectionFunctor()) const {
+ if (m_points.empty())
+ return os;
+
+ if (m_ambient_dim < 2) {
+ std::cerr << "Error: export_to_off => ambient dimension should be >= 2.\n";
+ os << "Error: export_to_off => ambient dimension should be >= 2.\n";
+ return os;
+ }
+ if (m_ambient_dim > 3) {
+ std::cerr << "Warning: export_to_off => ambient dimension should be "
+ "<= 3. Only the first 3 coordinates will be exported.\n";
+ }
+
+ if (m_intrinsic_dim < 1 || m_intrinsic_dim > 3) {
+ std::cerr << "Error: export_to_off => intrinsic dimension should be "
+ "between 1 and 3.\n";
+ os << "Error: export_to_off => intrinsic dimension should be "
+ "between 1 and 3.\n";
+ return os;
+ }
+
+ std::stringstream output;
+ std::size_t num_simplices, num_vertices;
+ export_vertices_to_off(output, num_vertices, false, point_projection);
+ if (p_complex) {
+ export_simplices_to_off(
+ *p_complex, output, num_simplices, p_simpl_to_color_in_red,
+ p_simpl_to_color_in_green, p_simpl_to_color_in_blue);
+ } else {
+ export_simplices_to_off(
+ output, num_simplices, color_inconsistencies, p_simpl_to_color_in_red,
+ p_simpl_to_color_in_green, p_simpl_to_color_in_blue);
+ }
+
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ os << "N";
+#endif
+
+ os << "OFF \n"
+ << num_vertices << " "
+ << num_simplices << " "
+ << "0 \n"
+ << output.str();
+
+ return os;
+ }
+
+ private:
+ void refresh_tangential_complex() {
+#if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)
+ std::cerr << yellow << "\nRefreshing TC... " << white;
+#endif
+
+#ifdef GUDHI_TC_PROFILING
+ Gudhi::Clock t;
+#endif
+#ifdef GUDHI_USE_TBB
+ // Parallel
+ if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value) {
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, m_points.size()),
+ Compute_tangent_triangulation(*this));
+ } else {
+#endif // GUDHI_USE_TBB
+ // Sequential
+ for (std::size_t i = 0; i < m_points.size(); ++i)
+ compute_tangent_triangulation(i);
+#ifdef GUDHI_USE_TBB
+ }
+#endif // GUDHI_USE_TBB
+
+#ifdef GUDHI_TC_PROFILING
+ t.end();
+ std::cerr << yellow << "done in " << t.num_seconds()
+ << " seconds.\n" << white;
+#elif defined(DEBUG_TRACES)
+ std::cerr << yellow << "done.\n" << white;
+#endif
+ }
+
+ // If the list of perturbed points is provided, it is much faster
+ template <typename Point_indices_range>
+ void refresh_tangential_complex(
+ Point_indices_range const& perturbed_points_indices) {
+#if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)
+ std::cerr << yellow << "\nRefreshing TC... " << white;
+#endif
+
+#ifdef GUDHI_TC_PROFILING
+ Gudhi::Clock t;
+#endif
+
+ // ANN tree containing only the perturbed points
+ Points_ds updated_pts_ds(m_points, perturbed_points_indices);
+
+#ifdef GUDHI_USE_TBB
+ // Parallel
+ if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value) {
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, m_points.size()),
+ Refresh_tangent_triangulation(*this, updated_pts_ds));
+ } else {
+#endif // GUDHI_USE_TBB
+ // Sequential
+ for (std::size_t i = 0; i < m_points.size(); ++i)
+ refresh_tangent_triangulation(i, updated_pts_ds);
+#ifdef GUDHI_USE_TBB
+ }
+#endif // GUDHI_USE_TBB
+
+#ifdef GUDHI_TC_PROFILING
+ t.end();
+ std::cerr << yellow << "done in " << t.num_seconds()
+ << " seconds.\n" << white;
+#elif defined(DEBUG_TRACES)
+ std::cerr << yellow << "done.\n" << white;
+#endif
+ }
+
+ void export_inconsistent_stars_to_OFF_files(std::string const& filename_base) const {
+ // For each triangulation
+ for (std::size_t idx = 0; idx < m_points.size(); ++idx) {
+ // We build a SC along the way in case it's inconsistent
+ Simplicial_complex sc;
+ // For each cell
+ bool is_inconsistent = false;
+ Star::const_iterator it_inc_simplex = m_stars[idx].begin();
+ Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
+ for (; it_inc_simplex != it_inc_simplex_end;
+ ++it_inc_simplex) {
+ // Skip infinite cells
+ if (is_infinite(*it_inc_simplex))
+ continue;
+
+ Simplex c = *it_inc_simplex;
+ c.insert(idx); // Add the missing index
+
+ sc.add_simplex(c);
+
+ // If we do not already know this star is inconsistent, test it
+ if (!is_inconsistent && !is_simplex_consistent(c))
+ is_inconsistent = true;
+ }
+
+ if (is_inconsistent) {
+ // Export star to OFF file
+ std::stringstream output_filename;
+ output_filename << filename_base << "_" << idx << ".off";
+ std::ofstream off_stream(output_filename.str().c_str());
+ export_to_off(sc, off_stream);
+ }
+ }
+ }
+
+ class Compare_distance_to_ref_point {
+ public:
+ Compare_distance_to_ref_point(Point const& ref, K const& k)
+ : m_ref(ref), m_k(k) { }
+
+ bool operator()(Point const& p1, Point const& p2) {
+ typename K::Squared_distance_d sqdist =
+ m_k.squared_distance_d_object();
+ return sqdist(p1, m_ref) < sqdist(p2, m_ref);
+ }
+
+ private:
+ Point const& m_ref;
+ K const& m_k;
+ };
+
+#ifdef GUDHI_USE_TBB
+ // Functor for compute_tangential_complex function
+ class Compute_tangent_triangulation {
+ Tangential_complex & m_tc;
+
+ public:
+ // Constructor
+ Compute_tangent_triangulation(Tangential_complex &tc)
+ : m_tc(tc) { }
+
+ // Constructor
+ Compute_tangent_triangulation(const Compute_tangent_triangulation &ctt)
+ : m_tc(ctt.m_tc) { }
+
+ // operator()
+ void operator()(const tbb::blocked_range<size_t>& r) const {
+ for (size_t i = r.begin(); i != r.end(); ++i)
+ m_tc.compute_tangent_triangulation(i);
+ }
+ };
+
+ // Functor for refresh_tangential_complex function
+ class Refresh_tangent_triangulation {
+ Tangential_complex & m_tc;
+ Points_ds const& m_updated_pts_ds;
+
+ public:
+ // Constructor
+ Refresh_tangent_triangulation(Tangential_complex &tc, Points_ds const& updated_pts_ds)
+ : m_tc(tc), m_updated_pts_ds(updated_pts_ds) { }
+
+ // Constructor
+ Refresh_tangent_triangulation(const Refresh_tangent_triangulation &ctt)
+ : m_tc(ctt.m_tc), m_updated_pts_ds(ctt.m_updated_pts_ds) { }
+
+ // operator()
+ void operator()(const tbb::blocked_range<size_t>& r) const {
+ for (size_t i = r.begin(); i != r.end(); ++i)
+ m_tc.refresh_tangent_triangulation(i, m_updated_pts_ds);
+ }
+ };
+#endif // GUDHI_USE_TBB
+
+ bool is_infinite(Simplex const& s) const {
+ return *s.rbegin() == (std::numeric_limits<std::size_t>::max)();
+ }
+
+ // Output: "triangulation" is a Regular Triangulation containing at least the
+ // star of "center_pt"
+ // Returns the handle of the center vertex
+ Tr_vertex_handle compute_star(std::size_t i, const Point &center_pt, const Tangent_space_basis &tsb,
+ Triangulation &triangulation, bool verbose = false) {
+ int tangent_space_dim = tsb.dimension();
+ const Tr_traits &local_tr_traits = triangulation.geom_traits();
+ Tr_vertex_handle center_vertex;
+
+ // Kernel functor & objects
+ typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object();
+
+ // Triangulation's traits functor & objects
+ typename Tr_traits::Compute_weight_d point_weight = local_tr_traits.compute_weight_d_object();
+ typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object();
+
+ //***************************************************
+ // Build a minimal triangulation in the tangent space
+ // (we only need the star of p)
+ //***************************************************
+
+ // Insert p
+ Tr_point proj_wp;
+ if (i == tsb.origin()) {
+ // Insert {(0, 0, 0...), m_weights[i]}
+ proj_wp = local_tr_traits.construct_weighted_point_d_object()(local_tr_traits.construct_point_d_object()(tangent_space_dim, CGAL::ORIGIN),
+ m_weights[i]);
+ } else {
+ const Weighted_point& wp = compute_perturbed_weighted_point(i);
+ proj_wp = project_point_and_compute_weight(wp, tsb, local_tr_traits);
+ }
+
+ center_vertex = triangulation.insert(proj_wp);
+ center_vertex->data() = i;
+ if (verbose)
+ std::cerr << "* Inserted point #" << i << "\n";
+
+#ifdef GUDHI_TC_VERY_VERBOSE
+ std::size_t num_attempts_to_insert_points = 1;
+ std::size_t num_inserted_points = 1;
+#endif
+ // const int NUM_NEIGHBORS = 150;
+ // KNS_range ins_range = m_points_ds.query_k_nearest_neighbors(center_pt, NUM_NEIGHBORS);
+ INS_range ins_range = m_points_ds.query_incremental_nearest_neighbors(center_pt);
+
+ // While building the local triangulation, we keep the radius
+ // of the sphere "star sphere" centered at "center_vertex"
+ // and which contains all the
+ // circumspheres of the star of "center_vertex"
+ boost::optional<FT> squared_star_sphere_radius_plus_margin;
+
+ // Insert points until we find a point which is outside "star sphere"
+ for (auto nn_it = ins_range.begin();
+ nn_it != ins_range.end();
+ ++nn_it) {
+ std::size_t neighbor_point_idx = nn_it->first;
+
+ // ith point = p, which is already inserted
+ if (neighbor_point_idx != i) {
+ // No need to lock the Mutex_for_perturb here since this will not be
+ // called while other threads are perturbing the positions
+ Point neighbor_pt;
+ FT neighbor_weight;
+ compute_perturbed_weighted_point(neighbor_point_idx, neighbor_pt, neighbor_weight);
+
+ if (squared_star_sphere_radius_plus_margin &&
+ k_sqdist(center_pt, neighbor_pt) > *squared_star_sphere_radius_plus_margin)
+ break;
+
+ Tr_point proj_pt = project_point_and_compute_weight(neighbor_pt, neighbor_weight, tsb,
+ local_tr_traits);
+
+#ifdef GUDHI_TC_VERY_VERBOSE
+ ++num_attempts_to_insert_points;
+#endif
+
+
+ Tr_vertex_handle vh = triangulation.insert_if_in_star(proj_pt, center_vertex);
+ // Tr_vertex_handle vh = triangulation.insert(proj_pt);
+ if (vh != Tr_vertex_handle() && vh->data() == (std::numeric_limits<std::size_t>::max)()) {
+#ifdef GUDHI_TC_VERY_VERBOSE
+ ++num_inserted_points;
+#endif
+ if (verbose)
+ std::cerr << "* Inserted point #" << neighbor_point_idx << "\n";
+
+ vh->data() = neighbor_point_idx;
+
+ // Let's recompute squared_star_sphere_radius_plus_margin
+ if (triangulation.current_dimension() >= tangent_space_dim) {
+ squared_star_sphere_radius_plus_margin = boost::none;
+ // Get the incident cells and look for the biggest circumsphere
+ std::vector<Tr_full_cell_handle> incident_cells;
+ triangulation.incident_full_cells(
+ center_vertex,
+ std::back_inserter(incident_cells));
+ for (typename std::vector<Tr_full_cell_handle>::iterator cit =
+ incident_cells.begin(); cit != incident_cells.end(); ++cit) {
+ Tr_full_cell_handle cell = *cit;
+ if (triangulation.is_infinite(cell)) {
+ squared_star_sphere_radius_plus_margin = boost::none;
+ break;
+ } else {
+ // Note that this uses the perturbed point since it uses
+ // the points of the local triangulation
+ Tr_point c = power_center(boost::make_transform_iterator(cell->vertices_begin(),
+ vertex_handle_to_point<Tr_point,
+ Tr_vertex_handle>),
+ boost::make_transform_iterator(cell->vertices_end(),
+ vertex_handle_to_point<Tr_point,
+ Tr_vertex_handle>));
+
+ FT sq_power_sphere_diam = 4 * point_weight(c);
+
+ if (!squared_star_sphere_radius_plus_margin ||
+ sq_power_sphere_diam > *squared_star_sphere_radius_plus_margin) {
+ squared_star_sphere_radius_plus_margin = sq_power_sphere_diam;
+ }
+ }
+ }
+
+ // Let's add the margin, now
+ // The value depends on whether we perturb weight or position
+ if (squared_star_sphere_radius_plus_margin) {
+ // "2*m_last_max_perturb" because both points can be perturbed
+ squared_star_sphere_radius_plus_margin = CGAL::square(std::sqrt(*squared_star_sphere_radius_plus_margin)
+ + 2 * m_last_max_perturb);
+
+ // Save it in `m_squared_star_spheres_radii_incl_margin`
+ m_squared_star_spheres_radii_incl_margin[i] =
+ *squared_star_sphere_radius_plus_margin;
+ } else {
+ m_squared_star_spheres_radii_incl_margin[i] = FT(-1);
+ }
+ }
+ }
+ }
+ }
+
+ return center_vertex;
+ }
+
+ void refresh_tangent_triangulation(std::size_t i, Points_ds const& updated_pts_ds, bool verbose = false) {
+ if (verbose)
+ std::cerr << "** Refreshing tangent tri #" << i << " **\n";
+
+ if (m_squared_star_spheres_radii_incl_margin[i] == FT(-1))
+ return compute_tangent_triangulation(i, verbose);
+
+ Point center_point = compute_perturbed_point(i);
+ // Among updated point, what is the closer from our center point?
+ std::size_t closest_pt_index =
+ updated_pts_ds.query_k_nearest_neighbors(center_point, 1, false).begin()->first;
+
+ typename K::Construct_weighted_point_d k_constr_wp =
+ m_k.construct_weighted_point_d_object();
+ typename K::Power_distance_d k_power_dist = m_k.power_distance_d_object();
+
+ // Construct a weighted point equivalent to the star sphere
+ Weighted_point star_sphere = k_constr_wp(compute_perturbed_point(i),
+ m_squared_star_spheres_radii_incl_margin[i]);
+ Weighted_point closest_updated_point =
+ compute_perturbed_weighted_point(closest_pt_index);
+
+ // Is the "closest point" inside our star sphere?
+ if (k_power_dist(star_sphere, closest_updated_point) <= FT(0))
+ compute_tangent_triangulation(i, verbose);
+ }
+
+ void compute_tangent_triangulation(std::size_t i, bool verbose = false) {
+ if (verbose)
+ std::cerr << "** Computing tangent tri #" << i << " **\n";
+ // std::cerr << "***********************************************\n";
+
+ // No need to lock the mutex here since this will not be called while
+ // other threads are perturbing the positions
+ const Point center_pt = compute_perturbed_point(i);
+ Tangent_space_basis &tsb = m_tangent_spaces[i];
+
+ // Estimate the tangent space
+ if (!m_are_tangent_spaces_computed[i]) {
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ tsb = compute_tangent_space(center_pt, i, true /*normalize*/, &m_orth_spaces[i]);
+#else
+ tsb = compute_tangent_space(center_pt, i);
+#endif
+ }
+
+#if defined(GUDHI_TC_PROFILING) && defined(GUDHI_TC_VERY_VERBOSE)
+ Gudhi::Clock t;
+#endif
+ int tangent_space_dim = tangent_basis_dim(i);
+ Triangulation &local_tr =
+ m_triangulations[i].construct_triangulation(tangent_space_dim);
+
+ m_triangulations[i].center_vertex() =
+ compute_star(i, center_pt, tsb, local_tr, verbose);
+
+#if defined(GUDHI_TC_PROFILING) && defined(GUDHI_TC_VERY_VERBOSE)
+ t.end();
+ std::cerr << " - triangulation construction: " << t.num_seconds() << " s.\n";
+ t.reset();
+#endif
+
+#ifdef GUDHI_TC_VERY_VERBOSE
+ std::cerr << "Inserted " << num_inserted_points << " points / "
+ << num_attempts_to_insert_points << " attemps to compute the star\n";
+#endif
+
+ update_star(i);
+
+#if defined(GUDHI_TC_PROFILING) && defined(GUDHI_TC_VERY_VERBOSE)
+ t.end();
+ std::cerr << " - update_star: " << t.num_seconds() << " s.\n";
+#endif
+ }
+
+ // Updates m_stars[i] directly from m_triangulations[i]
+
+ void update_star(std::size_t i) {
+ Star &star = m_stars[i];
+ star.clear();
+ Triangulation &local_tr = m_triangulations[i].tr();
+ Tr_vertex_handle center_vertex = m_triangulations[i].center_vertex();
+ int cur_dim_plus_1 = local_tr.current_dimension() + 1;
+
+ std::vector<Tr_full_cell_handle> incident_cells;
+ local_tr.incident_full_cells(
+ center_vertex, std::back_inserter(incident_cells));
+
+ typename std::vector<Tr_full_cell_handle>::const_iterator it_c = incident_cells.begin();
+ typename std::vector<Tr_full_cell_handle>::const_iterator it_c_end = incident_cells.end();
+ // For each cell
+ for (; it_c != it_c_end; ++it_c) {
+ // Will contain all indices except center_vertex
+ Incident_simplex incident_simplex;
+ for (int j = 0; j < cur_dim_plus_1; ++j) {
+ std::size_t index = (*it_c)->vertex(j)->data();
+ if (index != i)
+ incident_simplex.insert(index);
+ }
+ GUDHI_CHECK(incident_simplex.size() == cur_dim_plus_1 - 1,
+ std::logic_error("update_star: wrong size of incident simplex"));
+ star.push_back(incident_simplex);
+ }
+ }
+
+ // Estimates tangent subspaces using PCA
+
+ Tangent_space_basis compute_tangent_space(const Point &p
+ , const std::size_t i
+ , bool normalize_basis = true
+ , Orthogonal_space_basis *p_orth_space_basis = NULL
+ ) {
+ unsigned int num_pts_for_pca = (std::min)(static_cast<unsigned int> (std::pow(GUDHI_TC_BASE_VALUE_FOR_PCA, m_intrinsic_dim)),
+ static_cast<unsigned int> (m_points.size()));
+
+ // Kernel functors
+ typename K::Construct_vector_d constr_vec =
+ m_k.construct_vector_d_object();
+ typename K::Compute_coordinate_d coord =
+ m_k.compute_coordinate_d_object();
+
+#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+ KNS_range kns_range = m_points_ds_for_tse.query_k_nearest_neighbors(
+ p, num_pts_for_pca, false);
+ const Points &points_for_pca = m_points_for_tse;
+#else
+ KNS_range kns_range = m_points_ds.query_k_nearest_neighbors(p, num_pts_for_pca, false);
+ const Points &points_for_pca = m_points;
+#endif
+
+ // One row = one point
+ Eigen::MatrixXd mat_points(num_pts_for_pca, m_ambient_dim);
+ auto nn_it = kns_range.begin();
+ for (unsigned int j = 0;
+ j < num_pts_for_pca && nn_it != kns_range.end();
+ ++j, ++nn_it) {
+ for (int i = 0; i < m_ambient_dim; ++i) {
+ mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i));
+ }
+ }
+ Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean();
+ Eigen::MatrixXd cov = centered.adjoint() * centered;
+ Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eig(cov);
+
+ Tangent_space_basis tsb(i); // p = compute_perturbed_point(i) here
+
+ // The eigenvectors are sorted in increasing order of their corresponding
+ // eigenvalues
+ for (int j = m_ambient_dim - 1;
+ j >= m_ambient_dim - m_intrinsic_dim;
+ --j) {
+ if (normalize_basis) {
+ Vector v = constr_vec(m_ambient_dim,
+ eig.eigenvectors().col(j).data(),
+ eig.eigenvectors().col(j).data() + m_ambient_dim);
+ tsb.push_back(normalize_vector(v, m_k));
+ } else {
+ tsb.push_back(constr_vec(
+ m_ambient_dim,
+ eig.eigenvectors().col(j).data(),
+ eig.eigenvectors().col(j).data() + m_ambient_dim));
+ }
+ }
+
+ if (p_orth_space_basis) {
+ p_orth_space_basis->set_origin(i);
+ for (int j = m_ambient_dim - m_intrinsic_dim - 1;
+ j >= 0;
+ --j) {
+ if (normalize_basis) {
+ Vector v = constr_vec(m_ambient_dim,
+ eig.eigenvectors().col(j).data(),
+ eig.eigenvectors().col(j).data() + m_ambient_dim);
+ p_orth_space_basis->push_back(normalize_vector(v, m_k));
+ } else {
+ p_orth_space_basis->push_back(constr_vec(
+ m_ambient_dim,
+ eig.eigenvectors().col(j).data(),
+ eig.eigenvectors().col(j).data() + m_ambient_dim));
+ }
+ }
+ }
+
+ m_are_tangent_spaces_computed[i] = true;
+
+ return tsb;
+ }
+
+ // Compute the space tangent to a simplex (p1, p2, ... pn)
+ // TODO(CJ): Improve this?
+ // Basically, it takes all the neighbor points to p1, p2... pn and runs PCA
+ // on it. Note that most points are duplicated.
+
+ Tangent_space_basis compute_tangent_space(const Simplex &s, bool normalize_basis = true) {
+ unsigned int num_pts_for_pca = (std::min)(static_cast<unsigned int> (std::pow(GUDHI_TC_BASE_VALUE_FOR_PCA, m_intrinsic_dim)),
+ static_cast<unsigned int> (m_points.size()));
+
+ // Kernel functors
+ typename K::Construct_vector_d constr_vec =
+ m_k.construct_vector_d_object();
+ typename K::Compute_coordinate_d coord =
+ m_k.compute_coordinate_d_object();
+ typename K::Squared_length_d sqlen =
+ m_k.squared_length_d_object();
+ typename K::Scaled_vector_d scaled_vec =
+ m_k.scaled_vector_d_object();
+ typename K::Scalar_product_d scalar_pdct =
+ m_k.scalar_product_d_object();
+ typename K::Difference_of_vectors_d diff_vec =
+ m_k.difference_of_vectors_d_object();
+
+ // One row = one point
+ Eigen::MatrixXd mat_points(s.size() * num_pts_for_pca, m_ambient_dim);
+ unsigned int current_row = 0;
+
+ for (Simplex::const_iterator it_index = s.begin();
+ it_index != s.end(); ++it_index) {
+ const Point &p = m_points[*it_index];
+
+#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+ KNS_range kns_range = m_points_ds_for_tse.query_k_nearest_neighbors(
+ p, num_pts_for_pca, false);
+ const Points &points_for_pca = m_points_for_tse;
+#else
+ KNS_range kns_range = m_points_ds.query_k_nearest_neighbors(p, num_pts_for_pca, false);
+ const Points &points_for_pca = m_points;
+#endif
+
+ auto nn_it = kns_range.begin();
+ for (;
+ current_row < num_pts_for_pca && nn_it != kns_range.end();
+ ++current_row, ++nn_it) {
+ for (int i = 0; i < m_ambient_dim; ++i) {
+ mat_points(current_row, i) =
+ CGAL::to_double(coord(points_for_pca[nn_it->first], i));
+ }
+ }
+ }
+ Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean();
+ Eigen::MatrixXd cov = centered.adjoint() * centered;
+ Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eig(cov);
+
+ Tangent_space_basis tsb;
+
+ // The eigenvectors are sorted in increasing order of their corresponding
+ // eigenvalues
+ for (int j = m_ambient_dim - 1;
+ j >= m_ambient_dim - m_intrinsic_dim;
+ --j) {
+ if (normalize_basis) {
+ Vector v = constr_vec(m_ambient_dim,
+ eig.eigenvectors().col(j).data(),
+ eig.eigenvectors().col(j).data() + m_ambient_dim);
+ tsb.push_back(normalize_vector(v, m_k));
+ } else {
+ tsb.push_back(constr_vec(
+ m_ambient_dim,
+ eig.eigenvectors().col(j).data(),
+ eig.eigenvectors().col(j).data() + m_ambient_dim));
+ }
+ }
+
+ return tsb;
+ }
+
+ // Returns the dimension of the ith local triangulation
+
+ int tangent_basis_dim(std::size_t i) const {
+ return m_tangent_spaces[i].dimension();
+ }
+
+ Point compute_perturbed_point(std::size_t pt_idx) const {
+#ifdef GUDHI_TC_PERTURB_POSITION
+ return m_k.translated_point_d_object()(
+ m_points[pt_idx], m_translations[pt_idx]);
+#else
+ return m_points[pt_idx];
+#endif
+ }
+
+ void compute_perturbed_weighted_point(std::size_t pt_idx, Point &p, FT &w) const {
+#ifdef GUDHI_TC_PERTURB_POSITION
+ p = m_k.translated_point_d_object()(
+ m_points[pt_idx], m_translations[pt_idx]);
+#else
+ p = m_points[pt_idx];
+#endif
+ w = m_weights[pt_idx];
+ }
+
+ Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx) const {
+ typename K::Construct_weighted_point_d k_constr_wp =
+ m_k.construct_weighted_point_d_object();
+
+ Weighted_point wp = k_constr_wp(
+#ifdef GUDHI_TC_PERTURB_POSITION
+ m_k.translated_point_d_object()(m_points[pt_idx], m_translations[pt_idx]),
+#else
+ m_points[pt_idx],
+#endif
+ m_weights[pt_idx]);
+
+ return wp;
+ }
+
+ Point unproject_point(const Tr_point &p,
+ const Tangent_space_basis &tsb,
+ const Tr_traits &tr_traits) const {
+ typename K::Translated_point_d k_transl =
+ m_k.translated_point_d_object();
+ typename K::Scaled_vector_d k_scaled_vec =
+ m_k.scaled_vector_d_object();
+ typename Tr_traits::Compute_coordinate_d coord =
+ tr_traits.compute_coordinate_d_object();
+
+ Point global_point = compute_perturbed_point(tsb.origin());
+ for (int i = 0; i < m_intrinsic_dim; ++i)
+ global_point = k_transl(global_point,
+ k_scaled_vec(tsb[i], coord(p, i)));
+
+ return global_point;
+ }
+
+ // Project the point in the tangent space
+ // Resulting point coords are expressed in tsb's space
+ Tr_bare_point project_point(const Point &p,
+ const Tangent_space_basis &tsb,
+ const Tr_traits &tr_traits) const {
+ typename K::Scalar_product_d scalar_pdct =
+ m_k.scalar_product_d_object();
+ typename K::Difference_of_points_d diff_points =
+ m_k.difference_of_points_d_object();
+
+ Vector v = diff_points(p, compute_perturbed_point(tsb.origin()));
+
+ std::vector<FT> coords;
+ // Ambiant-space coords of the projected point
+ coords.reserve(tsb.dimension());
+ for (std::size_t i = 0; i < m_intrinsic_dim; ++i) {
+ // Local coords are given by the scalar product with the vectors of tsb
+ FT coord = scalar_pdct(v, tsb[i]);
+ coords.push_back(coord);
+ }
+
+ return tr_traits.construct_point_d_object()(
+ static_cast<int> (coords.size()), coords.begin(), coords.end());
+ }
+
+ // Project the point in the tangent space
+ // The weight will be the squared distance between p and the projection of p
+ // Resulting point coords are expressed in tsb's space
+
+ Tr_point project_point_and_compute_weight(const Weighted_point &wp,
+ const Tangent_space_basis &tsb,
+ const Tr_traits &tr_traits) const {
+ typename K::Point_drop_weight_d k_drop_w =
+ m_k.point_drop_weight_d_object();
+ typename K::Compute_weight_d k_point_weight =
+ m_k.compute_weight_d_object();
+ return project_point_and_compute_weight(
+ k_drop_w(wp), k_point_weight(wp), tsb, tr_traits);
+ }
+
+ // Same as above, with slightly different parameters
+ Tr_point project_point_and_compute_weight(const Point &p, const FT w,
+ const Tangent_space_basis &tsb,
+ const Tr_traits &tr_traits) const {
+ const int point_dim = m_k.point_dimension_d_object()(p);
+
+ typename K::Construct_point_d constr_pt =
+ m_k.construct_point_d_object();
+ typename K::Scalar_product_d scalar_pdct =
+ m_k.scalar_product_d_object();
+ typename K::Difference_of_points_d diff_points =
+ m_k.difference_of_points_d_object();
+ typename K::Compute_coordinate_d coord =
+ m_k.compute_coordinate_d_object();
+ typename K::Construct_cartesian_const_iterator_d ccci =
+ m_k.construct_cartesian_const_iterator_d_object();
+
+ Point origin = compute_perturbed_point(tsb.origin());
+ Vector v = diff_points(p, origin);
+
+ // Same dimension? Then the weight is 0
+ bool same_dim = (point_dim == tsb.dimension());
+
+ std::vector<FT> coords;
+ // Ambiant-space coords of the projected point
+ std::vector<FT> p_proj(ccci(origin), ccci(origin, 0));
+ coords.reserve(tsb.dimension());
+ for (int i = 0; i < tsb.dimension(); ++i) {
+ // Local coords are given by the scalar product with the vectors of tsb
+ FT c = scalar_pdct(v, tsb[i]);
+ coords.push_back(c);
+
+ // p_proj += c * tsb[i]
+ if (!same_dim) {
+ for (int j = 0; j < point_dim; ++j)
+ p_proj[j] += c * coord(tsb[i], j);
+ }
+ }
+
+ // Same dimension? Then the weight is 0
+ FT sq_dist_to_proj_pt = 0;
+ if (!same_dim) {
+ Point projected_pt = constr_pt(point_dim, p_proj.begin(), p_proj.end());
+ sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt);
+ }
+
+ return tr_traits.construct_weighted_point_d_object()
+ (tr_traits.construct_point_d_object()(static_cast<int> (coords.size()), coords.begin(), coords.end()),
+ w - sq_dist_to_proj_pt);
+ }
+
+ // Project all the points in the tangent space
+
+ template <typename Indexed_point_range>
+ std::vector<Tr_point> project_points_and_compute_weights(
+ const Indexed_point_range &point_indices,
+ const Tangent_space_basis &tsb,
+ const Tr_traits &tr_traits) const {
+ std::vector<Tr_point> ret;
+ for (typename Indexed_point_range::const_iterator
+ it = point_indices.begin(), it_end = point_indices.end();
+ it != it_end; ++it) {
+ ret.push_back(project_point_and_compute_weight(
+ compute_perturbed_weighted_point(*it), tsb, tr_traits));
+ }
+ return ret;
+ }
+
+ // A simplex here is a local tri's full cell handle
+
+ bool is_simplex_consistent(Tr_full_cell_handle fch, int cur_dim) const {
+ Simplex c;
+ for (int i = 0; i < cur_dim + 1; ++i) {
+ std::size_t data = fch->vertex(i)->data();
+ c.insert(data);
+ }
+ return is_simplex_consistent(c);
+ }
+
+ // A simplex here is a list of point indices
+ // TODO(CJ): improve it like the other "is_simplex_consistent" below
+
+ bool is_simplex_consistent(Simplex const& simplex) const {
+ // Check if the simplex is in the stars of all its vertices
+ Simplex::const_iterator it_point_idx = simplex.begin();
+ // For each point p of the simplex, we parse the incidents cells of p
+ // and we check if "simplex" is among them
+ for (; it_point_idx != simplex.end(); ++it_point_idx) {
+ std::size_t point_idx = *it_point_idx;
+ // Don't check infinite simplices
+ if (point_idx == (std::numeric_limits<std::size_t>::max)())
+ continue;
+
+ Star const& star = m_stars[point_idx];
+
+ // What we're looking for is "simplex" \ point_idx
+ Incident_simplex is_to_find = simplex;
+ is_to_find.erase(point_idx);
+
+ // For each cell
+ if (std::find(star.begin(), star.end(), is_to_find) == star.end())
+ return false;
+ }
+
+ return true;
+ }
+
+ // A simplex here is a list of point indices
+ // "s" contains all the points of the simplex except "center_point"
+ // This function returns the points whose star doesn't contain the simplex
+ // N.B.: the function assumes that the simplex is contained in
+ // star(center_point)
+
+ template <typename OutputIterator> // value_type = std::size_t
+ bool is_simplex_consistent(
+ std::size_t center_point,
+ Incident_simplex const& s, // without "center_point"
+ OutputIterator points_whose_star_does_not_contain_s,
+ bool check_also_in_non_maximal_faces = false) const {
+ Simplex full_simplex = s;
+ full_simplex.insert(center_point);
+
+ // Check if the simplex is in the stars of all its vertices
+ Incident_simplex::const_iterator it_point_idx = s.begin();
+ // For each point p of the simplex, we parse the incidents cells of p
+ // and we check if "simplex" is among them
+ for (; it_point_idx != s.end(); ++it_point_idx) {
+ std::size_t point_idx = *it_point_idx;
+ // Don't check infinite simplices
+ if (point_idx == (std::numeric_limits<std::size_t>::max)())
+ continue;
+
+ Star const& star = m_stars[point_idx];
+
+ // What we're looking for is full_simplex \ point_idx
+ Incident_simplex is_to_find = full_simplex;
+ is_to_find.erase(point_idx);
+
+ if (check_also_in_non_maximal_faces) {
+ // For each simplex "is" of the star, check if ic_to_simplex is
+ // included in "is"
+ bool found = false;
+ for (Star::const_iterator is = star.begin(), is_end = star.end();
+ !found && is != is_end; ++is) {
+ if (std::includes(is->begin(), is->end(),
+ is_to_find.begin(), is_to_find.end()))
+ found = true;
+ }
+
+ if (!found)
+ *points_whose_star_does_not_contain_s++ = point_idx;
+ } else {
+ // Does the star contain is_to_find?
+ if (std::find(star.begin(), star.end(), is_to_find) == star.end())
+ *points_whose_star_does_not_contain_s++ = point_idx;
+ }
+ }
+
+ return true;
+ }
+
+ // A simplex here is a list of point indices
+ // It looks for s in star(p).
+ // "s" contains all the points of the simplex except p.
+ bool is_simplex_in_star(std::size_t p,
+ Incident_simplex const& s,
+ bool check_also_in_non_maximal_faces = true) const {
+ Star const& star = m_stars[p];
+
+ if (check_also_in_non_maximal_faces) {
+ // For each simplex "is" of the star, check if ic_to_simplex is
+ // included in "is"
+ bool found = false;
+ for (Star::const_iterator is = star.begin(), is_end = star.end();
+ !found && is != is_end; ++is) {
+ if (std::includes(is->begin(), is->end(), s.begin(), s.end()))
+ found = true;
+ }
+
+ return found;
+ } else {
+ return !(std::find(star.begin(), star.end(), s) == star.end());
+ }
+ }
+
+#ifdef GUDHI_USE_TBB
+ // Functor for try_to_solve_inconsistencies_in_a_local_triangulation function
+ class Try_to_solve_inconsistencies_in_a_local_triangulation {
+ Tangential_complex & m_tc;
+ double m_max_perturb;
+ tbb::combinable<std::size_t> &m_num_inconsistencies;
+ tbb::combinable<std::vector<std::size_t> > &m_updated_points;
+
+ public:
+ // Constructor
+ Try_to_solve_inconsistencies_in_a_local_triangulation(Tangential_complex &tc,
+ double max_perturb,
+ tbb::combinable<std::size_t> &num_inconsistencies,
+ tbb::combinable<std::vector<std::size_t> > &updated_points)
+ : m_tc(tc),
+ m_max_perturb(max_perturb),
+ m_num_inconsistencies(num_inconsistencies),
+ m_updated_points(updated_points) { }
+
+ // Constructor
+ Try_to_solve_inconsistencies_in_a_local_triangulation(const Try_to_solve_inconsistencies_in_a_local_triangulation&
+ tsilt)
+ : m_tc(tsilt.m_tc),
+ m_max_perturb(tsilt.m_max_perturb),
+ m_num_inconsistencies(tsilt.m_num_inconsistencies),
+ m_updated_points(tsilt.m_updated_points) { }
+
+ // operator()
+ void operator()(const tbb::blocked_range<size_t>& r) const {
+ for (size_t i = r.begin(); i != r.end(); ++i) {
+ m_num_inconsistencies.local() +=
+ m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(i, m_max_perturb,
+ std::back_inserter(m_updated_points.local()));
+ }
+ }
+ };
+#endif // GUDHI_USE_TBB
+
+ void perturb(std::size_t point_idx, double max_perturb) {
+ const Tr_traits &local_tr_traits =
+ m_triangulations[point_idx].tr().geom_traits();
+ typename Tr_traits::Compute_coordinate_d coord =
+ local_tr_traits.compute_coordinate_d_object();
+ typename K::Translated_point_d k_transl =
+ m_k.translated_point_d_object();
+ typename K::Construct_vector_d k_constr_vec =
+ m_k.construct_vector_d_object();
+ typename K::Scaled_vector_d k_scaled_vec =
+ m_k.scaled_vector_d_object();
+
+ CGAL::Random_points_in_ball_d<Tr_bare_point>
+ tr_point_in_ball_generator(m_intrinsic_dim,
+ m_random_generator.get_double(0., max_perturb));
+
+ Tr_point local_random_transl =
+ local_tr_traits.construct_weighted_point_d_object()(*tr_point_in_ball_generator++, 0);
+ Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim);
+ const Tangent_space_basis &tsb = m_tangent_spaces[point_idx];
+ for (int i = 0; i < m_intrinsic_dim; ++i) {
+ global_transl = k_transl(global_transl,
+ k_scaled_vec(tsb[i], coord(local_random_transl, i)));
+ }
+ // Parallel
+#if defined(GUDHI_USE_TBB)
+ m_p_perturb_mutexes[point_idx].lock();
+ m_translations[point_idx] = global_transl;
+ m_p_perturb_mutexes[point_idx].unlock();
+ // Sequential
+#else
+ m_translations[point_idx] = global_transl;
+#endif
+ }
+
+ // Return true if inconsistencies were found
+ template <typename OutputIt>
+ bool try_to_solve_inconsistencies_in_a_local_triangulation(std::size_t tr_index,
+ double max_perturb,
+ OutputIt perturbed_pts_indices = CGAL::Emptyset_iterator()) {
+ bool is_inconsistent = false;
+
+ Star const& star = m_stars[tr_index];
+ Tr_vertex_handle center_vh = m_triangulations[tr_index].center_vertex();
+
+ // For each incident simplex
+ Star::const_iterator it_inc_simplex = star.begin();
+ Star::const_iterator it_inc_simplex_end = star.end();
+ for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
+ const Incident_simplex &incident_simplex = *it_inc_simplex;
+
+ // Don't check infinite cells
+ if (is_infinite(incident_simplex))
+ continue;
+
+ Simplex c = incident_simplex;
+ c.insert(tr_index); // Add the missing index
+
+ // Perturb the center point
+ if (!is_simplex_consistent(c)) {
+ is_inconsistent = true;
+
+ std::size_t idx = tr_index;
+
+ perturb(tr_index, max_perturb);
+ *perturbed_pts_indices++ = idx;
+
+ // We will try the other cells next time
+ break;
+ }
+ }
+
+ return is_inconsistent;
+ }
+
+
+ // 1st line: number of points
+ // Then one point per line
+ std::ostream &export_point_set(std::ostream & os,
+ bool use_perturbed_points = false,
+ const char *coord_separator = " ") const {
+ if (use_perturbed_points) {
+ std::vector<Point> perturbed_points;
+ perturbed_points.reserve(m_points.size());
+ for (std::size_t i = 0; i < m_points.size(); ++i)
+ perturbed_points.push_back(compute_perturbed_point(i));
+
+ return export_point_set(
+ m_k, perturbed_points, os, coord_separator);
+ } else {
+ return export_point_set(
+ m_k, m_points, os, coord_separator);
+ }
+ }
+
+ template<typename ProjectionFunctor = CGAL::Identity<Point> >
+ std::ostream &export_vertices_to_off(
+ std::ostream & os, std::size_t &num_vertices,
+ bool use_perturbed_points = false,
+ ProjectionFunctor const& point_projection = ProjectionFunctor()) const {
+ if (m_points.empty()) {
+ num_vertices = 0;
+ return os;
+ }
+
+ // If m_intrinsic_dim = 1, we output each point two times
+ // to be able to export each segment as a flat triangle with 3 different
+ // indices (otherwise, Meshlab detects degenerated simplices)
+ const int N = (m_intrinsic_dim == 1 ? 2 : 1);
+
+ // Kernel functors
+ typename K::Compute_coordinate_d coord =
+ m_k.compute_coordinate_d_object();
+
+#ifdef GUDHI_TC_EXPORT_ALL_COORDS_IN_OFF
+ int num_coords = m_ambient_dim;
+#else
+ int num_coords = (std::min)(m_ambient_dim, 3);
+#endif
+
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ OS_container::const_iterator it_os = m_orth_spaces.begin();
+#endif
+ typename Points::const_iterator it_p = m_points.begin();
+ typename Points::const_iterator it_p_end = m_points.end();
+ // For each point p
+ for (std::size_t i = 0; it_p != it_p_end; ++it_p, ++i) {
+ Point p = point_projection(
+ use_perturbed_points ? compute_perturbed_point(i) : *it_p);
+ for (int ii = 0; ii < N; ++ii) {
+ int j = 0;
+ for (; j < num_coords; ++j)
+ os << CGAL::to_double(coord(p, j)) << " ";
+ if (j == 2)
+ os << "0";
+
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ for (j = 0; j < num_coords; ++j)
+ os << " " << CGAL::to_double(coord(*it_os->begin(), j));
+#endif
+ os << "\n";
+ }
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ ++it_os;
+#endif
+ }
+
+ num_vertices = N * m_points.size();
+ return os;
+ }
+
+ std::ostream &export_simplices_to_off(std::ostream & os, std::size_t &num_OFF_simplices,
+ bool color_inconsistencies = false,
+ Simplex_set const *p_simpl_to_color_in_red = NULL,
+ Simplex_set const *p_simpl_to_color_in_green = NULL,
+ Simplex_set const *p_simpl_to_color_in_blue = NULL)
+ const {
+ // If m_intrinsic_dim = 1, each point is output two times
+ // (see export_vertices_to_off)
+ num_OFF_simplices = 0;
+ std::size_t num_maximal_simplices = 0;
+ std::size_t num_inconsistent_maximal_simplices = 0;
+ std::size_t num_inconsistent_stars = 0;
+ typename Tr_container::const_iterator it_tr = m_triangulations.begin();
+ typename Tr_container::const_iterator it_tr_end = m_triangulations.end();
+ // For each triangulation
+ for (std::size_t idx = 0; it_tr != it_tr_end; ++it_tr, ++idx) {
+ bool is_star_inconsistent = false;
+
+ Triangulation const& tr = it_tr->tr();
+ Tr_vertex_handle center_vh = it_tr->center_vertex();
+
+ if (tr.current_dimension() < m_intrinsic_dim)
+ continue;
+
+ // Color for this star
+ std::stringstream color;
+ // color << rand()%256 << " " << 100+rand()%156 << " " << 100+rand()%156;
+ color << 128 << " " << 128 << " " << 128;
+
+ // Gather the triangles here, with an int telling its color
+ typedef std::vector<std::pair<Simplex, int> > Star_using_triangles;
+ Star_using_triangles star_using_triangles;
+
+ // For each cell of the star
+ Star::const_iterator it_inc_simplex = m_stars[idx].begin();
+ Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
+ for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
+ Simplex c = *it_inc_simplex;
+ c.insert(idx);
+ std::size_t num_vertices = c.size();
+ ++num_maximal_simplices;
+
+ int color_simplex = -1; // -1=no color, 0=yellow, 1=red, 2=green, 3=blue
+ if (color_inconsistencies && !is_simplex_consistent(c)) {
+ ++num_inconsistent_maximal_simplices;
+ color_simplex = 0;
+ is_star_inconsistent = true;
+ } else {
+ if (p_simpl_to_color_in_red &&
+ std::find(
+ p_simpl_to_color_in_red->begin(),
+ p_simpl_to_color_in_red->end(),
+ c) != p_simpl_to_color_in_red->end()) {
+ color_simplex = 1;
+ } else if (p_simpl_to_color_in_green &&
+ std::find(
+ p_simpl_to_color_in_green->begin(),
+ p_simpl_to_color_in_green->end(),
+ c) != p_simpl_to_color_in_green->end()) {
+ color_simplex = 2;
+ } else if (p_simpl_to_color_in_blue &&
+ std::find(
+ p_simpl_to_color_in_blue->begin(),
+ p_simpl_to_color_in_blue->end(),
+ c) != p_simpl_to_color_in_blue->end()) {
+ color_simplex = 3;
+ }
+ }
+
+ // If m_intrinsic_dim = 1, each point is output two times,
+ // so we need to multiply each index by 2
+ // And if only 2 vertices, add a third one (each vertex is duplicated in
+ // the file when m_intrinsic dim = 2)
+ if (m_intrinsic_dim == 1) {
+ Simplex tmp_c;
+ Simplex::iterator it = c.begin();
+ for (; it != c.end(); ++it)
+ tmp_c.insert(*it * 2);
+ if (num_vertices == 2)
+ tmp_c.insert(*tmp_c.rbegin() + 1);
+
+ c = tmp_c;
+ }
+
+ if (num_vertices <= 3) {
+ star_using_triangles.push_back(std::make_pair(c, color_simplex));
+ } else {
+ // num_vertices >= 4: decompose the simplex in triangles
+ std::vector<bool> booleans(num_vertices, false);
+ std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true);
+ do {
+ Simplex triangle;
+ Simplex::iterator it = c.begin();
+ for (int i = 0; it != c.end(); ++i, ++it) {
+ if (booleans[i])
+ triangle.insert(*it);
+ }
+ star_using_triangles.push_back(
+ std::make_pair(triangle, color_simplex));
+ } while (std::next_permutation(booleans.begin(), booleans.end()));
+ }
+ }
+
+ // For each cell
+ Star_using_triangles::const_iterator it_simplex =
+ star_using_triangles.begin();
+ Star_using_triangles::const_iterator it_simplex_end =
+ star_using_triangles.end();
+ for (; it_simplex != it_simplex_end; ++it_simplex) {
+ const Simplex &c = it_simplex->first;
+
+ // Don't export infinite cells
+ if (is_infinite(c))
+ continue;
+
+ int color_simplex = it_simplex->second;
+
+ std::stringstream sstr_c;
+
+ Simplex::const_iterator it_point_idx = c.begin();
+ for (; it_point_idx != c.end(); ++it_point_idx) {
+ sstr_c << *it_point_idx << " ";
+ }
+
+ os << 3 << " " << sstr_c.str();
+ if (color_inconsistencies || p_simpl_to_color_in_red
+ || p_simpl_to_color_in_green || p_simpl_to_color_in_blue) {
+ switch (color_simplex) {
+ case 0: os << " 255 255 0";
+ break;
+ case 1: os << " 255 0 0";
+ break;
+ case 2: os << " 0 255 0";
+ break;
+ case 3: os << " 0 0 255";
+ break;
+ default: os << " " << color.str();
+ break;
+ }
+ }
+ ++num_OFF_simplices;
+ os << "\n";
+ }
+ if (is_star_inconsistent)
+ ++num_inconsistent_stars;
+ }
+
+#ifdef DEBUG_TRACES
+ std::cerr
+ << "\n==========================================================\n"
+ << "Export from list of stars to OFF:\n"
+ << " * Number of vertices: " << m_points.size() << "\n"
+ << " * Total number of maximal simplices: " << num_maximal_simplices
+ << "\n";
+ if (color_inconsistencies) {
+ std::cerr
+ << " * Number of inconsistent stars: "
+ << num_inconsistent_stars << " ("
+ << (m_points.size() > 0 ?
+ 100. * num_inconsistent_stars / m_points.size() : 0.) << "%)\n"
+ << " * Number of inconsistent maximal simplices: "
+ << num_inconsistent_maximal_simplices << " ("
+ << (num_maximal_simplices > 0 ?
+ 100. * num_inconsistent_maximal_simplices / num_maximal_simplices
+ : 0.) << "%)\n";
+ }
+ std::cerr << "==========================================================\n";
+#endif
+
+ return os;
+ }
+
+ public:
+ std::ostream &export_simplices_to_off(
+ const Simplicial_complex &complex,
+ std::ostream & os, std::size_t &num_OFF_simplices,
+ Simplex_set const *p_simpl_to_color_in_red = NULL,
+ Simplex_set const *p_simpl_to_color_in_green = NULL,
+ Simplex_set const *p_simpl_to_color_in_blue = NULL)
+ const {
+ typedef Simplicial_complex::Simplex Simplex;
+ typedef Simplicial_complex::Simplex_set Simplex_set;
+
+ // If m_intrinsic_dim = 1, each point is output two times
+ // (see export_vertices_to_off)
+ num_OFF_simplices = 0;
+ std::size_t num_maximal_simplices = 0;
+
+ typename Simplex_set::const_iterator it_s =
+ complex.simplex_range().begin();
+ typename Simplex_set::const_iterator it_s_end =
+ complex.simplex_range().end();
+ // For each simplex
+ for (; it_s != it_s_end; ++it_s) {
+ Simplex c = *it_s;
+ ++num_maximal_simplices;
+
+ int color_simplex = -1; // -1=no color, 0=yellow, 1=red, 2=green, 3=blue
+ if (p_simpl_to_color_in_red &&
+ std::find(
+ p_simpl_to_color_in_red->begin(),
+ p_simpl_to_color_in_red->end(),
+ c) != p_simpl_to_color_in_red->end()) {
+ color_simplex = 1;
+ } else if (p_simpl_to_color_in_green &&
+ std::find(p_simpl_to_color_in_green->begin(),
+ p_simpl_to_color_in_green->end(),
+ c) != p_simpl_to_color_in_green->end()) {
+ color_simplex = 2;
+ } else if (p_simpl_to_color_in_blue &&
+ std::find(p_simpl_to_color_in_blue->begin(),
+ p_simpl_to_color_in_blue->end(),
+ c) != p_simpl_to_color_in_blue->end()) {
+ color_simplex = 3;
+ }
+
+ // Gather the triangles here
+ typedef std::vector<Simplex> Triangles;
+ Triangles triangles;
+
+ int num_vertices = static_cast<int>(c.size());
+ // Do not export smaller dimension simplices
+ if (num_vertices < m_intrinsic_dim + 1)
+ continue;
+
+ // If m_intrinsic_dim = 1, each point is output two times,
+ // so we need to multiply each index by 2
+ // And if only 2 vertices, add a third one (each vertex is duplicated in
+ // the file when m_intrinsic dim = 2)
+ if (m_intrinsic_dim == 1) {
+ Simplex tmp_c;
+ Simplex::iterator it = c.begin();
+ for (; it != c.end(); ++it)
+ tmp_c.insert(*it * 2);
+ if (num_vertices == 2)
+ tmp_c.insert(*tmp_c.rbegin() + 1);
+
+ c = tmp_c;
+ }
+
+ if (num_vertices <= 3) {
+ triangles.push_back(c);
+ } else {
+ // num_vertices >= 4: decompose the simplex in triangles
+ std::vector<bool> booleans(num_vertices, false);
+ std::fill(booleans.begin() + num_vertices - 3, booleans.end(), true);
+ do {
+ Simplex triangle;
+ Simplex::iterator it = c.begin();
+ for (int i = 0; it != c.end(); ++i, ++it) {
+ if (booleans[i])
+ triangle.insert(*it);
+ }
+ triangles.push_back(triangle);
+ } while (std::next_permutation(booleans.begin(), booleans.end()));
+ }
+
+ // For each cell
+ Triangles::const_iterator it_tri = triangles.begin();
+ Triangles::const_iterator it_tri_end = triangles.end();
+ for (; it_tri != it_tri_end; ++it_tri) {
+ // Don't export infinite cells
+ if (is_infinite(*it_tri))
+ continue;
+
+ os << 3 << " ";
+ Simplex::const_iterator it_point_idx = it_tri->begin();
+ for (; it_point_idx != it_tri->end(); ++it_point_idx) {
+ os << *it_point_idx << " ";
+ }
+
+ if (p_simpl_to_color_in_red || p_simpl_to_color_in_green
+ || p_simpl_to_color_in_blue) {
+ switch (color_simplex) {
+ case 0: os << " 255 255 0";
+ break;
+ case 1: os << " 255 0 0";
+ break;
+ case 2: os << " 0 255 0";
+ break;
+ case 3: os << " 0 0 255";
+ break;
+ default: os << " 128 128 128";
+ break;
+ }
+ }
+
+ ++num_OFF_simplices;
+ os << "\n";
+ }
+ }
+
+#ifdef DEBUG_TRACES
+ std::cerr
+ << "\n==========================================================\n"
+ << "Export from complex to OFF:\n"
+ << " * Number of vertices: " << m_points.size() << "\n"
+ << " * Total number of maximal simplices: " << num_maximal_simplices
+ << "\n"
+ << "==========================================================\n";
+#endif
+
+ return os;
+ }
+
+ private:
+ const K m_k;
+ const int m_intrinsic_dim;
+ const int m_ambient_dim;
+
+ Points m_points;
+ Weights m_weights;
+#ifdef GUDHI_TC_PERTURB_POSITION
+ Translations_for_perturb m_translations;
+#if defined(GUDHI_USE_TBB)
+ Mutex_for_perturb *m_p_perturb_mutexes;
+#endif
+#endif
+
+ Points_ds m_points_ds;
+ double m_last_max_perturb;
+ std::vector<bool> m_are_tangent_spaces_computed;
+ TS_container m_tangent_spaces;
+#ifdef GUDHI_TC_EXPORT_NORMALS
+ OS_container m_orth_spaces;
+#endif
+ Tr_container m_triangulations; // Contains the triangulations
+ // and their center vertex
+ Stars_container m_stars;
+ std::vector<FT> m_squared_star_spheres_radii_incl_margin;
+
+#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+ Points m_points_for_tse;
+ Points_ds m_points_ds_for_tse;
+#endif
+
+ mutable CGAL::Random m_random_generator;
+}; // /class Tangential_complex
+
+} // end namespace tangential_complex
+} // end namespace Gudhi
+
+#endif // TANGENTIAL_COMPLEX_H_
diff --git a/include/gudhi/Tangential_complex/Simplicial_complex.h b/include/gudhi/Tangential_complex/Simplicial_complex.h
new file mode 100644
index 00000000..65c74ca5
--- /dev/null
+++ b/include/gudhi/Tangential_complex/Simplicial_complex.h
@@ -0,0 +1,539 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TANGENTIAL_COMPLEX_SIMPLICIAL_COMPLEX_H_
+#define TANGENTIAL_COMPLEX_SIMPLICIAL_COMPLEX_H_
+
+#include <gudhi/Tangential_complex/config.h>
+#include <gudhi/Tangential_complex/utilities.h>
+#include <gudhi/Debug_utils.h>
+#include <gudhi/console_color.h>
+
+#include <CGAL/iterator.h>
+
+// For is_pure_pseudomanifold
+#include <boost/graph/graph_traits.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/connected_components.hpp>
+#include <boost/container/flat_set.hpp>
+
+#include <algorithm>
+#include <string>
+#include <fstream>
+#include <map> // for map<>
+#include <vector> // for vector<>
+#include <set> // for set<>
+
+namespace Gudhi {
+namespace tangential_complex {
+namespace internal {
+
+class Simplicial_complex {
+ public:
+ typedef boost::container::flat_set<std::size_t> Simplex;
+ typedef std::set<Simplex> Simplex_set;
+
+ // If perform_checks = true, the function:
+ // - won't insert the simplex if it is already in a higher dim simplex
+ // - will erase any lower-dim simplices that are faces of the new simplex
+ // Returns true if the simplex was added
+ bool add_simplex(
+ const Simplex &s, bool perform_checks = true) {
+ if (perform_checks) {
+ unsigned int num_pts = static_cast<int> (s.size());
+ std::vector<Complex::iterator> to_erase;
+ bool check_higher_dim_simpl = true;
+ for (Complex::iterator it_simplex = m_complex.begin(),
+ it_simplex_end = m_complex.end();
+ it_simplex != it_simplex_end;
+ ++it_simplex) {
+ // Check if the simplex is not already in a higher dim simplex
+ if (check_higher_dim_simpl
+ && it_simplex->size() > num_pts
+ && std::includes(it_simplex->begin(), it_simplex->end(),
+ s.begin(), s.end())) {
+ // No need to insert it, then
+ return false;
+ }
+ // Check if the simplex includes some lower-dim simplices
+ if (it_simplex->size() < num_pts
+ && std::includes(s.begin(), s.end(),
+ it_simplex->begin(), it_simplex->end())) {
+ to_erase.push_back(it_simplex);
+ // We don't need to check higher-sim simplices any more
+ check_higher_dim_simpl = false;
+ }
+ }
+ for (std::vector<Complex::iterator>::const_iterator it = to_erase.begin();
+ it != to_erase.end(); ++it) {
+ m_complex.erase(*it);
+ }
+ }
+ return m_complex.insert(s).second;
+ }
+
+ const Simplex_set &simplex_range() const {
+ return m_complex;
+ }
+
+ bool empty() {
+ return m_complex.empty();
+ }
+
+ void clear() {
+ m_complex.clear();
+ }
+
+ template <typename Test, typename Output_it>
+ void get_simplices_matching_test(Test test, Output_it out) {
+ for (Complex::const_iterator it_simplex = m_complex.begin(),
+ it_simplex_end = m_complex.end();
+ it_simplex != it_simplex_end;
+ ++it_simplex) {
+ if (test(*it_simplex))
+ *out++ = *it_simplex;
+ }
+ }
+
+ // When a simplex S has only one co-face C, we can remove S and C
+ // without changing the topology
+
+ void collapse(int max_simplex_dim, bool quiet = false) {
+#ifdef DEBUG_TRACES
+ if (!quiet)
+ std::cerr << "Collapsing... ";
+#endif
+ // We note k = max_simplex_dim - 1
+ int k = max_simplex_dim - 1;
+
+ typedef Complex::iterator Simplex_iterator;
+ typedef std::vector<Simplex_iterator> Simplex_iterator_list;
+ typedef std::map<Simplex, Simplex_iterator_list> Cofaces_map;
+
+ std::size_t num_collapsed_maximal_simplices = 0;
+ do {
+ num_collapsed_maximal_simplices = 0;
+ // Create a map associating each non-maximal k-faces to the list of its
+ // maximal cofaces
+ Cofaces_map cofaces_map;
+ for (Complex::const_iterator it_simplex = m_complex.begin(),
+ it_simplex_end = m_complex.end();
+ it_simplex != it_simplex_end;
+ ++it_simplex) {
+ if (static_cast<int> (it_simplex->size()) > k + 1) {
+ std::vector<Simplex> k_faces;
+ // Get the k-faces composing the simplex
+ combinations(*it_simplex, k + 1, std::back_inserter(k_faces));
+ for (const auto &comb : k_faces)
+ cofaces_map[comb].push_back(it_simplex);
+ }
+ }
+
+ // For each non-maximal k-face F, if F has only one maximal coface Cf:
+ // - Look for the other k-faces F2, F3... of Cf in the map and:
+ // * if the list contains only Cf, clear the list (we don't remove the
+ // list since it creates troubles with the iterators) and add the F2,
+ // F3... to the complex
+ // * otherwise, remove Cf from the associated list
+ // - Remove Cf from the complex
+ for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(),
+ it_map_end = cofaces_map.end();
+ it_map_elt != it_map_end;
+ ++it_map_elt) {
+ if (it_map_elt->second.size() == 1) {
+ std::vector<Simplex> k_faces;
+ const Simplex_iterator_list::value_type &it_Cf =
+ *it_map_elt->second.begin();
+ GUDHI_CHECK(it_Cf->size() == max_simplex_dim + 1,
+ std::logic_error("Wrong dimension"));
+ // Get the k-faces composing the simplex
+ combinations(*it_Cf, k + 1, std::back_inserter(k_faces));
+ for (const auto &f2 : k_faces) {
+ // Skip F
+ if (f2 != it_map_elt->first) {
+ Cofaces_map::iterator it_comb_in_map = cofaces_map.find(f2);
+ if (it_comb_in_map->second.size() == 1) {
+ it_comb_in_map->second.clear();
+ m_complex.insert(f2);
+ } else { // it_comb_in_map->second.size() > 1
+ Simplex_iterator_list::iterator it = std::find(it_comb_in_map->second.begin(),
+ it_comb_in_map->second.end(),
+ it_Cf);
+ GUDHI_CHECK(it != it_comb_in_map->second.end(),
+ std::logic_error("Error: it == it_comb_in_map->second.end()"));
+ it_comb_in_map->second.erase(it);
+ }
+ }
+ }
+ m_complex.erase(it_Cf);
+ ++num_collapsed_maximal_simplices;
+ }
+ }
+ // Repeat until no maximal simplex got removed
+ } while (num_collapsed_maximal_simplices > 0);
+
+ // Collapse the lower dimension simplices
+ if (k > 0)
+ collapse(max_simplex_dim - 1, true);
+
+#ifdef DEBUG_TRACES
+ if (!quiet)
+ std::cerr << "done.\n";
+#endif
+ }
+
+ void display_stats() const {
+ std::cerr << yellow << "Complex stats:\n" << white;
+
+ if (m_complex.empty()) {
+ std::cerr << " * No simplices.\n";
+ } else {
+ // Number of simplex for each dimension
+ std::map<int, std::size_t> simplex_stats;
+
+ for (Complex::const_iterator it_simplex = m_complex.begin(),
+ it_simplex_end = m_complex.end();
+ it_simplex != it_simplex_end;
+ ++it_simplex) {
+ ++simplex_stats[static_cast<int> (it_simplex->size()) - 1];
+ }
+
+ for (std::map<int, std::size_t>::const_iterator it_map = simplex_stats.begin();
+ it_map != simplex_stats.end(); ++it_map) {
+ std::cerr << " * " << it_map->first << "-simplices: "
+ << it_map->second << "\n";
+ }
+ }
+ }
+
+ // verbose_level = 0, 1 or 2
+ bool is_pure_pseudomanifold__do_not_check_if_stars_are_connected(int simplex_dim,
+ bool allow_borders = false,
+ bool exit_at_the_first_problem = false,
+ int verbose_level = 0,
+ std::size_t *p_num_wrong_dim_simplices = NULL,
+ std::size_t *p_num_wrong_number_of_cofaces = NULL) const {
+ typedef Simplex K_1_face;
+ typedef std::map<K_1_face, std::size_t> Cofaces_map;
+
+ std::size_t num_wrong_dim_simplices = 0;
+ std::size_t num_wrong_number_of_cofaces = 0;
+
+ // Counts the number of cofaces of each K_1_face
+
+ // Create a map associating each non-maximal k-faces to the list of its
+ // maximal cofaces
+ Cofaces_map cofaces_map;
+ for (Complex::const_iterator it_simplex = m_complex.begin(),
+ it_simplex_end = m_complex.end();
+ it_simplex != it_simplex_end;
+ ++it_simplex) {
+ if (static_cast<int> (it_simplex->size()) != simplex_dim + 1) {
+ if (verbose_level >= 2)
+ std::cerr << "Found a simplex with dim = "
+ << it_simplex->size() - 1 << "\n";
+ ++num_wrong_dim_simplices;
+ } else {
+ std::vector<K_1_face> k_1_faces;
+ // Get the facets composing the simplex
+ combinations(
+ *it_simplex, simplex_dim, std::back_inserter(k_1_faces));
+ for (const auto &k_1_face : k_1_faces) {
+ ++cofaces_map[k_1_face];
+ }
+ }
+ }
+
+ for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(),
+ it_map_end = cofaces_map.end();
+ it_map_elt != it_map_end;
+ ++it_map_elt) {
+ if (it_map_elt->second != 2
+ && (!allow_borders || it_map_elt->second != 1)) {
+ if (verbose_level >= 2)
+ std::cerr << "Found a k-1-face with "
+ << it_map_elt->second << " cofaces\n";
+
+ if (exit_at_the_first_problem)
+ return false;
+ else
+ ++num_wrong_number_of_cofaces;
+ }
+ }
+
+ bool ret = num_wrong_dim_simplices == 0 && num_wrong_number_of_cofaces == 0;
+
+ if (verbose_level >= 1) {
+ std::cerr << "Pure pseudo-manifold: ";
+ if (ret) {
+ std::cerr << green << "YES" << white << "\n";
+ } else {
+ std::cerr << red << "NO" << white << "\n"
+ << " * Number of wrong dimension simplices: "
+ << num_wrong_dim_simplices << "\n"
+ << " * Number of wrong number of cofaces: "
+ << num_wrong_number_of_cofaces << "\n";
+ }
+ }
+
+ if (p_num_wrong_dim_simplices)
+ *p_num_wrong_dim_simplices = num_wrong_dim_simplices;
+ if (p_num_wrong_number_of_cofaces)
+ *p_num_wrong_number_of_cofaces = num_wrong_number_of_cofaces;
+
+ return ret;
+ }
+
+ template <int K>
+ std::size_t num_K_simplices() const {
+ Simplex_set k_simplices;
+
+ for (Complex::const_iterator it_simplex = m_complex.begin(),
+ it_simplex_end = m_complex.end();
+ it_simplex != it_simplex_end;
+ ++it_simplex) {
+ if (it_simplex->size() == K + 1) {
+ k_simplices.insert(*it_simplex);
+ } else if (it_simplex->size() > K + 1) {
+ // Get the k-faces composing the simplex
+ combinations(
+ *it_simplex, K + 1, std::inserter(k_simplices, k_simplices.begin()));
+ }
+ }
+
+ return k_simplices.size();
+ }
+
+ std::ptrdiff_t euler_characteristic(bool verbose = false) const {
+ if (verbose)
+ std::cerr << "\nComputing Euler characteristic of the complex...\n";
+
+ std::size_t num_vertices = num_K_simplices<0>();
+ std::size_t num_edges = num_K_simplices<1>();
+ std::size_t num_triangles = num_K_simplices<2>();
+
+ std::ptrdiff_t ec =
+ (std::ptrdiff_t) num_vertices
+ - (std::ptrdiff_t) num_edges
+ + (std::ptrdiff_t) num_triangles;
+
+ if (verbose)
+ std::cerr << "Euler characteristic: V - E + F = "
+ << num_vertices << " - " << num_edges << " + " << num_triangles << " = "
+ << blue
+ << ec
+ << white << "\n";
+
+ return ec;
+ }
+
+ // TODO(CJ): ADD COMMENTS
+
+ bool is_pure_pseudomanifold(
+ int simplex_dim,
+ std::size_t num_vertices,
+ bool allow_borders = false,
+ bool exit_at_the_first_problem = false,
+ int verbose_level = 0,
+ std::size_t *p_num_wrong_dim_simplices = NULL,
+ std::size_t *p_num_wrong_number_of_cofaces = NULL,
+ std::size_t *p_num_unconnected_stars = NULL,
+ Simplex_set *p_wrong_dim_simplices = NULL,
+ Simplex_set *p_wrong_number_of_cofaces_simplices = NULL,
+ Simplex_set *p_unconnected_stars_simplices = NULL) const {
+ // If simplex_dim == 1, we do not need to check if stars are connected
+ if (simplex_dim == 1) {
+ if (p_num_unconnected_stars)
+ *p_num_unconnected_stars = 0;
+ return is_pure_pseudomanifold__do_not_check_if_stars_are_connected(simplex_dim,
+ allow_borders,
+ exit_at_the_first_problem,
+ verbose_level,
+ p_num_wrong_dim_simplices,
+ p_num_wrong_number_of_cofaces);
+ }
+ // Associates each vertex (= the index in the vector)
+ // to its star (list of simplices)
+ typedef std::vector<std::vector<Complex::const_iterator> > Stars;
+ std::size_t num_wrong_dim_simplices = 0;
+ std::size_t num_wrong_number_of_cofaces = 0;
+ std::size_t num_unconnected_stars = 0;
+
+ // Fills a Stars data structure
+ Stars stars;
+ stars.resize(num_vertices);
+ for (Complex::const_iterator it_simplex = m_complex.begin(),
+ it_simplex_end = m_complex.end();
+ it_simplex != it_simplex_end;
+ ++it_simplex) {
+ if (static_cast<int> (it_simplex->size()) != simplex_dim + 1) {
+ if (verbose_level >= 2)
+ std::cerr << "Found a simplex with dim = "
+ << it_simplex->size() - 1 << "\n";
+ ++num_wrong_dim_simplices;
+ if (p_wrong_dim_simplices)
+ p_wrong_dim_simplices->insert(*it_simplex);
+ } else {
+ for (Simplex::const_iterator it_point_idx = it_simplex->begin();
+ it_point_idx != it_simplex->end();
+ ++it_point_idx) {
+ stars[*it_point_idx].push_back(it_simplex);
+ }
+ }
+ }
+
+ // Now, for each star, we have a vector of its d-simplices
+ // i.e. one index for each d-simplex
+ // Boost Graph only deals with indexes, so we also need indexes for the
+ // (d-1)-simplices
+ std::size_t center_vertex_index = 0;
+ for (Stars::const_iterator it_star = stars.begin();
+ it_star != stars.end();
+ ++it_star, ++center_vertex_index) {
+ typedef std::map<Simplex, std::vector<std::size_t> >
+ Dm1_faces_to_adj_D_faces;
+ Dm1_faces_to_adj_D_faces dm1_faces_to_adj_d_faces;
+
+ for (std::size_t i_dsimpl = 0; i_dsimpl < it_star->size(); ++i_dsimpl) {
+ Simplex dm1_simpl_of_link = *((*it_star)[i_dsimpl]);
+ dm1_simpl_of_link.erase(center_vertex_index);
+ // Copy it to a vector so that we can use operator[] on it
+ std::vector<std::size_t> dm1_simpl_of_link_vec(
+ dm1_simpl_of_link.begin(), dm1_simpl_of_link.end());
+
+ CGAL::Combination_enumerator<int> dm2_simplices(
+ simplex_dim - 1, 0, simplex_dim);
+ for (; !dm2_simplices.finished(); ++dm2_simplices) {
+ Simplex dm2_simpl;
+ for (int j = 0; j < simplex_dim - 1; ++j)
+ dm2_simpl.insert(dm1_simpl_of_link_vec[dm2_simplices[j]]);
+ dm1_faces_to_adj_d_faces[dm2_simpl].push_back(i_dsimpl);
+ }
+ }
+
+ Adj_graph adj_graph;
+ std::vector<Graph_vertex> d_faces_descriptors;
+ d_faces_descriptors.resize(it_star->size());
+ for (std::size_t j = 0; j < it_star->size(); ++j)
+ d_faces_descriptors[j] = boost::add_vertex(adj_graph);
+
+ Dm1_faces_to_adj_D_faces::const_iterator dm1_to_d_it =
+ dm1_faces_to_adj_d_faces.begin();
+ Dm1_faces_to_adj_D_faces::const_iterator dm1_to_d_it_end =
+ dm1_faces_to_adj_d_faces.end();
+ for (std::size_t i_km1_face = 0;
+ dm1_to_d_it != dm1_to_d_it_end;
+ ++dm1_to_d_it, ++i_km1_face) {
+ Graph_vertex km1_gv = boost::add_vertex(adj_graph);
+
+ for (std::vector<std::size_t>::const_iterator kface_it =
+ dm1_to_d_it->second.begin();
+ kface_it != dm1_to_d_it->second.end();
+ ++kface_it) {
+ boost::add_edge(km1_gv, *kface_it, adj_graph);
+ }
+
+ if (dm1_to_d_it->second.size() != 2
+ && (!allow_borders || dm1_to_d_it->second.size() != 1)) {
+ ++num_wrong_number_of_cofaces;
+ if (p_wrong_number_of_cofaces_simplices) {
+ for (auto idx : dm1_to_d_it->second)
+ p_wrong_number_of_cofaces_simplices->insert(*((*it_star)[idx]));
+ }
+ }
+ }
+
+ // What is left is to check the connexity
+ bool is_connected = true;
+ if (boost::num_vertices(adj_graph) > 0) {
+ std::vector<int> components(boost::num_vertices(adj_graph));
+ is_connected =
+ (boost::connected_components(adj_graph, &components[0]) == 1);
+ }
+
+ if (!is_connected) {
+ if (verbose_level >= 2)
+ std::cerr << "Error: star #" << center_vertex_index
+ << " is not connected\n";
+ ++num_unconnected_stars;
+ if (p_unconnected_stars_simplices) {
+ for (std::vector<Complex::const_iterator>::const_iterator
+ it_simpl = it_star->begin(),
+ it_simpl_end = it_star->end();
+ it_simpl != it_simpl_end;
+ ++it_simpl) {
+ p_unconnected_stars_simplices->insert(**it_simpl);
+ }
+ }
+ }
+ }
+
+ // Each one has been counted several times ("simplex_dim" times)
+ num_wrong_number_of_cofaces /= simplex_dim;
+
+ bool ret =
+ num_wrong_dim_simplices == 0
+ && num_wrong_number_of_cofaces == 0
+ && num_unconnected_stars == 0;
+
+ if (verbose_level >= 1) {
+ std::cerr << "Pure pseudo-manifold: ";
+ if (ret) {
+ std::cerr << green << "YES" << white << "\n";
+ } else {
+ std::cerr << red << "NO" << white << "\n"
+ << " * Number of wrong dimension simplices: "
+ << num_wrong_dim_simplices << "\n"
+ << " * Number of wrong number of cofaces: "
+ << num_wrong_number_of_cofaces << "\n"
+ << " * Number of not-connected stars: "
+ << num_unconnected_stars << "\n";
+ }
+ }
+
+ if (p_num_wrong_dim_simplices)
+ *p_num_wrong_dim_simplices = num_wrong_dim_simplices;
+ if (p_num_wrong_number_of_cofaces)
+ *p_num_wrong_number_of_cofaces = num_wrong_number_of_cofaces;
+ if (p_num_unconnected_stars)
+ *p_num_unconnected_stars = num_unconnected_stars;
+
+ return ret;
+ }
+
+ private:
+ typedef Simplex_set Complex;
+
+ // graph is an adjacency list
+ typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS> Adj_graph;
+ // map that gives to a certain simplex its node in graph and its dimension
+ typedef boost::graph_traits<Adj_graph>::vertex_descriptor Graph_vertex;
+ typedef boost::graph_traits<Adj_graph>::edge_descriptor Graph_edge;
+
+ Complex m_complex;
+}; // class Simplicial_complex
+
+} // namespace internal
+} // namespace tangential_complex
+} // namespace Gudhi
+
+#endif // TANGENTIAL_COMPLEX_SIMPLICIAL_COMPLEX_H_
diff --git a/include/gudhi/Tangential_complex/config.h b/include/gudhi/Tangential_complex/config.h
new file mode 100644
index 00000000..ffefcd6b
--- /dev/null
+++ b/include/gudhi/Tangential_complex/config.h
@@ -0,0 +1,43 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TANGENTIAL_COMPLEX_CONFIG_H_
+#define TANGENTIAL_COMPLEX_CONFIG_H_
+
+#include <cstddef>
+
+// ========================= Debugging & profiling =============================
+// #define GUDHI_TC_PROFILING
+// #define GUDHI_TC_VERY_VERBOSE
+// #define GUDHI_TC_PERFORM_EXTRA_CHECKS
+// #define GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES
+
+// ========================= Strategy ==========================================
+#define GUDHI_TC_PERTURB_POSITION
+// #define GUDHI_TC_PERTURB_WEIGHT
+
+// ========================= Parameters ========================================
+
+// PCA will use GUDHI_TC_BASE_VALUE_FOR_PCA^intrinsic_dim points
+const std::size_t GUDHI_TC_BASE_VALUE_FOR_PCA = 5;
+
+#endif // TANGENTIAL_COMPLEX_CONFIG_H_
diff --git a/include/gudhi/Tangential_complex/utilities.h b/include/gudhi/Tangential_complex/utilities.h
new file mode 100644
index 00000000..b2d6d674
--- /dev/null
+++ b/include/gudhi/Tangential_complex/utilities.h
@@ -0,0 +1,195 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TANGENTIAL_COMPLEX_UTILITIES_H_
+#define TANGENTIAL_COMPLEX_UTILITIES_H_
+
+#include <CGAL/Dimension.h>
+#include <CGAL/Combination_enumerator.h>
+#include <CGAL/IO/Triangulation_off_ostream.h>
+
+#include <boost/container/flat_set.hpp>
+
+#include <Eigen/Core>
+#include <Eigen/Eigen>
+
+#include <set>
+#include <vector>
+#include <array>
+#include <fstream>
+#include <atomic>
+#include <cmath> // for std::sqrt
+
+namespace Gudhi {
+namespace tangential_complex {
+namespace internal {
+
+// Provides copy constructors to std::atomic so that
+// it can be used in a vector
+template <typename T>
+struct Atomic_wrapper
+: public std::atomic<T> {
+ typedef std::atomic<T> Base;
+
+ Atomic_wrapper() { }
+
+ Atomic_wrapper(const T &t) : Base(t) { }
+
+ Atomic_wrapper(const std::atomic<T> &a) : Base(a.load()) { }
+
+ Atomic_wrapper(const Atomic_wrapper &other) : Base(other.load()) { }
+
+ Atomic_wrapper &operator=(const T &other) {
+ Base::store(other);
+ return *this;
+ }
+
+ Atomic_wrapper &operator=(const std::atomic<T> &other) {
+ Base::store(other.load());
+ return *this;
+ }
+
+ Atomic_wrapper &operator=(const Atomic_wrapper &other) {
+ Base::store(other.load());
+ return *this;
+ }
+};
+
+// Modifies v in-place
+template <typename K>
+typename K::Vector_d& normalize_vector(typename K::Vector_d& v,
+ K const& k) {
+ v = k.scaled_vector_d_object()(
+ v, typename K::FT(1) / std::sqrt(k.squared_length_d_object()(v)));
+ return v;
+}
+
+template<typename Kernel>
+struct Basis {
+ typedef typename Kernel::FT FT;
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::Vector_d Vector;
+ typedef typename std::vector<Vector>::const_iterator const_iterator;
+
+ std::size_t m_origin;
+ std::vector<Vector> m_vectors;
+
+ std::size_t origin() const {
+ return m_origin;
+ }
+
+ void set_origin(std::size_t o) {
+ m_origin = o;
+ }
+
+ const_iterator begin() const {
+ return m_vectors.begin();
+ }
+
+ const_iterator end() const {
+ return m_vectors.end();
+ }
+
+ std::size_t size() const {
+ return m_vectors.size();
+ }
+
+ Vector& operator[](const std::size_t i) {
+ return m_vectors[i];
+ }
+
+ const Vector& operator[](const std::size_t i) const {
+ return m_vectors[i];
+ }
+
+ void push_back(const Vector& v) {
+ m_vectors.push_back(v);
+ }
+
+ void reserve(const std::size_t s) {
+ m_vectors.reserve(s);
+ }
+
+ Basis() { }
+
+ Basis(std::size_t origin) : m_origin(origin) { }
+
+ Basis(std::size_t origin, const std::vector<Vector>& vectors)
+ : m_origin(origin), m_vectors(vectors) { }
+
+ int dimension() const {
+ return static_cast<int> (m_vectors.size());
+ }
+};
+
+// 1st line: number of points
+// Then one point per line
+template <typename Kernel, typename Point_range>
+std::ostream &export_point_set(
+ Kernel const& k,
+ Point_range const& points,
+ std::ostream & os,
+ const char *coord_separator = " ") {
+ // Kernel functors
+ typename Kernel::Construct_cartesian_const_iterator_d ccci =
+ k.construct_cartesian_const_iterator_d_object();
+
+ os << points.size() << "\n";
+
+ typename Point_range::const_iterator it_p = points.begin();
+ typename Point_range::const_iterator it_p_end = points.end();
+ // For each point p
+ for (; it_p != it_p_end; ++it_p) {
+ for (auto it = ccci(*it_p); it != ccci(*it_p, 0); ++it)
+ os << CGAL::to_double(*it) << coord_separator;
+
+ os << "\n";
+ }
+
+ return os;
+}
+
+// Compute all the k-combinations of elements
+// Output_iterator::value_type must be
+// boost::container::flat_set<std::size_t>
+template <typename Elements_container, typename Output_iterator>
+void combinations(const Elements_container elements, int k,
+ Output_iterator combinations) {
+ std::size_t n = elements.size();
+ std::vector<bool> booleans(n, false);
+ std::fill(booleans.begin() + n - k, booleans.end(), true);
+ do {
+ boost::container::flat_set<std::size_t> combination;
+ typename Elements_container::const_iterator it_elt = elements.begin();
+ for (std::size_t i = 0; i < n; ++i, ++it_elt) {
+ if (booleans[i])
+ combination.insert(*it_elt);
+ }
+ *combinations++ = combination;
+ } while (std::next_permutation(booleans.begin(), booleans.end()));
+}
+
+} // namespace internal
+} // namespace tangential_complex
+} // namespace Gudhi
+
+#endif // TANGENTIAL_COMPLEX_UTILITIES_H_
diff --git a/include/gudhi/Test.h b/include/gudhi/Test.h
deleted file mode 100644
index 6024c822..00000000
--- a/include/gudhi/Test.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* This file is part of the Gudhi Library. The Gudhi library
- * (Geometric Understanding in Higher Dimensions) is a generic C++
- * library for computational topology.
- *
- * Author(s): David Salinas
- *
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (France)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef TEST_H_
-#define TEST_H_
-
-#include <list>
-#include <string>
-#include <vector>
-#include <sstream>
-#include <iostream>
-
-
-#define TEST(a) std::cout << "TEST: " << (a) << std::endl
-#define TESTMSG(a, b) std::cout << "TEST: " << a << b << std::endl
-#define TESTVALUE(a) std::cout << "TEST: " << #a << ": " << a << std::endl
-
-/**
- * Class to perform test
- */
-
-class Test {
- private:
- std::string name;
- bool (*test)();
-
- std::string separation() const {
- return "+++++++++++++++++++++++++++++++++++++++++++++++++\n";
- }
-
- std::string print_between_plus(std::string& s) const {
- std::stringstream res;
- res << "+++++++++++++++++" << s << "+++++++++++++++++\n";
- return res.str();
- }
-
- public:
- Test(std::string name_, bool (*test_)()) {
- name = name_;
- test = test_;
- }
-
- bool run() {
- std::cout << print_between_plus(name);
- return test();
- }
-
- std::string getName() {
- return name;
- }
-};
-
-class Tests {
- private:
- std::list<Test> tests;
-
- public:
- void add(std::string name_, bool (*test_)()) {
- Test test(name_, test_);
- tests.push_back(test);
- }
-
- bool run() {
- bool tests_succesful(true);
- std::vector<bool> res;
- for (Test test : tests) {
- res.push_back(test.run());
- }
- std::cout << "\n\n results of tests : " << std::endl;
- int i = 0;
- for (Test t : tests) {
- std::cout << "Test " << i << " \"" << t.getName() << "\" --> ";
- if (res[i++]) {
- std::cout << "OK" << std::endl;
- } else {
- std::cout << "Fail" << std::endl;
- tests_succesful = false;
- break;
- }
- }
- return tests_succesful;
- }
-};
-
-#endif // TEST_H_
diff --git a/include/gudhi/Witness_complex.h b/include/gudhi/Witness_complex.h
index 489cdf11..63f03687 100644
--- a/include/gudhi/Witness_complex.h
+++ b/include/gudhi/Witness_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): Siargey Kachanovich
*
- * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (France)
+ * Copyright (C) 2015 INRIA (France)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,65 +23,44 @@
#ifndef WITNESS_COMPLEX_H_
#define WITNESS_COMPLEX_H_
-// Needed for the adjacency graph in bad link search
-#include <boost/graph/graph_traits.hpp>
-#include <boost/graph/adjacency_list.hpp>
-#include <boost/graph/connected_components.hpp>
+#include <gudhi/Active_witness/Active_witness.h>
+#include <gudhi/Witness_complex/all_faces_in.h>
-#include <boost/range/size.hpp>
-
-#include <gudhi/distance_functions.h>
-
-#include <algorithm>
#include <utility>
#include <vector>
#include <list>
-#include <set>
-#include <queue>
#include <limits>
-#include <ctime>
-#include <iostream>
namespace Gudhi {
namespace witness_complex {
-// /*
-// * \private
-// \class Witness_complex
-// \brief Constructs the witness complex for the given set of witnesses and landmarks.
-// \ingroup witness_complex
-// */
-template< class SimplicialComplex>
+/**
+ * \private
+ * \class Witness_complex
+ * \brief Constructs (weak) witness complex for a given table of nearest landmarks with respect to witnesses.
+ * \ingroup witness_complex
+ *
+ * \tparam Nearest_landmark_table_ needs to be a range of a range of pairs of nearest landmarks and distances.
+ * The class Nearest_landmark_table_::value_type must be a copiable range.
+ * The range of pairs must admit a member type 'iterator'. The dereference type
+ * of the pair range iterator needs to be 'std::pair<std::size_t, double>'.
+*/
+template< class Nearest_landmark_table_ >
class Witness_complex {
private:
- struct Active_witness {
- int witness_id;
- int landmark_id;
-
- Active_witness(int witness_id_, int landmark_id_)
- : witness_id(witness_id_),
- landmark_id(landmark_id_) { }
- };
-
- private:
- typedef typename SimplicialComplex::Simplex_handle Simplex_handle;
- typedef typename SimplicialComplex::Vertex_handle Vertex_handle;
-
- typedef std::vector< double > Point_t;
- typedef std::vector< Point_t > Point_Vector;
-
- typedef std::vector< Vertex_handle > typeVectorVertex;
- typedef std::pair< typeVectorVertex, Filtration_value> typeSimplex;
- typedef std::pair< Simplex_handle, bool > typePairSimplexBool;
-
- typedef int Witness_id;
- typedef int Landmark_id;
- typedef std::list< Vertex_handle > ActiveWitnessList;
-
- private:
- int nbL_; // Number of landmarks
- SimplicialComplex& sc_; // Simplicial complex
+ typedef typename Nearest_landmark_table_::value_type Nearest_landmark_range;
+ typedef std::size_t Witness_id;
+ typedef std::size_t Landmark_id;
+ typedef std::pair<Landmark_id, double> Id_distance_pair;
+ typedef Active_witness<Id_distance_pair, Nearest_landmark_range> ActiveWitness;
+ typedef std::list< ActiveWitness > ActiveWitnessList;
+ typedef std::vector< Landmark_id > typeVectorVertex;
+ typedef std::vector<Nearest_landmark_range> Nearest_landmark_table_internal;
+ typedef Landmark_id Vertex_handle;
+
+ protected:
+ Nearest_landmark_table_internal nearest_landmark_table_;
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -90,174 +69,136 @@ class Witness_complex {
//@{
- // Witness_range<Closest_landmark_range<Vertex_handle>>
+ Witness_complex() {
+ }
- /*
- * \brief Iterative construction of the witness complex.
- * \details The witness complex is written in sc_ basing on a matrix knn of
- * nearest neighbours of the form {witnesses}x{landmarks}.
- *
- * The type KNearestNeighbors can be seen as
- * Witness_range<Closest_landmark_range<Vertex_handle>>, where
- * Witness_range and Closest_landmark_range are random access ranges.
- *
- * Constructor takes into account at most (dim+1)
- * first landmarks from each landmark range to construct simplices.
- *
- * Landmarks are supposed to be in [0,nbL_-1]
+ /**
+ * \brief Initializes member variables before constructing simplicial complex.
+ * \details Records nearest landmark table.
+ * @param[in] nearest_landmark_table needs to be a range of a range of pairs of nearest landmarks and distances.
+ * The class Nearest_landmark_table_::value_type must be a copiable range.
+ * The range of pairs must admit a member type 'iterator'. The dereference type
+ * of the pair range iterator needs to be 'std::pair<std::size_t, double>'.
*/
- template< typename KNearestNeighbors >
- Witness_complex(KNearestNeighbors const & knn,
- int nbL,
- int dim,
- SimplicialComplex & sc) : nbL_(nbL), sc_(sc) {
- // Construction of the active witness list
- int nbW = boost::size(knn);
- typeVectorVertex vv;
- int counter = 0;
- /* The list of still useful witnesses
- * it will diminuish in the course of iterations
- */
- ActiveWitnessList active_w; // = new ActiveWitnessList();
- for (Vertex_handle i = 0; i != nbL_; ++i) {
- // initial fill of 0-dimensional simplices
- // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore
- counter++;
- vv = {i};
- sc_.insert_simplex(vv);
- // TODO(SK) Error if not inserted : normally no need here though
+
+ Witness_complex(Nearest_landmark_table_ const & nearest_landmark_table)
+ : nearest_landmark_table_(std::begin(nearest_landmark_table), std::end(nearest_landmark_table)) {
+ }
+
+ /** \brief Outputs the (weak) witness complex of relaxation 'max_alpha_square'
+ * in a simplicial complex data structure.
+ * \details The function returns true if the construction is successful and false otherwise.
+ * @param[out] complex Simplicial complex data structure compatible which is a model of
+ * SimplicialComplexForWitness concept.
+ * @param[in] max_alpha_square Maximal squared relaxation parameter.
+ * @param[in] limit_dimension Represents the maximal dimension of the simplicial complex
+ * (default value = no limit).
+ */
+ template < typename SimplicialComplexForWitness >
+ bool create_complex(SimplicialComplexForWitness& complex,
+ double max_alpha_square,
+ std::size_t limit_dimension = std::numeric_limits<std::size_t>::max()) const {
+ if (complex.num_vertices() > 0) {
+ std::cerr << "Witness complex cannot create complex - complex is not empty.\n";
+ return false;
}
- int k = 1; /* current dimension in iterative construction */
- for (int i = 0; i != nbW; ++i)
- active_w.push_back(i);
- while (!active_w.empty() && k < dim) {
- typename ActiveWitnessList::iterator it = active_w.begin();
- while (it != active_w.end()) {
- typeVectorVertex simplex_vector;
- /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/
- bool ok = all_faces_in(knn, *it, k);
- if (ok) {
- for (int i = 0; i != k + 1; ++i)
- simplex_vector.push_back(knn[*it][i]);
- sc_.insert_simplex(simplex_vector);
- // TODO(SK) Error if not inserted : normally no need here though
- ++it;
- } else {
- active_w.erase(it++); // First increase the iterator and then erase the previous element
- }
+ if (max_alpha_square < 0) {
+ std::cerr << "Witness complex cannot create complex - squared relaxation parameter must be non-negative.\n";
+ return false;
+ }
+ if (limit_dimension < 0) {
+ std::cerr << "Witness complex cannot create complex - limit dimension must be non-negative.\n";
+ return false;
+ }
+ ActiveWitnessList active_witnesses;
+ Landmark_id k = 0; /* current dimension in iterative construction */
+ for (auto w : nearest_landmark_table_)
+ active_witnesses.push_back(ActiveWitness(w));
+ while (!active_witnesses.empty() && k <= limit_dimension) {
+ typename ActiveWitnessList::iterator aw_it = active_witnesses.begin();
+ std::vector<Landmark_id> simplex;
+ simplex.reserve(k+1);
+ while (aw_it != active_witnesses.end()) {
+ bool ok = add_all_faces_of_dimension(k,
+ max_alpha_square,
+ std::numeric_limits<double>::infinity(),
+ aw_it->begin(),
+ simplex,
+ complex,
+ aw_it->end());
+ assert(simplex.empty());
+ if (!ok)
+ active_witnesses.erase(aw_it++); // First increase the iterator and then erase the previous element
+ else
+ aw_it++;
}
k++;
}
+ complex.set_dimension(k-1);
+ return true;
}
//@}
private:
- /* \brief Check if the facets of the k-dimensional simplex witnessed
- * by witness witness_id are already in the complex.
- * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id
+ /* \brief Adds recursively all the faces of a certain dimension dim witnessed by the same witness.
+ * Iterator is needed to know until how far we can take landmarks to form simplexes.
+ * simplex is the prefix of the simplexes to insert.
+ * The output value indicates if the witness rests active or not.
*/
- template <typename KNearestNeighbors>
- bool all_faces_in(KNearestNeighbors const &knn, int witness_id, int k) {
- std::vector< Vertex_handle > facet;
- // CHECK ALL THE FACETS
- for (int i = 0; i != k + 1; ++i) {
- facet = {};
- for (int j = 0; j != k + 1; ++j) {
- if (j != i) {
- facet.push_back(knn[witness_id][j]);
+ template < typename SimplicialComplexForWitness >
+ bool add_all_faces_of_dimension(int dim,
+ double alpha2,
+ double norelax_dist2,
+ typename ActiveWitness::iterator curr_l,
+ std::vector<Landmark_id>& simplex,
+ SimplicialComplexForWitness& sc,
+ typename ActiveWitness::iterator end) const {
+ if (curr_l == end)
+ return false;
+ bool will_be_active = false;
+ typename ActiveWitness::iterator l_it = curr_l;
+ if (dim > 0) {
+ for (; l_it != end && l_it->second - alpha2 <= norelax_dist2; ++l_it) {
+ simplex.push_back(l_it->first);
+ if (sc.find(simplex) != sc.null_simplex()) {
+ typename ActiveWitness::iterator next_it = l_it;
+ will_be_active = add_all_faces_of_dimension(dim-1,
+ alpha2,
+ norelax_dist2,
+ ++next_it,
+ simplex,
+ sc,
+ end) || will_be_active;
}
- } // endfor
- if (sc_.find(facet) == sc_.null_simplex())
- return false;
- } // endfor
- return true;
- }
-
- template <typename T>
- static void print_vector(const std::vector<T>& v) {
- std::cout << "[";
- if (!v.empty()) {
- std::cout << *(v.begin());
- for (auto it = v.begin() + 1; it != v.end(); ++it) {
- std::cout << ",";
- std::cout << *it;
+ assert(!simplex.empty());
+ simplex.pop_back();
+ // If norelax_dist is infinity, change to first omitted distance
+ if (l_it->second <= norelax_dist2)
+ norelax_dist2 = l_it->second;
}
- }
- std::cout << "]";
- }
-
- public:
- // /*
- // * \brief Verification if every simplex in the complex is witnessed by witnesses in knn.
- // * \param print_output =true will print the witnesses for each simplex
- // * \remark Added for debugging purposes.
- // */
- template< class KNearestNeighbors >
- bool is_witness_complex(KNearestNeighbors const & knn, bool print_output) {
- for (Simplex_handle sh : sc_.complex_simplex_range()) {
- bool is_witnessed = false;
- typeVectorVertex simplex;
- int nbV = 0; // number of verticed in the simplex
- for (Vertex_handle v : sc_.simplex_vertex_range(sh))
- simplex.push_back(v);
- nbV = simplex.size();
- for (typeVectorVertex w : knn) {
- bool has_vertices = true;
- for (Vertex_handle v : simplex)
- if (std::find(w.begin(), w.begin() + nbV, v) == w.begin() + nbV) {
- has_vertices = false;
- }
- if (has_vertices) {
- is_witnessed = true;
- if (print_output) {
- std::cout << "The simplex ";
- print_vector(simplex);
- std::cout << " is witnessed by the witness ";
- print_vector(w);
- std::cout << std::endl;
- }
- break;
- }
- }
- if (!is_witnessed) {
- if (print_output) {
- std::cout << "The following simplex is not witnessed ";
- print_vector(simplex);
- std::cout << std::endl;
+ } else if (dim == 0) {
+ for (; l_it != end && l_it->second - alpha2 <= norelax_dist2; ++l_it) {
+ simplex.push_back(l_it->first);
+ double filtration_value = 0;
+ // if norelax_dist is infinite, relaxation is 0.
+ if (l_it->second > norelax_dist2)
+ filtration_value = l_it->second - norelax_dist2;
+ if (all_faces_in(simplex, &filtration_value, sc)) {
+ will_be_active = true;
+ sc.insert_simplex(simplex, filtration_value);
}
- assert(is_witnessed);
- return false;
+ assert(!simplex.empty());
+ simplex.pop_back();
+ // If norelax_dist is infinity, change to first omitted distance
+ if (l_it->second < norelax_dist2)
+ norelax_dist2 = l_it->second;
}
}
- return true;
+ return will_be_active;
}
};
- /**
- * \ingroup witness_complex
- * \brief Iterative construction of the witness complex.
- * \details The witness complex is written in simplicial complex sc_
- * basing on a matrix knn of
- * nearest neighbours of the form {witnesses}x{landmarks}.
- *
- * The type KNearestNeighbors can be seen as
- * Witness_range<Closest_landmark_range<Vertex_handle>>, where
- * Witness_range and Closest_landmark_range are random access ranges.
- *
- * Procedure takes into account at most (dim+1)
- * first landmarks from each landmark range to construct simplices.
- *
- * Landmarks are supposed to be in [0,nbL_-1]
- */
- template <class KNearestNeighbors, class SimplicialComplexForWitness>
- void witness_complex(KNearestNeighbors const & knn,
- int nbL,
- int dim,
- SimplicialComplexForWitness & sc) {
- Witness_complex<SimplicialComplexForWitness>(knn, nbL, dim, sc);
- }
-
} // namespace witness_complex
} // namespace Gudhi
diff --git a/include/gudhi/Witness_complex/all_faces_in.h b/include/gudhi/Witness_complex/all_faces_in.h
new file mode 100644
index 00000000..b68d75a1
--- /dev/null
+++ b/include/gudhi/Witness_complex/all_faces_in.h
@@ -0,0 +1,55 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2015 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WITNESS_COMPLEX_ALL_FACES_IN_H_
+#define WITNESS_COMPLEX_ALL_FACES_IN_H_
+
+/* \brief Check if the facets of the k-dimensional simplex witnessed
+ * by witness witness_id are already in the complex.
+ * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id
+ */
+template < typename SimplicialComplexForWitness,
+ typename Simplex >
+ bool all_faces_in(Simplex& simplex,
+ double* filtration_value,
+ SimplicialComplexForWitness& sc) {
+ typedef typename SimplicialComplexForWitness::Simplex_handle Simplex_handle;
+
+ if (simplex.size() == 1)
+ return true; /* Add vertices unconditionally */
+
+ Simplex facet;
+ for (typename Simplex::iterator not_it = simplex.begin(); not_it != simplex.end(); ++not_it) {
+ facet.clear();
+ for (typename Simplex::iterator it = simplex.begin(); it != simplex.end(); ++it)
+ if (it != not_it)
+ facet.push_back(*it);
+ Simplex_handle facet_sh = sc.find(facet);
+ if (facet_sh == sc.null_simplex())
+ return false;
+ else if (sc.filtration(facet_sh) > *filtration_value)
+ *filtration_value = sc.filtration(facet_sh);
+ }
+ return true;
+ }
+
+#endif // WITNESS_COMPLEX_ALL_FACES_IN_H_
diff --git a/include/gudhi/choose_n_farthest_points.h b/include/gudhi/choose_n_farthest_points.h
new file mode 100644
index 00000000..86500b28
--- /dev/null
+++ b/include/gudhi/choose_n_farthest_points.h
@@ -0,0 +1,133 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CHOOSE_N_FARTHEST_POINTS_H_
+#define CHOOSE_N_FARTHEST_POINTS_H_
+
+#include <boost/range.hpp>
+
+#include <gudhi/Null_output_iterator.h>
+
+#include <iterator>
+#include <vector>
+#include <random>
+#include <limits> // for numeric_limits<>
+
+namespace Gudhi {
+
+namespace subsampling {
+
+/**
+ * \ingroup subsampling
+ */
+enum : std::size_t {
+/**
+ * Argument for `choose_n_farthest_points` to indicate that the starting point should be picked randomly.
+ */
+ random_starting_point = std::size_t(-1)
+};
+
+/**
+ * \ingroup subsampling
+ * \brief Subsample by a greedy strategy of iteratively adding the farthest point from the
+ * current chosen point set to the subsampling.
+ * The iteration starts with the landmark `starting point` or, if `starting point==random_starting_point`, with a random landmark.
+ * \tparam Kernel must provide a type Kernel::Squared_distance_d which is a model of the
+ * concept <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_d/classKernel__d_1_1Squared__distance__d.html">Kernel_d::Squared_distance_d</a> (despite the name, taken from CGAL, this can be any kind of metric or proximity measure).
+ * It must also contain a public member `squared_distance_d_object()` that returns an object of this type.
+ * \tparam Point_range Range whose value type is Kernel::Point_d. It must provide random-access
+ * via `operator[]` and the points should be stored contiguously in memory.
+ * \tparam PointOutputIterator Output iterator whose value type is Kernel::Point_d.
+ * \tparam DistanceOutputIterator Output iterator for distances.
+ * \details It chooses `final_size` points from a random access range
+ * `input_pts` and outputs them in the output iterator `output_it`. It also
+ * outputs the distance from each of those points to the set of previous
+ * points in `dist_it`.
+ * @param[in] k A kernel object.
+ * @param[in] input_pts Const reference to the input points.
+ * @param[in] final_size The size of the subsample to compute.
+ * @param[in] starting_point The seed in the farthest point algorithm.
+ * @param[out] output_it The output iterator for points.
+ * @param[out] dist_it The optional output iterator for distances.
+ *
+ */
+template < typename Kernel,
+typename Point_range,
+typename PointOutputIterator,
+typename DistanceOutputIterator = Null_output_iterator>
+void choose_n_farthest_points(Kernel const &k,
+ Point_range const &input_pts,
+ std::size_t final_size,
+ std::size_t starting_point,
+ PointOutputIterator output_it,
+ DistanceOutputIterator dist_it = {}) {
+ std::size_t nb_points = boost::size(input_pts);
+ if (final_size > nb_points)
+ final_size = nb_points;
+
+ // Tests to the limit
+ if (final_size < 1)
+ return;
+
+ if (starting_point == random_starting_point) {
+ // Choose randomly the first landmark
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ std::uniform_int_distribution<std::size_t> dis(0, (input_pts.size() - 1));
+ starting_point = dis(gen);
+ }
+
+ typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object();
+
+ std::size_t current_number_of_landmarks = 0; // counter for landmarks
+ const double infty = std::numeric_limits<double>::infinity(); // infinity (see next entry)
+ std::vector< double > dist_to_L(nb_points, infty); // vector of current distances to L from input_pts
+
+ std::size_t curr_max_w = starting_point;
+
+ for (current_number_of_landmarks = 0; current_number_of_landmarks != final_size; current_number_of_landmarks++) {
+ // curr_max_w at this point is the next landmark
+ *output_it++ = input_pts[curr_max_w];
+ *dist_it++ = dist_to_L[curr_max_w];
+ std::size_t i = 0;
+ for (auto& p : input_pts) {
+ double curr_dist = sqdist(p, *(std::begin(input_pts) + curr_max_w));
+ if (curr_dist < dist_to_L[i])
+ dist_to_L[i] = curr_dist;
+ ++i;
+ }
+ // choose the next curr_max_w
+ double curr_max_dist = 0; // used for defining the furhest point from L
+ for (i = 0; i < dist_to_L.size(); i++)
+ if (dist_to_L[i] > curr_max_dist) {
+ curr_max_dist = dist_to_L[i];
+ curr_max_w = i;
+ }
+ }
+}
+
+} // namespace subsampling
+
+} // namespace Gudhi
+
+#endif // CHOOSE_N_FARTHEST_POINTS_H_
diff --git a/include/gudhi/console_color.h b/include/gudhi/console_color.h
new file mode 100644
index 00000000..c4671da3
--- /dev/null
+++ b/include/gudhi/console_color.h
@@ -0,0 +1,97 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 INRIA Sophia-Antipolis (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CONSOLE_COLOR_H_
+#define CONSOLE_COLOR_H_
+
+#include <iostream>
+
+#if defined(WIN32)
+#include <windows.h>
+#endif
+
+inline std::ostream& blue(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout,
+ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
+#else
+ s << "\x1b[0;34m";
+#endif
+ return s;
+}
+
+inline std::ostream& red(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY);
+#else
+ s << "\x1b[0;31m";
+#endif
+ return s;
+}
+
+inline std::ostream& green(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
+#else
+ s << "\x1b[0;32m";
+#endif
+ return s;
+}
+
+inline std::ostream& yellow(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout,
+ FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
+#else
+ s << "\x1b[0;33m";
+#endif
+ return s;
+}
+
+inline std::ostream& white(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout,
+ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
+#else
+ s << "\x1b[0;37m";
+#endif
+ return s;
+}
+
+inline std::ostream& black_on_white(std::ostream &s) {
+#if defined(WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleTextAttribute(hStdout,
+ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
+#else
+ s << "\x1b[0;33m";
+#endif
+ return s;
+}
+
+
+#endif // CONSOLE_COLOR_H_
diff --git a/include/gudhi/distance_functions.h b/include/gudhi/distance_functions.h
index cd518581..f6e2ab5a 100644
--- a/include/gudhi/distance_functions.h
+++ b/include/gudhi/distance_functions.h
@@ -4,7 +4,7 @@
*
* Author(s): Clément Maria
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,20 +24,32 @@
#define DISTANCE_FUNCTIONS_H_
#include <cmath> // for std::sqrt
+#include <type_traits> // for std::decay
+#include <iterator> // for std::begin, std::end
-/* Compute the Euclidean distance between two Points given
- * by a range of coordinates. The points are assumed to have
- * the same dimension. */
-template< typename Point >
-double euclidean_distance(Point &p1, Point &p2) {
- double dist = 0.;
- auto it1 = p1.begin();
- auto it2 = p2.begin();
- for (; it1 != p1.end(); ++it1, ++it2) {
- double tmp = *it1 - *it2;
- dist += tmp*tmp;
+namespace Gudhi {
+
+/** @file
+ * @brief Global distance functions
+ */
+
+/** @brief Compute the Euclidean distance between two Points given by a range of coordinates. The points are assumed to
+ * have the same dimension. */
+class Euclidean_distance {
+ public:
+ template< typename Point >
+ auto operator()(const Point& p1, const Point& p2) const -> typename std::decay<decltype(*std::begin(p1))>::type {
+ auto it1 = p1.begin();
+ auto it2 = p2.begin();
+ typename Point::value_type dist = 0.;
+ for (; it1 != p1.end(); ++it1, ++it2) {
+ typename Point::value_type tmp = (*it1) - (*it2);
+ dist += tmp*tmp;
+ }
+ return std::sqrt(dist);
}
- return std::sqrt(dist);
-}
+};
+
+} // namespace Gudhi
#endif // DISTANCE_FUNCTIONS_H_
diff --git a/include/gudhi/graph_simplicial_complex.h b/include/gudhi/graph_simplicial_complex.h
index 042ef516..5fe7c826 100644
--- a/include/gudhi/graph_simplicial_complex.h
+++ b/include/gudhi/graph_simplicial_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): Clément Maria
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,61 +39,4 @@ struct vertex_filtration_t {
typedef boost::vertex_property_tag kind;
};
-typedef int Vertex_handle;
-typedef double Filtration_value;
-typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS
-, boost::property < vertex_filtration_t, Filtration_value >
-, boost::property < edge_filtration_t, Filtration_value >
-> Graph_t;
-typedef std::pair< Vertex_handle, Vertex_handle > Edge_t;
-
-/** \brief Output the proximity graph of the points.
- *
- * If points contains n elements, the proximity graph is the graph
- * with n vertices, and an edge [u,v] iff the distance function between
- * points u and v is smaller than threshold.
- *
- * The type PointCloud furnishes .begin() and .end() methods, that return
- * iterators with value_type Point.
- */
-template< typename PointCloud
-, typename Point >
-Graph_t compute_proximity_graph(PointCloud &points
- , Filtration_value threshold
- , Filtration_value distance(Point p1, Point p2)) {
- std::vector< Edge_t > edges;
- std::vector< Filtration_value > edges_fil;
- std::map< Vertex_handle, Filtration_value > vertices;
-
- Vertex_handle idx_u, idx_v;
- Filtration_value fil;
- idx_u = 0;
- for (auto it_u = points.begin(); it_u != points.end(); ++it_u) {
- idx_v = idx_u + 1;
- for (auto it_v = it_u + 1; it_v != points.end(); ++it_v, ++idx_v) {
- fil = distance(*it_u, *it_v);
- if (fil <= threshold) {
- edges.emplace_back(idx_u, idx_v);
- edges_fil.push_back(fil);
- }
- }
- ++idx_u;
- }
-
- Graph_t skel_graph(edges.begin()
- , edges.end()
- , edges_fil.begin()
- , idx_u); // number of points labeled from 0 to idx_u-1
-
- auto vertex_prop = boost::get(vertex_filtration_t(), skel_graph);
-
- boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
- for (std::tie(vi, vi_end) = boost::vertices(skel_graph);
- vi != vi_end; ++vi) {
- boost::put(vertex_prop, *vi, 0.);
- }
-
- return skel_graph;
-}
-
#endif // GRAPH_SIMPLICIAL_COMPLEX_H_
diff --git a/include/gudhi/pick_n_random_points.h b/include/gudhi/pick_n_random_points.h
new file mode 100644
index 00000000..f0e3f1f1
--- /dev/null
+++ b/include/gudhi/pick_n_random_points.h
@@ -0,0 +1,86 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PICK_N_RANDOM_POINTS_H_
+#define PICK_N_RANDOM_POINTS_H_
+
+#include <gudhi/Clock.h>
+
+#include <boost/range/size.hpp>
+
+#include <cstddef>
+#include <random> // random_device, mt19937
+#include <algorithm> // shuffle
+#include <numeric> // iota
+#include <iterator>
+#include <vector>
+
+
+namespace Gudhi {
+
+namespace subsampling {
+
+/**
+ * \ingroup subsampling
+ * \brief Subsample a point set by picking random vertices.
+ *
+ * \details It chooses `final_size` distinct points from a random access range `points`
+ * and outputs them to the output iterator `output_it`.
+ * Point_container::iterator should be ValueSwappable and RandomAccessIterator.
+ */
+template <typename Point_container,
+typename OutputIterator>
+void pick_n_random_points(Point_container const &points,
+ std::size_t final_size,
+ OutputIterator output_it) {
+#ifdef GUDHI_SUBS_PROFILING
+ Gudhi::Clock t;
+#endif
+
+ std::size_t nbP = boost::size(points);
+ if (final_size > nbP)
+ final_size = nbP;
+
+ std::vector<int> landmarks(nbP);
+ std::iota(landmarks.begin(), landmarks.end(), 0);
+
+ std::random_device rd;
+ std::mt19937 g(rd());
+
+ std::shuffle(landmarks.begin(), landmarks.end(), g);
+ landmarks.resize(final_size);
+
+ for (int l : landmarks)
+ *output_it++ = points[l];
+
+#ifdef GUDHI_SUBS_PROFILING
+ t.end();
+ std::cerr << "Random landmark choice took " << t.num_seconds()
+ << " seconds." << std::endl;
+#endif
+}
+
+} // namespace subsampling
+
+} // namespace Gudhi
+
+#endif // PICK_N_RANDOM_POINTS_H_
diff --git a/include/gudhi/random_point_generators.h b/include/gudhi/random_point_generators.h
new file mode 100644
index 00000000..2ec465ef
--- /dev/null
+++ b/include/gudhi/random_point_generators.h
@@ -0,0 +1,474 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RANDOM_POINT_GENERATORS_H_
+#define RANDOM_POINT_GENERATORS_H_
+
+#include <CGAL/number_utils.h>
+#include <CGAL/Random.h>
+#include <CGAL/point_generators_d.h>
+
+#include <vector> // for vector<>
+
+namespace Gudhi {
+
+///////////////////////////////////////////////////////////////////////////////
+// Note: All these functions have been tested with the CGAL::Epick_d kernel
+///////////////////////////////////////////////////////////////////////////////
+
+// construct_point: dim 2
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2) {
+ typename Kernel::FT tab[2];
+ tab[0] = x1;
+ tab[1] = x2;
+ return k.construct_point_d_object()(2, &tab[0], &tab[2]);
+}
+
+// construct_point: dim 3
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3) {
+ typename Kernel::FT tab[3];
+ tab[0] = x1;
+ tab[1] = x2;
+ tab[2] = x3;
+ return k.construct_point_d_object()(3, &tab[0], &tab[3]);
+}
+
+// construct_point: dim 4
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3,
+ typename Kernel::FT x4) {
+ typename Kernel::FT tab[4];
+ tab[0] = x1;
+ tab[1] = x2;
+ tab[2] = x3;
+ tab[3] = x4;
+ return k.construct_point_d_object()(4, &tab[0], &tab[4]);
+}
+
+// construct_point: dim 5
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3,
+ typename Kernel::FT x4, typename Kernel::FT x5) {
+ typename Kernel::FT tab[5];
+ tab[0] = x1;
+ tab[1] = x2;
+ tab[2] = x3;
+ tab[3] = x4;
+ tab[4] = x5;
+ return k.construct_point_d_object()(5, &tab[0], &tab[5]);
+}
+
+// construct_point: dim 6
+
+template <typename Kernel>
+typename Kernel::Point_d construct_point(const Kernel &k,
+ typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3,
+ typename Kernel::FT x4, typename Kernel::FT x5, typename Kernel::FT x6) {
+ typename Kernel::FT tab[6];
+ tab[0] = x1;
+ tab[1] = x2;
+ tab[2] = x3;
+ tab[3] = x4;
+ tab[4] = x5;
+ tab[5] = x6;
+ return k.construct_point_d_object()(6, &tab[0], &tab[6]);
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_plane(std::size_t num_points, int intrinsic_dim,
+ int ambient_dim,
+ double coord_min = -5., double coord_max = 5.) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ std::vector<FT> pt(ambient_dim, FT(0));
+ for (int j = 0; j < intrinsic_dim; ++j)
+ pt[j] = rng.get_double(coord_min, coord_max);
+
+ Point p = k.construct_point_d_object()(ambient_dim, pt.begin(), pt.end());
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_moment_curve(std::size_t num_points, int dim,
+ typename Kernel::FT min_x,
+ typename Kernel::FT max_x) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT x = rng.get_double(min_x, max_x);
+ std::vector<FT> coords;
+ coords.reserve(dim);
+ for (int p = 1; p <= dim; ++p)
+ coords.push_back(std::pow(CGAL::to_double(x), p));
+ Point p = k.construct_point_d_object()(
+ dim, coords.begin(), coords.end());
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+
+// R = big radius, r = small radius
+template <typename Kernel/*, typename TC_basis*/>
+std::vector<typename Kernel::Point_d> generate_points_on_torus_3D(std::size_t num_points, double R, double r,
+ bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ Point p = construct_point(k,
+ (R + r * std::cos(u)) * std::cos(v),
+ (R + r * std::cos(u)) * std::sin(v),
+ r * std::sin(u));
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+// "Private" function used by generate_points_on_torus_d
+template <typename Kernel, typename OutputIterator>
+static void generate_uniform_points_on_torus_d(const Kernel &k, int dim, std::size_t num_slices,
+ OutputIterator out,
+ double radius_noise_percentage = 0.,
+ std::vector<typename Kernel::FT> current_point = std::vector<typename Kernel::FT>()) {
+ CGAL::Random rng;
+ int point_size = static_cast<int>(current_point.size());
+ if (point_size == 2 * dim) {
+ *out++ = k.construct_point_d_object()(point_size, current_point.begin(), current_point.end());
+ } else {
+ for (std::size_t slice_idx = 0; slice_idx < num_slices; ++slice_idx) {
+ double radius_noise_ratio = 1.;
+ if (radius_noise_percentage > 0.) {
+ radius_noise_ratio = rng.get_double(
+ (100. - radius_noise_percentage) / 100.,
+ (100. + radius_noise_percentage) / 100.);
+ }
+ std::vector<typename Kernel::FT> cp2 = current_point;
+ double alpha = 6.2832 * slice_idx / num_slices;
+ cp2.push_back(radius_noise_ratio * std::cos(alpha));
+ cp2.push_back(radius_noise_ratio * std::sin(alpha));
+ generate_uniform_points_on_torus_d(
+ k, dim, num_slices, out, radius_noise_percentage, cp2);
+ }
+ }
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_torus_d(std::size_t num_points, int dim, bool uniform = false,
+ double radius_noise_percentage = 0.) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ if (uniform) {
+ std::size_t num_slices = (std::size_t)std::pow(num_points, 1. / dim);
+ generate_uniform_points_on_torus_d(
+ k, dim, num_slices, std::back_inserter(points), radius_noise_percentage);
+ } else {
+ for (std::size_t i = 0; i < num_points;) {
+ double radius_noise_ratio = 1.;
+ if (radius_noise_percentage > 0.) {
+ radius_noise_ratio = rng.get_double(
+ (100. - radius_noise_percentage) / 100.,
+ (100. + radius_noise_percentage) / 100.);
+ }
+ std::vector<typename Kernel::FT> pt;
+ pt.reserve(dim * 2);
+ for (int curdim = 0; curdim < dim; ++curdim) {
+ FT alpha = rng.get_double(0, 6.2832);
+ pt.push_back(radius_noise_ratio * std::cos(alpha));
+ pt.push_back(radius_noise_ratio * std::sin(alpha));
+ }
+
+ Point p = k.construct_point_d_object()(pt.begin(), pt.end());
+ points.push_back(p);
+ ++i;
+ }
+ }
+ return points;
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_sphere_d(std::size_t num_points, int dim, double radius,
+ double radius_noise_percentage = 0.) {
+ typedef typename Kernel::Point_d Point;
+ Kernel k;
+ CGAL::Random rng;
+ CGAL::Random_points_on_sphere_d<Point> generator(dim, radius);
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ Point p = *generator++;
+ if (radius_noise_percentage > 0.) {
+ double radius_noise_ratio = rng.get_double(
+ (100. - radius_noise_percentage) / 100.,
+ (100. + radius_noise_percentage) / 100.);
+
+ typename Kernel::Point_to_vector_d k_pt_to_vec =
+ k.point_to_vector_d_object();
+ typename Kernel::Vector_to_point_d k_vec_to_pt =
+ k.vector_to_point_d_object();
+ typename Kernel::Scaled_vector_d k_scaled_vec =
+ k.scaled_vector_d_object();
+ p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio));
+ }
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_two_spheres_d(std::size_t num_points, int dim, double radius,
+ double distance_between_centers,
+ double radius_noise_percentage = 0.) {
+ typedef typename Kernel::FT FT;
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::Vector_d Vector;
+ Kernel k;
+ CGAL::Random rng;
+ CGAL::Random_points_on_sphere_d<Point> generator(dim, radius);
+ std::vector<Point> points;
+ points.reserve(num_points);
+
+ std::vector<FT> t(dim, FT(0));
+ t[0] = distance_between_centers;
+ Vector c1_to_c2(t.begin(), t.end());
+
+ for (std::size_t i = 0; i < num_points;) {
+ Point p = *generator++;
+ if (radius_noise_percentage > 0.) {
+ double radius_noise_ratio = rng.get_double(
+ (100. - radius_noise_percentage) / 100.,
+ (100. + radius_noise_percentage) / 100.);
+
+ typename Kernel::Point_to_vector_d k_pt_to_vec =
+ k.point_to_vector_d_object();
+ typename Kernel::Vector_to_point_d k_vec_to_pt =
+ k.vector_to_point_d_object();
+ typename Kernel::Scaled_vector_d k_scaled_vec =
+ k.scaled_vector_d_object();
+ p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio));
+ }
+
+ typename Kernel::Translated_point_d k_transl =
+ k.translated_point_d_object();
+ Point p2 = k_transl(p, c1_to_c2);
+ points.push_back(p);
+ points.push_back(p2);
+ i += 2;
+ }
+ return points;
+}
+
+// Product of a 3-sphere and a circle => d = 3 / D = 5
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_3sphere_and_circle(std::size_t num_points,
+ double sphere_radius) {
+ typedef typename Kernel::FT FT;
+ typedef typename Kernel::Point_d Point;
+ Kernel k;
+ CGAL::Random rng;
+ CGAL::Random_points_on_sphere_d<Point> generator(3, sphere_radius);
+ std::vector<Point> points;
+ points.reserve(num_points);
+
+ typename Kernel::Compute_coordinate_d k_coord =
+ k.compute_coordinate_d_object();
+ for (std::size_t i = 0; i < num_points;) {
+ Point p_sphere = *generator++; // First 3 coords
+
+ FT alpha = rng.get_double(0, 6.2832);
+ std::vector<FT> pt(5);
+ pt[0] = k_coord(p_sphere, 0);
+ pt[1] = k_coord(p_sphere, 1);
+ pt[2] = k_coord(p_sphere, 2);
+ pt[3] = std::cos(alpha);
+ pt[4] = std::sin(alpha);
+ Point p(pt.begin(), pt.end());
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+// a = big radius, b = small radius
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_3D(std::size_t num_points, double a, double b,
+ bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ double tmp = cos(u / 2) * sin(v) - sin(u / 2) * sin(2. * v);
+ Point p = construct_point(k,
+ (a + b * tmp) * cos(u),
+ (a + b * tmp) * sin(u),
+ b * (sin(u / 2) * sin(v) + cos(u / 2) * sin(2. * v)));
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+// a = big radius, b = small radius
+template <typename Kernel>
+std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_4D(std::size_t num_points, double a, double b,
+ double noise = 0., bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ Point p = construct_point(k,
+ (a + b * cos(v)) * cos(u) + (noise == 0. ? 0. : rng.get_double(0, noise)),
+ (a + b * cos(v)) * sin(u) + (noise == 0. ? 0. : rng.get_double(0, noise)),
+ b * sin(v) * cos(u / 2) + (noise == 0. ? 0. : rng.get_double(0, noise)),
+ b * sin(v) * sin(u / 2) + (noise == 0. ? 0. : rng.get_double(0, noise)));
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+
+// a = big radius, b = small radius
+
+template <typename Kernel>
+std::vector<typename Kernel::Point_d>
+generate_points_on_klein_bottle_variant_5D(
+ std::size_t num_points, double a, double b, bool uniform = false) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::FT FT;
+ Kernel k;
+ CGAL::Random rng;
+
+ // if uniform
+ std::size_t num_lines = (std::size_t)sqrt(num_points);
+
+ std::vector<Point> points;
+ points.reserve(num_points);
+ for (std::size_t i = 0; i < num_points;) {
+ FT u, v;
+ if (uniform) {
+ std::size_t k1 = i / num_lines;
+ std::size_t k2 = i % num_lines;
+ u = 6.2832 * k1 / num_lines;
+ v = 6.2832 * k2 / num_lines;
+ } else {
+ u = rng.get_double(0, 6.2832);
+ v = rng.get_double(0, 6.2832);
+ }
+ FT x1 = (a + b * cos(v)) * cos(u);
+ FT x2 = (a + b * cos(v)) * sin(u);
+ FT x3 = b * sin(v) * cos(u / 2);
+ FT x4 = b * sin(v) * sin(u / 2);
+ FT x5 = x1 + x2 + x3 + x4;
+
+ Point p = construct_point(k, x1, x2, x3, x4, x5);
+ points.push_back(p);
+ ++i;
+ }
+ return points;
+}
+
+} // namespace Gudhi
+
+#endif // RANDOM_POINT_GENERATORS_H_
diff --git a/include/gudhi/reader_utils.h b/include/gudhi/reader_utils.h
index 899f9df6..97a87edd 100644
--- a/include/gudhi/reader_utils.h
+++ b/include/gudhi/reader_utils.h
@@ -2,9 +2,9 @@
* (Geometric Understanding in Higher Dimensions) is a generic C++
* library for computational topology.
*
- * Author(s): Clément Maria
+ * Author(s): Clement Maria, Pawel Dlotko
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * Copyright (C) 2014 INRIA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,18 +30,25 @@
#include <iostream>
#include <fstream>
#include <map>
-#include <limits> // for numeric_limits<>
+#include <limits> // for numeric_limits
#include <string>
#include <vector>
+#include <utility> // for pair
+
+// Keep this file tag for Doxygen to parse the code, otherwise, functions are not documented.
+// It is required for global functions and variables.
+
+/** @file
+ * @brief This file includes common file reader for GUDHI
+ */
/**
- * \brief Read a set of points to turn it
- * into a vector< vector<double> > by filling points
+ * @brief Read a set of points to turn it into a vector< vector<double> > by filling points.
*
- * File format: 1 point per line
- * X11 X12 ... X1d
- * X21 X22 ... X2d
- * etc
+ * File format: 1 point per line<br>
+ * X11 X12 ... X1d<br>
+ * X21 X22 ... X2d<br>
+ * etc<br>
*/
inline void read_points(std::string file_name, std::vector< std::vector< double > > & points) {
std::ifstream in_file(file_name.c_str(), std::ios::in);
@@ -66,23 +73,29 @@ inline void read_points(std::string file_name, std::vector< std::vector< double
}
/**
- * \brief Read a graph from a file.
+ * @brief Read a graph from a file.
+ *
+ * \tparam Graph_t Type for the return graph. Must be constructible from iterators on pairs of Vertex_handle
+ * \tparam Filtration_value Type for the value of the read filtration
+ * \tparam Vertex_handle Type for the value of the read vertices
*
- * File format: 1 simplex per line
- * Dim1 X11 X12 ... X1d Fil1
- * Dim2 X21 X22 ... X2d Fil2
- * etc
+ * File format: 1 simplex per line<br>
+ * Dim1 X11 X12 ... X1d Fil1<br>
+ * Dim2 X21 X22 ... X2d Fil2<br>
+ * etc<br>
*
* The vertices must be labeled from 0 to n-1.
* Every simplex must appear exactly once.
* Simplices of dimension more than 1 are ignored.
*/
-inline Graph_t read_graph(std::string file_name) {
+template< typename Graph_t, typename Filtration_value, typename Vertex_handle >
+Graph_t read_graph(std::string file_name) {
std::ifstream in_(file_name.c_str(), std::ios::in);
if (!in_.is_open()) {
std::cerr << "Unable to open file " << file_name << std::endl;
}
+ typedef std::pair< Vertex_handle, Vertex_handle > Edge_t;
std::vector< Edge_t > edges;
std::vector< Filtration_value > edges_fil;
std::map< Vertex_handle, Filtration_value > vertices;
@@ -130,7 +143,7 @@ inline Graph_t read_graph(std::string file_name) {
Graph_t skel_graph(edges.begin(), edges.end(), edges_fil.begin(), vertices.size());
auto vertex_prop = boost::get(vertex_filtration_t(), skel_graph);
- boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
+ typename boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
auto v_it = vertices.begin();
for (std::tie(vi, vi_end) = boost::vertices(skel_graph); vi != vi_end; ++vi, ++v_it) {
boost::put(vertex_prop, *vi, v_it->second);
@@ -140,12 +153,12 @@ inline Graph_t read_graph(std::string file_name) {
}
/**
- * \brief Read a face from a file.
+ * @brief Read a face from a file.
*
- * File format: 1 simplex per line
- * Dim1 X11 X12 ... X1d Fil1
- * Dim2 X21 X22 ... X2d Fil2
- * etc
+ * File format: 1 simplex per line<br>
+ * Dim1 X11 X12 ... X1d Fil1<br>
+ * Dim2 X21 X22 ... X2d Fil2<br>
+ * etc<br>
*
* The vertices must be labeled from 0 to n-1.
* Every simplex must appear exactly once.
@@ -166,18 +179,16 @@ bool read_simplex(std::istream & in_, std::vector< Vertex_handle > & simplex, Fi
}
/**
- * \brief Read a hasse simplex from a file.
- *
- * File format: 1 simplex per line
- * Dim1 k11 k12 ... k1Dim1 Fil1
- * Dim2 k21 k22 ... k2Dim2 Fil2
- * etc
- *
- * The key of a simplex is its position in the filtration order
- * and also the number of its row in the file.
- * Dimi ki1 ki2 ... kiDimi Fili means that the ith simplex in the
- * filtration has dimension Dimi, filtration value fil1 and simplices with
- * key ki1 ... kiDimi in its boundary.*/
+ * @brief Read a hasse simplex from a file.
+ *
+ * File format: 1 simplex per line<br>
+ * Dim1 k11 k12 ... k1Dim1 Fil1<br>
+ * Dim2 k21 k22 ... k2Dim2 Fil2<br>
+ * etc<br>
+ *
+ * The key of a simplex is its position in the filtration order and also the number of its row in the file.
+ * Dimi ki1 ki2 ... kiDimi Fili means that the ith simplex in the filtration has dimension Dimi, filtration value
+ * fil1 and simplices with key ki1 ... kiDimi in its boundary.*/
template< typename Simplex_key, typename Filtration_value >
bool read_hasse_simplex(std::istream & in_, std::vector< Simplex_key > & boundary, Filtration_value & fil) {
int dim;
@@ -195,4 +206,93 @@ bool read_hasse_simplex(std::istream & in_, std::vector< Simplex_key > & boundar
return true;
}
+/**
+ * @brief Read a lower triangular distance matrix from a csv file. We assume that the .csv store the whole
+ * (square) matrix.
+ *
+ * @author Pawel Dlotko
+ *
+ * Square matrix file format:<br>
+ * 0;D12;...;D1j<br>
+ * D21;0;...;D2j<br>
+ * ...<br>
+ * Dj1;Dj2;...;0<br>
+ *
+ * lower matrix file format:<br>
+ * 0<br>
+ * D21;<br>
+ * D31;D32;<br>
+ * ...<br>
+ * Dj1;Dj2;...;Dj(j-1);<br>
+ *
+ **/
+template< typename Filtration_value >
+std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from_csv_file(const std::string& filename,
+ const char separator = ';') {
+#ifdef DEBUG_TRACES
+ std::cout << "Using procedure read_lower_triangular_matrix_from_csv_file \n";
+#endif // DEBUG_TRACES
+ std::vector< std::vector< Filtration_value > > result;
+ std::ifstream in;
+ in.open(filename.c_str());
+ if (!in.is_open()) {
+ return result;
+ }
+
+ std::string line;
+
+ // the first line is emtpy, so we ignore it:
+ std::getline(in, line);
+ std::vector< Filtration_value > values_in_this_line;
+ result.push_back(values_in_this_line);
+
+ int number_of_line = 0;
+
+ // first, read the file line by line to a string:
+ while (std::getline(in, line)) {
+ // if line is empty, break
+ if (line.size() == 0)
+ break;
+
+ // if the last element of a string is comma:
+ if (line[ line.size() - 1 ] == separator) {
+ // then shrink the string by one
+ line.pop_back();
+ }
+
+ // replace all commas with spaces
+ std::replace(line.begin(), line.end(), separator, ' ');
+
+ // put the new line to a stream
+ std::istringstream iss(line);
+ // and now read the doubles.
+
+ int number_of_entry = 0;
+ std::vector< Filtration_value > values_in_this_line;
+ while (iss.good()) {
+ double entry;
+ iss >> entry;
+ if (number_of_entry <= number_of_line) {
+ values_in_this_line.push_back(entry);
+ }
+ ++number_of_entry;
+ }
+ if (!values_in_this_line.empty())result.push_back(values_in_this_line);
+ ++number_of_line;
+ }
+ in.close();
+
+#ifdef DEBUG_TRACES
+ std::cerr << "Here is the matrix we read : \n";
+ for (size_t i = 0; i != result.size(); ++i) {
+ for (size_t j = 0; j != result[i].size(); ++j) {
+ std::cerr << result[i][j] << " ";
+ }
+ std::cerr << std::endl;
+ }
+#endif // DEBUG_TRACES
+
+ return result;
+} // read_lower_triangular_matrix_from_csv_file
+
#endif // READER_UTILS_H_
diff --git a/include/gudhi/sparsify_point_set.h b/include/gudhi/sparsify_point_set.h
new file mode 100644
index 00000000..507f8c79
--- /dev/null
+++ b/include/gudhi/sparsify_point_set.h
@@ -0,0 +1,113 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 INRIA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SPARSIFY_POINT_SET_H_
+#define SPARSIFY_POINT_SET_H_
+
+#include <gudhi/Kd_tree_search.h>
+#ifdef GUDHI_SUBSAMPLING_PROFILING
+#include <gudhi/Clock.h>
+#endif
+
+#include <cstddef>
+#include <vector>
+
+namespace Gudhi {
+
+namespace subsampling {
+
+/**
+ * \ingroup subsampling
+ * \brief Outputs a subset of the input points so that the
+ * squared distance between any two points
+ * is greater than or equal to `min_squared_dist`.
+ *
+ * \tparam Kernel must be a model of the <a target="_blank"
+ * href="http://doc.cgal.org/latest/Spatial_searching/classSearchTraits.html">SearchTraits</a>
+ * concept, such as the <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class, which
+ * can be static if you know the ambiant dimension at compile-time, or dynamic if you don't.
+ * \tparam Point_range Range whose value type is Kernel::Point_d. It must provide random-access
+ * via `operator[]` and the points should be stored contiguously in memory.
+ * \tparam OutputIterator Output iterator whose value type is Kernel::Point_d.
+ *
+ * @param[in] k A kernel object.
+ * @param[in] input_pts Const reference to the input points.
+ * @param[in] min_squared_dist Minimum squared distance separating the output points.
+ * @param[out] output_it The output iterator.
+ */
+template <typename Kernel, typename Point_range, typename OutputIterator>
+void
+sparsify_point_set(
+ const Kernel &k, Point_range const& input_pts,
+ typename Kernel::FT min_squared_dist,
+ OutputIterator output_it) {
+ typedef typename Gudhi::spatial_searching::Kd_tree_search<
+ Kernel, Point_range> Points_ds;
+
+#ifdef GUDHI_SUBSAMPLING_PROFILING
+ Gudhi::Clock t;
+#endif
+
+ Points_ds points_ds(input_pts);
+
+ std::vector<bool> dropped_points(input_pts.size(), false);
+
+ // Parse the input points, and add them if they are not too close to
+ // the other points
+ std::size_t pt_idx = 0;
+ for (typename Point_range::const_iterator it_pt = input_pts.begin();
+ it_pt != input_pts.end();
+ ++it_pt, ++pt_idx) {
+ if (dropped_points[pt_idx])
+ continue;
+
+ *output_it++ = *it_pt;
+
+ auto ins_range = points_ds.query_incremental_nearest_neighbors(*it_pt);
+
+ // If another point Q is closer that min_squared_dist, mark Q to be dropped
+ for (auto const& neighbor : ins_range) {
+ std::size_t neighbor_point_idx = neighbor.first;
+ // If the neighbor is too close, we drop the neighbor
+ if (neighbor.second < min_squared_dist) {
+ // N.B.: If neighbor_point_idx < pt_idx,
+ // dropped_points[neighbor_point_idx] is already true but adding a
+ // test doesn't make things faster, so why bother?
+ dropped_points[neighbor_point_idx] = true;
+ } else {
+ break;
+ }
+ }
+ }
+
+#ifdef GUDHI_SUBSAMPLING_PROFILING
+ t.end();
+ std::cerr << "Point set sparsified in " << t.num_seconds()
+ << " seconds." << std::endl;
+#endif
+}
+
+} // namespace subsampling
+} // namespace Gudhi
+
+#endif // SPARSIFY_POINT_SET_H_
diff --git a/include/gudhi_patches/Bottleneck_distance_CGAL_patches.txt b/include/gudhi_patches/Bottleneck_distance_CGAL_patches.txt
new file mode 100644
index 00000000..a588d113
--- /dev/null
+++ b/include/gudhi_patches/Bottleneck_distance_CGAL_patches.txt
@@ -0,0 +1,3 @@
+CGAL/Kd_tree.h
+CGAL/Kd_tree_node.h
+CGAL/Orthogonal_incremental_neighbor_search.h
diff --git a/include/gudhi_patches/CGAL/Convex_hull.h b/include/gudhi_patches/CGAL/Convex_hull.h
new file mode 100644
index 00000000..a8f91bf8
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Convex_hull.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+/* RANDOM DESIGN IDEAS:
+- Use a policy tag to choose for incremental with inserts only or
+ incremental with removals and inserts.
+ In the first case: use Triangulation for storage.
+ In the second case: use Delaunay !
+ In this second case, we must keeps the points that are inserted in the hull,
+ as they may become part of the boundary later on, when some points are removed.
+- Constructor with range argument uses quickhull.
+*/
+
+#ifndef CGAL_CONVEX_HULL_H
+#define CGAL_CONVEX_HULL_H
+
+namespace CGAL {
+
+template < class CHTraits, class TDS_ = Default >
+class Convex_hull
+{
+ typedef typename Maximal_dimension<typename CHTraits::Point_d>::type
+ Maximal_dimension_;
+ typedef typename Default::Get<TDS_, Triangulation_data_structure
+ < Maximal_dimension_,
+ Triangulation_vertex<CHTraits>,
+ Triangulation_full_cell<CHTraits> >
+ >::type TDS;
+ typedef Convex_hull<CHTraits, TDS_> Self;
+
+ typedef typename CHTraits::Coaffine_orientation_d
+ Coaffine_orientation_d;
+ typedef typename CHTraits::Orientation_d Orientation_d;
+
+public:
+};
+
+} //namespace CGAL
+
+#endif // CGAL_CONVEX_HULL_H
diff --git a/include/gudhi_patches/CGAL/Delaunay_triangulation.h b/include/gudhi_patches/CGAL/Delaunay_triangulation.h
new file mode 100644
index 00000000..071cd184
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Delaunay_triangulation.h
@@ -0,0 +1,933 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_DELAUNAY_COMPLEX_H
+#define CGAL_DELAUNAY_COMPLEX_H
+
+#include <CGAL/tss.h>
+#include <CGAL/Triangulation.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/Default.h>
+
+#include <boost/iterator/transform_iterator.hpp>
+
+#include <algorithm>
+
+namespace CGAL {
+
+template< typename DCTraits, typename _TDS = Default >
+class Delaunay_triangulation
+: public Triangulation<DCTraits,
+ typename Default::Get<_TDS, Triangulation_data_structure<
+ typename DCTraits::Dimension,
+ Triangulation_vertex<DCTraits>,
+ Triangulation_full_cell<DCTraits> >
+ >::type >
+{
+ typedef typename DCTraits::Dimension Maximal_dimension_;
+ typedef typename Default::Get<_TDS, Triangulation_data_structure<
+ Maximal_dimension_,
+ Triangulation_vertex<DCTraits>,
+ Triangulation_full_cell<DCTraits> >
+ >::type TDS;
+ typedef Triangulation<DCTraits, TDS> Base;
+ typedef Delaunay_triangulation<DCTraits, _TDS> Self;
+
+ typedef typename DCTraits::Side_of_oriented_sphere_d
+ Side_of_oriented_sphere_d;
+ typedef typename DCTraits::Orientation_d Orientation_d;
+
+public: // PUBLIC NESTED TYPES
+
+ typedef DCTraits Geom_traits;
+ typedef typename Base::Triangulation_ds Triangulation_ds;
+
+ typedef typename Base::Vertex Vertex;
+ typedef typename Base::Full_cell Full_cell;
+ typedef typename Base::Facet Facet;
+ typedef typename Base::Face Face;
+
+ typedef typename Base::Maximal_dimension Maximal_dimension;
+ typedef typename DCTraits::Point_d Point;
+ typedef typename DCTraits::Point_d Point_d;
+
+ typedef typename Base::Vertex_handle Vertex_handle;
+ typedef typename Base::Vertex_iterator Vertex_iterator;
+ typedef typename Base::Vertex_const_handle Vertex_const_handle;
+ typedef typename Base::Vertex_const_iterator Vertex_const_iterator;
+
+ typedef typename Base::Full_cell_handle Full_cell_handle;
+ typedef typename Base::Full_cell_iterator Full_cell_iterator;
+ typedef typename Base::Full_cell_const_handle Full_cell_const_handle;
+ typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator;
+ typedef typename Base::Finite_full_cell_const_iterator
+ Finite_full_cell_const_iterator;
+
+ typedef typename Base::size_type size_type;
+ typedef typename Base::difference_type difference_type;
+
+ typedef typename Base::Locate_type Locate_type;
+
+ //Tag to distinguish triangulations with weighted_points
+ typedef Tag_false Weighted_tag;
+
+protected: // DATA MEMBERS
+
+
+public:
+
+ using typename Base::Rotor;
+ using Base::maximal_dimension;
+ using Base::are_incident_full_cells_valid;
+ using Base::coaffine_orientation_predicate;
+ using Base::reset_flat_orientation;
+ using Base::current_dimension;
+ //using Base::star;
+ //using Base::incident_full_cells;
+ using Base::geom_traits;
+ using Base::index_of_covertex;
+ //using Base::index_of_second_covertex;
+ using Base::infinite_vertex;
+ using Base::rotate_rotor;
+ using Base::insert_in_hole;
+ using Base::insert_outside_convex_hull_1;
+ using Base::is_infinite;
+ using Base::locate;
+ using Base::points_begin;
+ using Base::set_neighbors;
+ using Base::new_full_cell;
+ using Base::number_of_vertices;
+ using Base::orientation;
+ using Base::tds;
+ using Base::reorient_full_cells;
+ using Base::full_cell;
+ using Base::full_cells_begin;
+ using Base::full_cells_end;
+ using Base::finite_full_cells_begin;
+ using Base::finite_full_cells_end;
+ using Base::vertices_begin;
+ using Base::vertices_end;
+ // using Base::
+
+private:
+ //*** Side_of_oriented_subsphere_d ***
+ typedef typename Base::Flat_orientation_d Flat_orientation_d;
+ typedef typename Base::Construct_flat_orientation_d Construct_flat_orientation_d;
+ typedef typename DCTraits::In_flat_side_of_oriented_sphere_d In_flat_side_of_oriented_sphere_d;
+ // Wrapper
+ struct Side_of_oriented_subsphere_d
+ {
+ boost::optional<Flat_orientation_d>* fop;
+ Construct_flat_orientation_d cfo;
+ In_flat_side_of_oriented_sphere_d ifsoos;
+
+ Side_of_oriented_subsphere_d(
+ boost::optional<Flat_orientation_d>& x,
+ Construct_flat_orientation_d const&y,
+ In_flat_side_of_oriented_sphere_d const&z)
+ : fop(&x), cfo(y), ifsoos(z) {}
+
+ template<class Iter>
+ CGAL::Orientation operator()(Iter a, Iter b, const Point & p)const
+ {
+ if(!*fop)
+ *fop=cfo(a,b);
+ return ifsoos(fop->get(),a,b,p);
+ }
+ };
+public:
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS
+
+ Delaunay_triangulation(int dim, const Geom_traits &k = Geom_traits())
+ : Base(dim, k)
+ {
+ }
+
+ // With this constructor,
+ // the user can specify a Flat_orientation_d object to be used for
+ // orienting simplices of a specific dimension
+ // (= preset_flat_orientation_.first)
+ // It it used by the dark triangulations created by DT::remove
+ Delaunay_triangulation(
+ int dim,
+ const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation,
+ const Geom_traits &k = Geom_traits())
+ : Base(dim, preset_flat_orientation, k)
+ {
+ }
+
+ ~Delaunay_triangulation() {}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS
+
+ // Not Documented
+ Side_of_oriented_subsphere_d side_of_oriented_subsphere_predicate() const
+ {
+ return Side_of_oriented_subsphere_d (
+ flat_orientation_,
+ geom_traits().construct_flat_orientation_d_object(),
+ geom_traits().in_flat_side_of_oriented_sphere_d_object()
+ );
+ }
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
+
+ Full_cell_handle remove(Vertex_handle);
+ Full_cell_handle remove(const Point & p, Full_cell_handle hint = Full_cell_handle())
+ {
+ Locate_type lt;
+ Face f(maximal_dimension());
+ Facet ft;
+ Full_cell_handle s = locate(p, lt, f, ft, hint);
+ if( Base::ON_VERTEX == lt )
+ {
+ return remove(s->vertex(f.index(0)));
+ }
+ return Full_cell_handle();
+ }
+
+ template< typename ForwardIterator >
+ void remove(ForwardIterator start, ForwardIterator end)
+ {
+ while( start != end )
+ remove(*start++);
+ }
+
+ // Not documented
+ void remove_decrease_dimension(Vertex_handle);
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS
+
+ template< typename ForwardIterator >
+ size_type insert(ForwardIterator start, ForwardIterator end)
+ {
+ size_type n = number_of_vertices();
+ std::vector<Point> points(start, end);
+ spatial_sort(points.begin(), points.end(), geom_traits());
+ Full_cell_handle hint;
+ for( typename std::vector<Point>::const_iterator p = points.begin(); p != points.end(); ++p )
+ {
+ hint = insert(*p, hint)->full_cell();
+ }
+ return number_of_vertices() - n;
+ }
+ Vertex_handle insert(const Point &, Locate_type, const Face &, const Facet &, Full_cell_handle);
+ Vertex_handle insert(const Point & p, Full_cell_handle start = Full_cell_handle())
+ {
+ Locate_type lt;
+ Face f(maximal_dimension());
+ Facet ft;
+ Full_cell_handle s = locate(p, lt, f, ft, start);
+ return insert(p, lt, f, ft, s);
+ }
+ Vertex_handle insert(const Point & p, Vertex_handle hint)
+ {
+ CGAL_assertion( Vertex_handle() != hint );
+ return insert(p, hint->full_cell());
+ }
+ Vertex_handle insert_outside_affine_hull(const Point &);
+ Vertex_handle insert_in_conflicting_cell(const Point &, Full_cell_handle);
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES
+
+ bool is_in_conflict(const Point &, Full_cell_const_handle) const;
+ template< class OrientationPredicate >
+ Oriented_side perturbed_side_of_positive_sphere(const Point &,
+ Full_cell_const_handle, const OrientationPredicate &) const;
+
+ template< typename OutputIterator >
+ Facet compute_conflict_zone(const Point &, Full_cell_handle, OutputIterator) const;
+
+ template < typename OrientationPredicate, typename SideOfOrientedSpherePredicate >
+ class Conflict_predicate
+ {
+ const Self & dc_;
+ const Point & p_;
+ OrientationPredicate ori_;
+ SideOfOrientedSpherePredicate side_of_s_;
+ int cur_dim_;
+ public:
+ Conflict_predicate(
+ const Self & dc,
+ const Point & p,
+ const OrientationPredicate & ori,
+ const SideOfOrientedSpherePredicate & side)
+ : dc_(dc), p_(p), ori_(ori), side_of_s_(side), cur_dim_(dc.current_dimension()) {}
+
+ inline
+ bool operator()(Full_cell_const_handle s) const
+ {
+ bool ok;
+ if( ! dc_.is_infinite(s) )
+ {
+ Oriented_side side = side_of_s_(dc_.points_begin(s), dc_.points_begin(s) + cur_dim_ + 1, p_);
+ if( ON_POSITIVE_SIDE == side )
+ ok = true;
+ else if( ON_NEGATIVE_SIDE == side )
+ ok = false;
+ else
+ ok = ON_POSITIVE_SIDE == dc_.perturbed_side_of_positive_sphere<OrientationPredicate>(p_, s, ori_);
+ }
+ else
+ {
+ typedef typename Full_cell::Vertex_handle_const_iterator VHCI;
+ typedef Substitute_point_in_vertex_iterator<VHCI> F;
+ F spivi(dc_.infinite_vertex(), &p_);
+
+ Orientation o = ori_(
+ boost::make_transform_iterator(s->vertices_begin(), spivi),
+ boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1,
+ spivi));
+
+ if( POSITIVE == o )
+ ok = true;
+ else if( o == NEGATIVE )
+ ok = false;
+ else
+ ok = (*this)(s->neighbor( s->index( dc_.infinite_vertex() ) ));
+ }
+ return ok;
+ }
+ };
+
+ template < typename ConflictPredicate >
+ class Conflict_traversal_predicate
+ {
+ const Self & dc_;
+ const ConflictPredicate & pred_;
+ public:
+ Conflict_traversal_predicate(const Self & dc, const ConflictPredicate & pred)
+ : dc_(dc), pred_(pred)
+ {}
+ inline
+ bool operator()(const Facet & f) const
+ {
+ return pred_(dc_.full_cell(f)->neighbor(dc_.index_of_covertex(f)));
+ }
+ };
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
+
+ bool is_valid(bool verbose = false, int level = 0) const;
+
+private:
+ // Some internal types to shorten notation
+ typedef typename Base::Coaffine_orientation_d Coaffine_orientation_d;
+ using Base::flat_orientation_;
+ typedef Conflict_predicate<Coaffine_orientation_d, Side_of_oriented_subsphere_d>
+ Conflict_pred_in_subspace;
+ typedef Conflict_predicate<Orientation_d, Side_of_oriented_sphere_d>
+ Conflict_pred_in_fullspace;
+ typedef Conflict_traversal_predicate<Conflict_pred_in_subspace>
+ Conflict_traversal_pred_in_subspace;
+ typedef Conflict_traversal_predicate<Conflict_pred_in_fullspace>
+ Conflict_traversal_pred_in_fullspace;
+};
+
+// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+// FUNCTIONS THAT ARE MEMBER METHODS:
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
+
+template< typename DCTraits, typename TDS >
+typename Delaunay_triangulation<DCTraits, TDS>::Full_cell_handle
+Delaunay_triangulation<DCTraits, TDS>
+::remove( Vertex_handle v )
+{
+ CGAL_precondition( ! is_infinite(v) );
+ CGAL_expensive_precondition( is_vertex(v) );
+
+ // THE CASE cur_dim == 0
+ if( 0 == current_dimension() )
+ {
+ remove_decrease_dimension(v);
+ return Full_cell_handle();
+ }
+ else if( 1 == current_dimension() )
+ { // THE CASE cur_dim == 1
+ if( 2 == number_of_vertices() )
+ {
+ remove_decrease_dimension(v);
+ return Full_cell_handle();
+ }
+ Full_cell_handle left = v->full_cell();
+ if( 0 == left->index(v) )
+ left = left->neighbor(1);
+ CGAL_assertion( 1 == left->index(v) );
+ Full_cell_handle right = left->neighbor(0);
+
+ tds().associate_vertex_with_full_cell(left, 1, right->vertex(1));
+ set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0));
+
+ tds().delete_vertex(v);
+ tds().delete_full_cell(right);
+ return left;
+ }
+
+ // THE CASE cur_dim >= 2
+ // Gather the finite vertices sharing an edge with |v|
+ typedef typename Base::template Full_cell_set<Full_cell_handle> Simplices;
+ Simplices simps;
+ std::back_insert_iterator<Simplices> out(simps);
+ tds().incident_full_cells(v, out);
+ typedef std::set<Vertex_handle> Vertex_set;
+ Vertex_set verts;
+ Vertex_handle vh;
+ for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it )
+ for( int i = 0; i <= current_dimension(); ++i )
+ {
+ vh = (*it)->vertex(i);
+ if( is_infinite(vh) )
+ continue;
+ if( vh == v )
+ continue;
+ verts.insert(vh);
+ }
+
+ // After gathering finite neighboring vertices, create their Dark Delaunay triangulation
+ typedef Triangulation_vertex<Geom_traits, Vertex_handle> Dark_vertex_base;
+ typedef Triangulation_full_cell<Geom_traits,
+ internal::Triangulation::Dark_full_cell_data<Self> > Dark_full_cell_base;
+ typedef Triangulation_data_structure<Maximal_dimension, Dark_vertex_base, Dark_full_cell_base> Dark_tds;
+ typedef Delaunay_triangulation<DCTraits, Dark_tds> Dark_triangulation;
+ typedef typename Dark_triangulation::Face Dark_face;
+ typedef typename Dark_triangulation::Facet Dark_facet;
+ typedef typename Dark_triangulation::Vertex_handle Dark_v_handle;
+ typedef typename Dark_triangulation::Full_cell_handle Dark_s_handle;
+
+ // If flat_orientation_ is defined, we give it the Dark triangulation
+ // so that the orientation it uses for "current_dimension()"-simplices is
+ // coherent with the global triangulation
+ Dark_triangulation dark_side(
+ maximal_dimension(),
+ flat_orientation_ ?
+ std::pair<int, const Flat_orientation_d *>(current_dimension(), flat_orientation_.get_ptr())
+ : std::pair<int, const Flat_orientation_d *>((std::numeric_limits<int>::max)(), (Flat_orientation_d*) NULL) );
+
+ Dark_s_handle dark_s;
+ Dark_v_handle dark_v;
+ typedef std::map<Vertex_handle, Dark_v_handle> Vertex_map;
+ Vertex_map light_to_dark;
+ typename Vertex_set::iterator vit = verts.begin();
+ while( vit != verts.end() )
+ {
+ dark_v = dark_side.insert((*vit)->point(), dark_s);
+ dark_s = dark_v->full_cell();
+ dark_v->data() = *vit;
+ light_to_dark[*vit] = dark_v;
+ ++vit;
+ }
+
+ if( dark_side.current_dimension() != current_dimension() )
+ {
+ CGAL_assertion( dark_side.current_dimension() + 1 == current_dimension() );
+ // Here, the finite neighbors of |v| span a affine subspace of
+ // dimension one less than the current dimension. Two cases are possible:
+ if( (size_type)(verts.size() + 1) == number_of_vertices() )
+ {
+ remove_decrease_dimension(v);
+ return Full_cell_handle();
+ }
+ else
+ { // |v| is strictly outside the convex hull of the rest of the points. This is an
+ // easy case: first, modify the finite full_cells, then, delete the infinite ones.
+ // We don't even need the Dark triangulation.
+ Simplices infinite_simps;
+ {
+ Simplices finite_simps;
+ for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it )
+ if( is_infinite(*it) )
+ infinite_simps.push_back(*it);
+ else
+ finite_simps.push_back(*it);
+ simps.swap(finite_simps);
+ } // now, simps only contains finite simplices
+ // First, modify the finite full_cells:
+ for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it )
+ {
+ int v_idx = (*it)->index(v);
+ tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex());
+ }
+ // Make the handles to infinite full cells searchable
+ infinite_simps.make_searchable();
+ // Then, modify the neighboring relation
+ for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it )
+ {
+ for( int i = 0; i <= current_dimension(); ++i )
+ {
+ if (is_infinite((*it)->vertex(i)))
+ continue;
+ (*it)->vertex(i)->set_full_cell(*it);
+ Full_cell_handle n = (*it)->neighbor(i);
+ // Was |n| a finite full cell prior to removing |v| ?
+ if( ! infinite_simps.contains(n) )
+ continue;
+ int n_idx = n->index(v);
+ set_neighbors(*it, i, n->neighbor(n_idx), n->neighbor(n_idx)->index(n));
+ }
+ }
+ Full_cell_handle ret_s;
+ // Then, we delete the infinite full_cells
+ for( typename Simplices::iterator it = infinite_simps.begin(); it != infinite_simps.end(); ++it )
+ tds().delete_full_cell(*it);
+ tds().delete_vertex(v);
+ return simps.front();
+ }
+ }
+ else // From here on, dark_side.current_dimension() == current_dimension()
+ {
+ dark_side.infinite_vertex()->data() = infinite_vertex();
+ light_to_dark[infinite_vertex()] = dark_side.infinite_vertex();
+ }
+
+ // Now, compute the conflict zone of v->point() in
+ // the dark side. This is precisely the set of full_cells
+ // that we have to glue back into the light side.
+ Dark_face dark_f(dark_side.maximal_dimension());
+ Dark_facet dark_ft;
+ typename Dark_triangulation::Locate_type lt;
+ dark_s = dark_side.locate(v->point(), lt, dark_f, dark_ft);
+ CGAL_assertion( lt != Dark_triangulation::ON_VERTEX
+ && lt != Dark_triangulation::OUTSIDE_AFFINE_HULL );
+
+ // |ret_s| is the full_cell that we return
+ Dark_s_handle dark_ret_s = dark_s;
+ Full_cell_handle ret_s;
+
+ typedef typename Base::template Full_cell_set<Dark_s_handle> Dark_full_cells;
+ Dark_full_cells conflict_zone;
+ std::back_insert_iterator<Dark_full_cells> dark_out(conflict_zone);
+
+ dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out);
+ // Make the dark simplices in the conflict zone searchable
+ conflict_zone.make_searchable();
+
+ // THE FOLLOWING SHOULD MAYBE GO IN TDS.
+ // Here is the plan:
+ // 1. Pick any Facet from boundary of the light zone
+ // 2. Find corresponding Facet on boundary of dark zone
+ // 3. stitch.
+
+ // 1. Build a facet on the boudary of the light zone:
+ Full_cell_handle light_s = *simps.begin();
+ Facet light_ft(light_s, light_s->index(v));
+
+ // 2. Find corresponding Dark_facet on boundary of the dark zone
+ Dark_full_cells dark_incident_s;
+ for( int i = 0; i <= current_dimension(); ++i )
+ {
+ if( index_of_covertex(light_ft) == i )
+ continue;
+ Dark_v_handle dark_v = light_to_dark[full_cell(light_ft)->vertex(i)];
+ dark_incident_s.clear();
+ dark_out = std::back_inserter(dark_incident_s);
+ dark_side.tds().incident_full_cells(dark_v, dark_out);
+ for( typename Dark_full_cells::iterator it = dark_incident_s.begin(); it != dark_incident_s.end(); ++it )
+ {
+ (*it)->data().count_ += 1;
+ }
+ }
+
+ for( typename Dark_full_cells::iterator it = dark_incident_s.begin(); it != dark_incident_s.end(); ++it )
+ {
+ if( current_dimension() != (*it)->data().count_ )
+ continue;
+ if( ! conflict_zone.contains(*it) )
+ continue;
+ // We found a full_cell incident to the dark facet corresponding to the light facet |light_ft|
+ int ft_idx = 0;
+ while( light_s->has_vertex( (*it)->vertex(ft_idx)->data() ) )
+ ++ft_idx;
+ dark_ft = Dark_facet(*it, ft_idx);
+ break;
+ }
+ // Pre-3. Now, we are ready to traverse both boundary and do the stiching.
+
+ // But first, we create the new full_cells in the light triangulation,
+ // with as much adjacency information as possible.
+
+ // Create new full_cells with vertices
+ for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it )
+ {
+ Full_cell_handle new_s = new_full_cell();
+ (*it)->data().light_copy_ = new_s;
+ for( int i = 0; i <= current_dimension(); ++i )
+ tds().associate_vertex_with_full_cell(new_s, i, (*it)->vertex(i)->data());
+ if( dark_ret_s == *it )
+ ret_s = new_s;
+ }
+
+ // Setup adjacencies inside the hole
+ for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it )
+ {
+ Full_cell_handle new_s = (*it)->data().light_copy_;
+ for( int i = 0; i <= current_dimension(); ++i )
+ if( conflict_zone.contains((*it)->neighbor(i)) )
+ tds().set_neighbors(new_s, i, (*it)->neighbor(i)->data().light_copy_, (*it)->mirror_index(i));
+ }
+
+ // 3. Stitch
+ simps.make_searchable();
+ typedef std::queue<std::pair<Facet, Dark_facet> > Queue;
+ Queue q;
+ q.push(std::make_pair(light_ft, dark_ft));
+ dark_s = dark_side.full_cell(dark_ft);
+ int dark_i = dark_side.index_of_covertex(dark_ft);
+ // mark dark_ft as visited:
+ // TODO try by marking with Dark_v_handle (vertex)
+ dark_s->neighbor(dark_i)->set_neighbor(dark_s->mirror_index(dark_i), Dark_s_handle());
+ while( ! q.empty() )
+ {
+ std::pair<Facet, Dark_facet> p = q.front();
+ q.pop();
+ light_ft = p.first;
+ dark_ft = p.second;
+ light_s = full_cell(light_ft);
+ int light_i = index_of_covertex(light_ft);
+ dark_s = dark_side.full_cell(dark_ft);
+ int dark_i = dark_side.index_of_covertex(dark_ft);
+ Full_cell_handle light_n = light_s->neighbor(light_i);
+ set_neighbors(dark_s->data().light_copy_, dark_i, light_n, light_s->mirror_index(light_i));
+ for( int di = 0; di <= current_dimension(); ++di )
+ {
+ if( di == dark_i )
+ continue;
+ int li = light_s->index(dark_s->vertex(di)->data());
+ Rotor light_r(light_s, li, light_i);
+ typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i);
+
+ while (simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r))))
+ light_r = rotate_rotor(light_r);
+
+ while (conflict_zone.contains(cpp11::get<0>(dark_r)->neighbor(cpp11::get<1>(dark_r))))
+ dark_r = dark_side.rotate_rotor(dark_r);
+
+ Dark_s_handle dark_ns = cpp11::get<0>(dark_r);
+ int dark_ni = cpp11::get<1>(dark_r);
+ Full_cell_handle light_ns = cpp11::get<0>(light_r);
+ int light_ni = cpp11::get<1>(light_r);
+ // mark dark_r as visited:
+ // TODO try by marking with Dark_v_handle (vertex)
+ Dark_s_handle outside = dark_ns->neighbor(dark_ni);
+ Dark_v_handle mirror = dark_ns->mirror_vertex(dark_ni, current_dimension());
+ int dn = outside->index(mirror);
+ if( Dark_s_handle() == outside->neighbor(dn) )
+ continue;
+ outside->set_neighbor(dn, Dark_s_handle());
+ q.push(std::make_pair(Facet(light_ns, light_ni), Dark_facet(dark_ns, dark_ni)));
+ }
+ }
+ tds().delete_full_cells(simps.begin(), simps.end());
+ tds().delete_vertex(v);
+ return ret_s;
+}
+
+template< typename DCTraits, typename TDS >
+void
+Delaunay_triangulation<DCTraits, TDS>
+::remove_decrease_dimension(Vertex_handle v)
+{
+ CGAL_precondition( current_dimension() >= 0 );
+ tds().remove_decrease_dimension(v, infinite_vertex());
+ // reset the predicates:
+ reset_flat_orientation();
+ if( 1 <= current_dimension() )
+ {
+ Full_cell_handle inf_v_cell = infinite_vertex()->full_cell();
+ int inf_v_index = inf_v_cell->index(infinite_vertex());
+ Full_cell_handle s = inf_v_cell->neighbor(inf_v_index);
+ Orientation o = orientation(s);
+ CGAL_assertion( ZERO != o );
+ if( NEGATIVE == o )
+ reorient_full_cells();
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS
+
+template< typename DCTraits, typename TDS >
+typename Delaunay_triangulation<DCTraits, TDS>::Vertex_handle
+Delaunay_triangulation<DCTraits, TDS>
+::insert(const Point & p, Locate_type lt, const Face & f, const Facet &, Full_cell_handle s)
+{
+ switch( lt )
+ {
+ case Base::OUTSIDE_AFFINE_HULL:
+ return insert_outside_affine_hull(p);
+ break;
+ case Base::ON_VERTEX:
+ {
+ Vertex_handle v = s->vertex(f.index(0));
+ v->set_point(p);
+ return v;
+ break;
+ }
+ default:
+ if( 1 == current_dimension() )
+ {
+ if( Base::OUTSIDE_CONVEX_HULL == lt )
+ {
+ return insert_outside_convex_hull_1(p, s);
+ }
+ Vertex_handle v = tds().insert_in_full_cell(s);
+ v->set_point(p);
+ return v;
+ }
+ else
+ return insert_in_conflicting_cell(p, s);
+ break;
+ }
+}
+
+/*
+[Undocumented function]
+
+Inserts the point `p` in the Delaunay triangulation. Returns a handle to the
+(possibly newly created) vertex at that position.
+\pre The point `p`
+must lie outside the affine hull of the Delaunay triangulation. This implies that
+`dt`.`current_dimension()` must be less than `dt`.`maximal_dimension()`.
+*/
+template< typename DCTraits, typename TDS >
+typename Delaunay_triangulation<DCTraits, TDS>::Vertex_handle
+Delaunay_triangulation<DCTraits, TDS>
+::insert_outside_affine_hull(const Point & p)
+{
+ // we don't use Base::insert_outside_affine_hull(...) because here, we
+ // also need to reset the side_of_oriented_subsphere functor.
+ CGAL_precondition( current_dimension() < maximal_dimension() );
+ Vertex_handle v = tds().insert_increase_dimension(infinite_vertex());
+ // reset the predicates:
+ reset_flat_orientation();
+ v->set_point(p);
+ if( current_dimension() >= 1 )
+ {
+ Full_cell_handle inf_v_cell = infinite_vertex()->full_cell();
+ int inf_v_index = inf_v_cell->index(infinite_vertex());
+ Full_cell_handle s = inf_v_cell->neighbor(inf_v_index);
+ Orientation o = orientation(s);
+ CGAL_assertion( ZERO != o );
+ if( NEGATIVE == o )
+ reorient_full_cells();
+
+ // We just inserted the second finite point and the right infinite
+ // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be
+ // consistent with the rest of the cells
+ if (current_dimension() == 1)
+ {
+ // Is "inf_v_cell" the right infinite cell?
+ // Then inf_v_index should be 1
+ if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0
+ && inf_v_index == 0)
+ {
+ inf_v_cell->swap_vertices(
+ current_dimension() - 1, current_dimension());
+ }
+ // Otherwise, let's find the right infinite cell
+ else
+ {
+ inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2);
+ inf_v_index = inf_v_cell->index(infinite_vertex());
+ // Is "inf_v_cell" the right infinite cell?
+ // Then inf_v_index should be 1
+ if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0
+ && inf_v_index == 0)
+ {
+ inf_v_cell->swap_vertices(
+ current_dimension() - 1, current_dimension());
+ }
+ }
+ }
+ }
+ return v;
+}
+
+/*!
+[Undocumented function]
+
+Inserts the point `p` in the Delaunay triangulation. Returns a handle to the
+(possibly newly created) vertex at that position.
+\pre The point `p` must be in conflict with the full cell `c`.
+*/
+template< typename DCTraits, typename TDS >
+typename Delaunay_triangulation<DCTraits, TDS>::Vertex_handle
+Delaunay_triangulation<DCTraits, TDS>
+::insert_in_conflicting_cell(const Point & p, Full_cell_handle s)
+{
+ CGAL_precondition(is_in_conflict(p, s));
+
+ // for storing conflicting full_cells.
+ typedef std::vector<Full_cell_handle> Full_cell_h_vector;
+ CGAL_STATIC_THREAD_LOCAL_VARIABLE(Full_cell_h_vector,cs,0);
+ cs.clear();
+
+ std::back_insert_iterator<Full_cell_h_vector> out(cs);
+ Facet ft = compute_conflict_zone(p, s, out);
+ return insert_in_hole(p, cs.begin(), cs.end(), ft);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES
+
+// NOT DOCUMENTED
+template< typename DCTraits, typename TDS >
+template< typename OrientationPred >
+Oriented_side
+Delaunay_triangulation<DCTraits, TDS>
+::perturbed_side_of_positive_sphere(const Point & p, Full_cell_const_handle s,
+ const OrientationPred & ori) const
+{
+ CGAL_precondition_msg( ! is_infinite(s), "full cell must be finite");
+ CGAL_expensive_precondition( POSITIVE == orientation(s) );
+ typedef std::vector<const Point *> Points;
+ Points points(current_dimension() + 2);
+ int i(0);
+ for( ; i <= current_dimension(); ++i )
+ points[i] = &(s->vertex(i)->point());
+ points[i] = &p;
+ std::sort(points.begin(), points.end(),
+ internal::Triangulation::Compare_points_for_perturbation<Self>(*this));
+ typename Points::const_reverse_iterator cut_pt = points.rbegin();
+ Points test_points;
+ while( cut_pt != points.rend() )
+ {
+ if( &p == *cut_pt )
+ // because the full_cell "s" is assumed to be positively oriented
+ return ON_NEGATIVE_SIDE; // we consider |p| to lie outside the sphere
+ test_points.clear();
+ typename Base::Point_const_iterator spit = points_begin(s);
+ int adjust_sign = -1;
+ for( i = 0; i < current_dimension(); ++i )
+ {
+ if( &(*spit) == *cut_pt )
+ {
+ ++spit;
+ adjust_sign = (((current_dimension() + i) % 2) == 0) ? -1 : +1;
+ }
+ test_points.push_back(&(*spit));
+ ++spit;
+ }
+ test_points.push_back(&p);
+
+ typedef typename CGAL::Iterator_project<typename Points::iterator,
+ internal::Triangulation::Point_from_pointer<Self>,
+ const Point &, const Point *> Point_pointer_iterator;
+
+ Orientation ori_value = ori(
+ Point_pointer_iterator(test_points.begin()),
+ Point_pointer_iterator(test_points.end()));
+
+ if( ZERO != ori_value )
+ return Oriented_side( - adjust_sign * ori_value );
+
+ ++cut_pt;
+ }
+ CGAL_assertion(false); // we should never reach here
+ return ON_NEGATIVE_SIDE;
+}
+
+template< typename DCTraits, typename TDS >
+bool
+Delaunay_triangulation<DCTraits, TDS>
+::is_in_conflict(const Point & p, Full_cell_const_handle s) const
+{
+ CGAL_precondition( 2 <= current_dimension() );
+ if( current_dimension() < maximal_dimension() )
+ {
+ Conflict_pred_in_subspace c(*this, p, coaffine_orientation_predicate(), side_of_oriented_subsphere_predicate());
+ return c(s);
+ }
+ else
+ {
+ Orientation_d ori = geom_traits().orientation_d_object();
+ Side_of_oriented_sphere_d side = geom_traits().side_of_oriented_sphere_d_object();
+ Conflict_pred_in_fullspace c(*this, p, ori, side);
+ return c(s);
+ }
+}
+
+template< typename DCTraits, typename TDS >
+template< typename OutputIterator >
+typename Delaunay_triangulation<DCTraits, TDS>::Facet
+Delaunay_triangulation<DCTraits, TDS>
+::compute_conflict_zone(const Point & p, Full_cell_handle s, OutputIterator out) const
+{
+ CGAL_precondition( 2 <= current_dimension() );
+ if( current_dimension() < maximal_dimension() )
+ {
+ Conflict_pred_in_subspace c(*this, p, coaffine_orientation_predicate(), side_of_oriented_subsphere_predicate());
+ Conflict_traversal_pred_in_subspace tp(*this, c);
+ return tds().gather_full_cells(s, tp, out);
+ }
+ else
+ {
+ Orientation_d ori = geom_traits().orientation_d_object();
+ Side_of_oriented_sphere_d side = geom_traits().side_of_oriented_sphere_d_object();
+ Conflict_pred_in_fullspace c(*this, p, ori, side);
+ Conflict_traversal_pred_in_fullspace tp(*this, c);
+ return tds().gather_full_cells(s, tp, out);
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
+
+template< typename DCTraits, typename TDS >
+bool
+Delaunay_triangulation<DCTraits, TDS>
+::is_valid(bool verbose, int level) const
+{
+ if (!Base::is_valid(verbose, level))
+ return false;
+
+ int dim = current_dimension();
+ if (dim == maximal_dimension())
+ {
+ for (Finite_full_cell_const_iterator cit = this->finite_full_cells_begin() ;
+ cit != this->finite_full_cells_end() ; ++cit )
+ {
+ Full_cell_const_handle ch = cit.base();
+ for(int i = 0; i < dim+1 ; ++i )
+ {
+ // If the i-th neighbor is not an infinite cell
+ Vertex_handle opposite_vh =
+ ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch));
+ if (!is_infinite(opposite_vh))
+ {
+ Side_of_oriented_sphere_d side =
+ geom_traits().side_of_oriented_sphere_d_object();
+ if (side(Point_const_iterator(ch->vertices_begin()),
+ Point_const_iterator(ch->vertices_end()),
+ opposite_vh->point()) == ON_BOUNDED_SIDE)
+ {
+ if (verbose)
+ CGAL_warning_msg(false, "Non-empty sphere");
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+
+} //namespace CGAL
+
+#endif // CGAL_DELAUNAY_COMPLEX_H
diff --git a/include/gudhi_patches/CGAL/Epeck_d.h b/include/gudhi_patches/CGAL/Epeck_d.h
new file mode 100644
index 00000000..52bce84c
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Epeck_d.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_EPECK_D_H
+#define CGAL_EPECK_D_H
+#include <CGAL/NewKernel_d/Cartesian_base.h>
+#include <CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h>
+#include <CGAL/NewKernel_d/Kernel_d_interface.h>
+#include <CGAL/internal/Exact_type_selector.h>
+
+
+namespace CGAL {
+#define CGAL_BASE \
+ Cartesian_base_d<internal::Exact_field_selector<double>::Type, Dim>
+template<class Dim>
+struct Epeck_d_help1
+: CGAL_BASE
+{
+ CGAL_CONSTEXPR Epeck_d_help1(){}
+ CGAL_CONSTEXPR Epeck_d_help1(int d):CGAL_BASE(d){}
+};
+#undef CGAL_BASE
+#define CGAL_BASE \
+ Kernel_d_interface< \
+ Cartesian_wrap< \
+ Epeck_d_help1<Dim>, \
+ Epeck_d<Dim> > >
+template<class Dim>
+struct Epeck_d
+: CGAL_BASE
+{
+ CGAL_CONSTEXPR Epeck_d(){}
+ CGAL_CONSTEXPR Epeck_d(int d):CGAL_BASE(d){}
+};
+#undef CGAL_BASE
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/Epick_d.h b/include/gudhi_patches/CGAL/Epick_d.h
new file mode 100644
index 00000000..64438539
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Epick_d.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_EPICK_D_H
+#define CGAL_EPICK_D_H
+#include <CGAL/NewKernel_d/Cartesian_base.h>
+#include <CGAL/NewKernel_d/Cartesian_static_filters.h>
+#include <CGAL/NewKernel_d/Cartesian_filter_K.h>
+#include <CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h>
+#include <CGAL/NewKernel_d/Kernel_d_interface.h>
+#include <CGAL/internal/Exact_type_selector.h>
+#include <CGAL/Interval_nt.h>
+#include <CGAL/NewKernel_d/Types/Weighted_point.h>
+
+
+namespace CGAL {
+#define CGAL_BASE \
+ Cartesian_filter_K< \
+ Cartesian_base_d<double, Dim>, \
+ Cartesian_base_d<Interval_nt_advanced, Dim>, \
+ Cartesian_base_d<internal::Exact_field_selector<double>::Type, Dim> \
+ >
+template<class Dim>
+struct Epick_d_help1
+: CGAL_BASE
+{
+ CGAL_CONSTEXPR Epick_d_help1(){}
+ CGAL_CONSTEXPR Epick_d_help1(int d):CGAL_BASE(d){}
+};
+#undef CGAL_BASE
+#define CGAL_BASE \
+ Cartesian_static_filters<Dim,Epick_d_help1<Dim>,Epick_d_help2<Dim> >
+template<class Dim>
+struct Epick_d_help2
+: CGAL_BASE
+{
+ CGAL_CONSTEXPR Epick_d_help2(){}
+ CGAL_CONSTEXPR Epick_d_help2(int d):CGAL_BASE(d){}
+};
+#undef CGAL_BASE
+#define CGAL_BASE \
+ Kernel_d_interface< \
+ Cartesian_wrap< \
+ Epick_d_help2<Dim>, \
+ Epick_d<Dim> > >
+template<class Dim>
+struct Epick_d
+: CGAL_BASE
+{
+ CGAL_CONSTEXPR Epick_d(){}
+ CGAL_CONSTEXPR Epick_d(int d):CGAL_BASE(d){}
+};
+#undef CGAL_BASE
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h b/include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h
new file mode 100644
index 00000000..701f0820
--- /dev/null
+++ b/include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h
@@ -0,0 +1,320 @@
+// Copyright (c) 2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL: $
+// $Id: $
+//
+// Author(s) : Clement Jamin
+
+
+#ifndef CGAL_TRIANGULATION_IO_H
+#define CGAL_TRIANGULATION_IO_H
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Triangulation.h>
+#include <sstream>
+#include <iostream>
+
+namespace CGAL {
+
+namespace Triangulation_IO
+{
+// TODO: test if the stream is binary or text?
+template<typename Traits, typename P>
+int
+output_point(std::ostream & os, const Traits &traits, const P & p)
+{
+ typedef typename Traits::Compute_coordinate_d Ccd;
+ const Ccd ccd = traits.compute_coordinate_d_object();
+ const int dim = traits.point_dimension_d_object()(p);
+ if (dim > 0)
+ {
+ os << ccd(p, 0);
+ for (int i = 1 ; i < dim ; ++i)
+ os << " " << CGAL::to_double(ccd(p, i));
+ }
+ return dim;
+}
+
+// TODO: test if the stream is binary or text?
+template<typename Traits, typename P>
+int
+output_weighted_point(std::ostream & os, const Traits &traits, const P & p,
+ bool output_weight = true)
+{
+ typedef typename Traits::Compute_coordinate_d Ccd;
+ typename Traits::Construct_point_d cp =
+ traits.construct_point_d_object();
+ typename Traits::Compute_weight_d pt_weight = traits.compute_weight_d_object();
+ const Ccd ccd = traits.compute_coordinate_d_object();
+ const int dim = traits.point_dimension_d_object()(p);
+ if (dim > 0)
+ {
+ output_point(os, traits, p);
+ if (output_weight)
+ os << " " << pt_weight(p);
+ }
+ return dim;
+}
+
+// TODO: test if the stream is binary or text?
+template<typename Traits, typename FCH>
+void
+output_full_cell(std::ostream & os, const Traits &traits, const FCH & fch,
+ bool output_weights = false)
+{
+ typename FCH::value_type::Vertex_handle_iterator vit = fch->vertices_begin();
+ for( ; vit != fch->vertices_end(); ++vit )
+ {
+ int dim;
+ if (output_weights)
+ dim = output_weighted_point(os, traits, (*vit)->point());
+ else
+ dim = output_point(os, traits, (*vit)->point());
+ if (dim > 0)
+ os << std::endl;
+ }
+}
+
+// TODO: test if the stream is binary or text?
+/*template<typename Traits, typename P>
+void
+input_point(std::istream & is, const Traits &traits, P & p)
+{
+ typedef typename Traits::FT FT;
+ std::vector<FT> coords;
+
+ std::string line;
+ for(;;)
+ {
+ if (!std::getline(is, line))
+ return is;
+ if (line != "")
+ break;
+ }
+ std::stringstream line_sstr(line);
+ FT temp;
+ while (line_sstr >> temp)
+ coords.push_back(temp);
+
+ p = traits.construct_point_d_object()(coords.begin(), coords.end());
+}*/
+
+} // namespace Triangulation_IO
+
+///////////////////////////////////////////////////////////////
+// TODO: replace these operator>> by an "input_point" function
+///////////////////////////////////////////////////////////////
+
+// TODO: test if the stream is binary or text?
+template<typename K>
+std::istream &
+operator>>(std::istream &is, typename Wrap::Point_d<K> & p)
+{
+ typedef typename Wrap::Point_d<K> P;
+ typedef typename K::FT FT;
+ std::vector<FT> coords;
+
+ std::string line;
+ for(;;)
+ {
+ if (!std::getline(is, line))
+ return is;
+ if (line != "")
+ break;
+ }
+ std::stringstream line_sstr(line);
+ FT temp;
+ while (line_sstr >> temp)
+ coords.push_back(temp);
+
+ p = P(coords.begin(), coords.end());
+ return is;
+}
+
+// TODO: test if the stream is binary or text?
+template<typename K>
+std::istream &
+operator>>(std::istream &is, typename Wrap::Weighted_point_d<K> & wp)
+{
+ typedef typename Wrap::Point_d<K> P;
+ typedef typename Wrap::Weighted_point_d<K> WP;
+ typedef typename K::FT FT;
+
+ std::string line;
+ for(;;)
+ {
+ if (!std::getline(is, line))
+ return is;
+ if (line != "")
+ break;
+ }
+ std::stringstream line_sstr(line);
+ FT temp;
+ std::vector<FT> coords;
+ while (line_sstr >> temp)
+ coords.push_back(temp);
+
+ typename std::vector<FT>::iterator last = coords.end() - 1;
+ P p = P(coords.begin(), last);
+ wp = WP(p, *last);
+
+ return is;
+}
+
+// TODO: test if the stream is binary or text?
+template<typename K>
+std::istream &
+operator>>(std::istream &is, typename Wrap::Vector_d<K> & v)
+{
+ typedef typename Wrap::Vector_d<K> V;
+ typedef typename K::FT FT;
+ std::vector<FT> coords;
+
+ std::string line;
+ for (;;)
+ {
+ if (!std::getline(is, line))
+ return is;
+ if (line != "")
+ break;
+ }
+ std::stringstream line_sstr(line);
+ FT temp;
+ while (line_sstr >> temp)
+ coords.push_back(temp);
+
+ v = V(coords.begin(), coords.end());
+ return is;
+}
+
+template < class GT, class TDS >
+std::ostream &
+export_triangulation_to_off(std::ostream & os,
+ const Triangulation<GT,TDS> & tr,
+ bool in_3D_export_surface_only = false)
+{
+ typedef Triangulation<GT,TDS> Tr;
+ typedef typename Tr::Vertex_const_handle Vertex_handle;
+ typedef typename Tr::Finite_vertex_const_iterator Finite_vertex_iterator;
+ typedef typename Tr::Finite_full_cell_const_iterator Finite_full_cell_iterator;
+ typedef typename Tr::Full_cell_const_iterator Full_cell_iterator;
+ typedef typename Tr::Full_cell Full_cell;
+ typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator;
+
+ if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3)
+ {
+ std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3.";
+ os << "Warning: export_tds_to_off => dimension should be 2 or 3.";
+ return os;
+ }
+
+ size_t n = tr.number_of_vertices();
+
+ std::stringstream output;
+
+ // write the vertices
+ std::map<Vertex_handle, int> index_of_vertex;
+ int i = 0;
+ for(Finite_vertex_iterator it = tr.finite_vertices_begin();
+ it != tr.finite_vertices_end(); ++it, ++i)
+ {
+ Triangulation_IO::output_point(output, tr.geom_traits(), it->point());
+ if (tr.maximal_dimension() == 2)
+ output << " 0";
+ output << std::endl;
+ index_of_vertex[it.base()] = i;
+ }
+ CGAL_assertion( i == n );
+
+ size_t number_of_triangles = 0;
+ if (tr.maximal_dimension() == 2)
+ {
+ for (Finite_full_cell_iterator fch = tr.finite_full_cells_begin() ;
+ fch != tr.finite_full_cells_end() ; ++fch)
+ {
+ output << "3 ";
+ for (Full_cell_vertex_iterator vit = fch->vertices_begin() ;
+ vit != fch->vertices_end() ; ++vit)
+ {
+ output << index_of_vertex[*vit] << " ";
+ }
+ output << std::endl;
+ ++number_of_triangles;
+ }
+ }
+ else if (tr.maximal_dimension() == 3)
+ {
+ if (in_3D_export_surface_only)
+ {
+ // Parse boundary facets
+ for (Full_cell_iterator fch = tr.full_cells_begin() ;
+ fch != tr.full_cells_end() ; ++fch)
+ {
+ if (tr.is_infinite(fch))
+ {
+ output << "3 ";
+ for (Full_cell_vertex_iterator vit = fch->vertices_begin() ;
+ vit != fch->vertices_end() ; ++vit)
+ {
+ if (!tr.is_infinite(*vit))
+ output << index_of_vertex[*vit] << " ";
+ }
+ output << std::endl;
+ ++number_of_triangles;
+ }
+ }
+ }
+ else
+ {
+ // Parse finite cells
+ for (Finite_full_cell_iterator fch = tr.finite_full_cells_begin() ;
+ fch != tr.finite_full_cells_end() ; ++fch)
+ {
+ output << "3 "
+ << index_of_vertex[fch->vertex(0)] << " "
+ << index_of_vertex[fch->vertex(1)] << " "
+ << index_of_vertex[fch->vertex(2)]
+ << std::endl;
+ output << "3 "
+ << index_of_vertex[fch->vertex(0)] << " "
+ << index_of_vertex[fch->vertex(2)] << " "
+ << index_of_vertex[fch->vertex(3)]
+ << std::endl;
+ output << "3 "
+ << index_of_vertex[fch->vertex(1)] << " "
+ << index_of_vertex[fch->vertex(2)] << " "
+ << index_of_vertex[fch->vertex(3)]
+ << std::endl;
+ output << "3 "
+ << index_of_vertex[fch->vertex(0)] << " "
+ << index_of_vertex[fch->vertex(1)] << " "
+ << index_of_vertex[fch->vertex(3)]
+ << std::endl;
+ number_of_triangles += 4;
+ }
+ }
+ }
+
+ os << "OFF \n"
+ << n << " "
+ << number_of_triangles << " 0\n"
+ << output.str();
+
+ return os;
+}
+
+} //namespace CGAL
+
+#endif // CGAL_TRIANGULATION_IO_H
diff --git a/include/gudhi_patches/CGAL/Kd_tree.h b/include/gudhi_patches/CGAL/Kd_tree.h
new file mode 100644
index 00000000..f085b0da
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Kd_tree.h
@@ -0,0 +1,582 @@
+// Copyright (c) 2002,2011,2014 Utrecht University (The Netherlands), Max-Planck-Institute Saarbruecken (Germany).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Hans Tangelder (<hanst@cs.uu.nl>),
+// : Waqar Khan <wkhan@mpi-inf.mpg.de>
+
+#ifndef CGAL_KD_TREE_H
+#define CGAL_KD_TREE_H
+
+#include "Kd_tree_node.h"
+
+#include <CGAL/basic.h>
+#include <CGAL/assertions.h>
+#include <vector>
+
+#include <CGAL/algorithm.h>
+#include <CGAL/internal/Get_dimension_tag.h>
+#include <CGAL/Search_traits.h>
+
+
+#include <deque>
+#include <boost/container/deque.hpp>
+#include <boost/optional.hpp>
+
+#ifdef CGAL_HAS_THREADS
+#include <CGAL/mutex.h>
+#endif
+
+namespace CGAL {
+
+//template <class SearchTraits, class Splitter_=Median_of_rectangle<SearchTraits>, class UseExtendedNode = Tag_true >
+template <class SearchTraits, class Splitter_=Sliding_midpoint<SearchTraits>, class UseExtendedNode = Tag_true >
+class Kd_tree {
+
+public:
+ typedef SearchTraits Traits;
+ typedef Splitter_ Splitter;
+ typedef typename SearchTraits::Point_d Point_d;
+ typedef typename Splitter::Container Point_container;
+
+ typedef typename SearchTraits::FT FT;
+ typedef Kd_tree_node<SearchTraits, Splitter, UseExtendedNode > Node;
+ typedef Kd_tree_leaf_node<SearchTraits, Splitter, UseExtendedNode > Leaf_node;
+ typedef Kd_tree_internal_node<SearchTraits, Splitter, UseExtendedNode > Internal_node;
+ typedef Kd_tree<SearchTraits, Splitter> Tree;
+ typedef Kd_tree<SearchTraits, Splitter,UseExtendedNode> Self;
+
+ typedef Node* Node_handle;
+ typedef const Node* Node_const_handle;
+ typedef Leaf_node* Leaf_node_handle;
+ typedef const Leaf_node* Leaf_node_const_handle;
+ typedef Internal_node* Internal_node_handle;
+ typedef const Internal_node* Internal_node_const_handle;
+ typedef typename std::vector<const Point_d*>::const_iterator Point_d_iterator;
+ typedef typename std::vector<const Point_d*>::const_iterator Point_d_const_iterator;
+ typedef typename Splitter::Separator Separator;
+ typedef typename std::vector<Point_d>::const_iterator iterator;
+ typedef typename std::vector<Point_d>::const_iterator const_iterator;
+
+ typedef typename std::vector<Point_d>::size_type size_type;
+
+ typedef typename internal::Get_dimension_tag<SearchTraits>::Dimension D;
+
+private:
+ SearchTraits traits_;
+ Splitter split;
+
+
+ // wokaround for https://svn.boost.org/trac/boost/ticket/9332
+#if (_MSC_VER == 1800) && (BOOST_VERSION == 105500)
+ std::deque<Internal_node> internal_nodes;
+ std::deque<Leaf_node> leaf_nodes;
+#else
+ boost::container::deque<Internal_node> internal_nodes;
+ boost::container::deque<Leaf_node> leaf_nodes;
+#endif
+
+ Node_handle tree_root;
+
+ Kd_tree_rectangle<FT,D>* bbox;
+ std::vector<Point_d> pts;
+
+ // Instead of storing the points in arrays in the Kd_tree_node
+ // we put all the data in a vector in the Kd_tree.
+ // and we only store an iterator range in the Kd_tree_node.
+ //
+ std::vector<const Point_d*> data;
+
+
+ #ifdef CGAL_HAS_THREADS
+ mutable CGAL_MUTEX building_mutex;//mutex used to protect const calls inducing build()
+ #endif
+ bool built_;
+ bool removed_;
+
+ // protected copy constructor
+ Kd_tree(const Tree& tree)
+ : traits_(tree.traits_),built_(tree.built_)
+ {};
+
+
+ // Instead of the recursive construction of the tree in the class Kd_tree_node
+ // we do this in the tree class. The advantage is that we then can optimize
+ // the allocation of the nodes.
+
+ // The leaf node
+ Node_handle
+ create_leaf_node(Point_container& c)
+ {
+ Leaf_node node(true , static_cast<unsigned int>(c.size()));
+ std::ptrdiff_t tmp = c.begin() - data.begin();
+ node.data = pts.begin() + tmp;
+
+ leaf_nodes.push_back(node);
+ Leaf_node_handle nh = &leaf_nodes.back();
+
+
+ return nh;
+ }
+
+
+ // The internal node
+
+ Node_handle
+ create_internal_node(Point_container& c, const Tag_true&)
+ {
+ return create_internal_node_use_extension(c);
+ }
+
+ Node_handle
+ create_internal_node(Point_container& c, const Tag_false&)
+ {
+ return create_internal_node(c);
+ }
+
+
+
+ // TODO: Similiar to the leaf_init function above, a part of the code should be
+ // moved to a the class Kd_tree_node.
+ // It is not proper yet, but the goal was to see if there is
+ // a potential performance gain through the Compact_container
+ Node_handle
+ create_internal_node_use_extension(Point_container& c)
+ {
+ Internal_node node(false);
+ internal_nodes.push_back(node);
+ Internal_node_handle nh = &internal_nodes.back();
+
+ Separator sep;
+ Point_container c_low(c.dimension(),traits_);
+ split(sep, c, c_low);
+ nh->set_separator(sep);
+
+ int cd = nh->cutting_dimension();
+ if(!c_low.empty()){
+ nh->lower_low_val = c_low.tight_bounding_box().min_coord(cd);
+ nh->lower_high_val = c_low.tight_bounding_box().max_coord(cd);
+ }
+ else{
+ nh->lower_low_val = nh->cutting_value();
+ nh->lower_high_val = nh->cutting_value();
+ }
+ if(!c.empty()){
+ nh->upper_low_val = c.tight_bounding_box().min_coord(cd);
+ nh->upper_high_val = c.tight_bounding_box().max_coord(cd);
+ }
+ else{
+ nh->upper_low_val = nh->cutting_value();
+ nh->upper_high_val = nh->cutting_value();
+ }
+
+ CGAL_assertion(nh->cutting_value() >= nh->lower_low_val);
+ CGAL_assertion(nh->cutting_value() <= nh->upper_high_val);
+
+ if (c_low.size() > split.bucket_size()){
+ nh->lower_ch = create_internal_node_use_extension(c_low);
+ }else{
+ nh->lower_ch = create_leaf_node(c_low);
+ }
+ if (c.size() > split.bucket_size()){
+ nh->upper_ch = create_internal_node_use_extension(c);
+ }else{
+ nh->upper_ch = create_leaf_node(c);
+ }
+
+
+
+
+ return nh;
+ }
+
+
+ // Note also that I duplicated the code to get rid if the if's for
+ // the boolean use_extension which was constant over the construction
+ Node_handle
+ create_internal_node(Point_container& c)
+ {
+ Internal_node node(false);
+ internal_nodes.push_back(node);
+ Internal_node_handle nh = &internal_nodes.back();
+ Separator sep;
+
+ Point_container c_low(c.dimension(),traits_);
+ split(sep, c, c_low);
+ nh->set_separator(sep);
+
+ if (c_low.size() > split.bucket_size()){
+ nh->lower_ch = create_internal_node(c_low);
+ }else{
+ nh->lower_ch = create_leaf_node(c_low);
+ }
+ if (c.size() > split.bucket_size()){
+ nh->upper_ch = create_internal_node(c);
+ }else{
+ nh->upper_ch = create_leaf_node(c);
+ }
+
+
+
+ return nh;
+ }
+
+
+
+public:
+
+ Kd_tree(Splitter s = Splitter(),const SearchTraits traits=SearchTraits())
+ : traits_(traits),split(s), built_(false), removed_(false)
+ {}
+
+ template <class InputIterator>
+ Kd_tree(InputIterator first, InputIterator beyond,
+ Splitter s = Splitter(),const SearchTraits traits=SearchTraits())
+ : traits_(traits),split(s), built_(false), removed_(false)
+ {
+ pts.insert(pts.end(), first, beyond);
+ }
+
+ bool empty() const {
+ return pts.empty();
+ }
+
+ void
+ build()
+ {
+ // This function is not ready to be called when a tree already exists, one
+ // must call invalidate_built() first.
+ CGAL_assertion(!is_built());
+ CGAL_assertion(!removed_);
+ const Point_d& p = *pts.begin();
+ typename SearchTraits::Construct_cartesian_const_iterator_d ccci=traits_.construct_cartesian_const_iterator_d_object();
+ int dim = static_cast<int>(std::distance(ccci(p), ccci(p,0)));
+
+ data.reserve(pts.size());
+ for(unsigned int i = 0; i < pts.size(); i++){
+ data.push_back(&pts[i]);
+ }
+ Point_container c(dim, data.begin(), data.end(),traits_);
+ bbox = new Kd_tree_rectangle<FT,D>(c.bounding_box());
+ if (c.size() <= split.bucket_size()){
+ tree_root = create_leaf_node(c);
+ }else {
+ tree_root = create_internal_node(c, UseExtendedNode());
+ }
+
+ //Reorder vector for spatial locality
+ std::vector<Point_d> ptstmp;
+ ptstmp.resize(pts.size());
+ for (std::size_t i = 0; i < pts.size(); ++i){
+ ptstmp[i] = *data[i];
+ }
+ for(std::size_t i = 0; i < leaf_nodes.size(); ++i){
+ std::ptrdiff_t tmp = leaf_nodes[i].begin() - pts.begin();
+ leaf_nodes[i].data = ptstmp.begin() + tmp;
+ }
+ pts.swap(ptstmp);
+
+ data.clear();
+
+ built_ = true;
+ }
+
+private:
+ //any call to this function is for the moment not threadsafe
+ void const_build() const {
+ #ifdef CGAL_HAS_THREADS
+ //this ensure that build() will be called once
+ CGAL_SCOPED_LOCK(building_mutex);
+ if(!is_built())
+ #endif
+ const_cast<Self*>(this)->build(); //THIS IS NOT THREADSAFE
+ }
+public:
+
+ bool is_built() const
+ {
+ return built_;
+ }
+
+ void invalidate_built()
+ {
+ if(removed_){
+ // Walk the tree to collect the remaining points.
+ // Writing directly to pts would likely work, but better be safe.
+ std::vector<Point_d> ptstmp;
+ //ptstmp.resize(root()->num_items());
+ root()->tree_items(std::back_inserter(ptstmp));
+ pts.swap(ptstmp);
+ removed_=false;
+ CGAL_assertion(is_built()); // the rest of the cleanup must happen
+ }
+ if(is_built()){
+ internal_nodes.clear();
+ leaf_nodes.clear();
+ data.clear();
+ delete bbox;
+ built_ = false;
+ }
+ }
+
+ void clear()
+ {
+ invalidate_built();
+ pts.clear();
+ removed_ = false;
+ }
+
+ void
+ insert(const Point_d& p)
+ {
+ invalidate_built();
+ pts.push_back(p);
+ }
+
+ template <class InputIterator>
+ void
+ insert(InputIterator first, InputIterator beyond)
+ {
+ invalidate_built();
+ pts.insert(pts.end(),first, beyond);
+ }
+
+private:
+ struct Equal_by_coordinates {
+ SearchTraits const* traits;
+ Point_d const* pp;
+ bool operator()(Point_d const&q) const {
+ typename SearchTraits::Construct_cartesian_const_iterator_d ccci=traits->construct_cartesian_const_iterator_d_object();
+ return std::equal(ccci(*pp), ccci(*pp,0), ccci(q));
+ }
+ };
+ Equal_by_coordinates equal_by_coordinates(Point_d const&p){
+ Equal_by_coordinates ret = { &traits(), &p };
+ return ret;
+ }
+
+public:
+ void
+ remove(const Point_d& p)
+ {
+ remove(p, equal_by_coordinates(p));
+ }
+
+ template<class Equal>
+ void
+ remove(const Point_d& p, Equal const& equal_to_p)
+ {
+#if 0
+ // This code could have quadratic runtime.
+ if (!is_built()) {
+ std::vector<Point_d>::iterator pi = std::find(pts.begin(), pts.end(), p);
+ // Precondition: the point must be there.
+ CGAL_assertion (pi != pts.end());
+ pts.erase(pi);
+ return;
+ }
+#endif
+ bool success = remove_(p, 0, false, 0, false, root(), equal_to_p);
+ CGAL_assertion(success);
+
+ // Do not set the flag is the tree has been cleared.
+ if(is_built())
+ removed_ |= success;
+ }
+private:
+ template<class Equal>
+ bool remove_(const Point_d& p,
+ Internal_node_handle grandparent, bool parent_islower,
+ Internal_node_handle parent, bool islower,
+ Node_handle node, Equal const& equal_to_p) {
+ // Recurse to locate the point
+ if (!node->is_leaf()) {
+ Internal_node_handle newparent = static_cast<Internal_node_handle>(node);
+ // FIXME: This should be if(x<y) remove low; else remove up;
+ if (traits().construct_cartesian_const_iterator_d_object()(p)[newparent->cutting_dimension()] <= newparent->cutting_value()) {
+ if (remove_(p, parent, islower, newparent, true, newparent->lower(), equal_to_p))
+ return true;
+ }
+ //if (traits().construct_cartesian_const_iterator_d_object()(p)[newparent->cutting_dimension()] >= newparent->cutting_value())
+ return remove_(p, parent, islower, newparent, false, newparent->upper(), equal_to_p);
+
+ CGAL_assertion(false); // Point was not found
+ }
+
+ // Actual removal
+ Leaf_node_handle lnode = static_cast<Leaf_node_handle>(node);
+ if (lnode->size() > 1) {
+ iterator pi = std::find_if(lnode->begin(), lnode->end(), equal_to_p);
+ // FIXME: we should ensure this never happens
+ if (pi == lnode->end()) return false;
+ iterator lasti = lnode->end() - 1;
+ if (pi != lasti) {
+ // Hack to get a non-const iterator
+ std::iter_swap(pts.begin()+(pi-pts.begin()), pts.begin()+(lasti-pts.begin()));
+ }
+ lnode->drop_last_point();
+ } else if (!equal_to_p(*lnode->begin())) {
+ // FIXME: we should ensure this never happens
+ return false;
+ } else if (grandparent) {
+ Node_handle brother = islower ? parent->upper() : parent->lower();
+ if (parent_islower)
+ grandparent->set_lower(brother);
+ else
+ grandparent->set_upper(brother);
+ } else if (parent) {
+ tree_root = islower ? parent->upper() : parent->lower();
+ } else {
+ clear();
+ }
+ return true;
+ }
+
+public:
+ //For efficiency; reserve the size of the points vectors in advance (if the number of points is already known).
+ void reserve(size_t size)
+ {
+ pts.reserve(size);
+ }
+
+ //Get the capacity of the underlying points vector.
+ size_t capacity()
+ {
+ return pts.capacity();
+ }
+
+
+ template <class OutputIterator, class FuzzyQueryItem>
+ OutputIterator
+ search(OutputIterator it, const FuzzyQueryItem& q) const
+ {
+ if(! pts.empty()){
+
+ if(! is_built()){
+ const_build();
+ }
+ Kd_tree_rectangle<FT,D> b(*bbox);
+ return tree_root->search(it,q,b);
+ }
+ return it;
+ }
+
+
+ template <class FuzzyQueryItem>
+ boost::optional<Point_d>
+ search_any_point(const FuzzyQueryItem& q) const
+ {
+ if(! pts.empty()){
+
+ if(! is_built()){
+ const_build();
+ }
+ Kd_tree_rectangle<FT,D> b(*bbox);
+ return tree_root->search_any_point(q,b);
+ }
+ return boost::none;
+ }
+
+
+ ~Kd_tree() {
+ if(is_built()){
+ delete bbox;
+ }
+ }
+
+
+ const SearchTraits&
+ traits() const
+ {
+ return traits_;
+ }
+
+ Node_const_handle
+ root() const
+ {
+ if(! is_built()){
+ const_build();
+ }
+ return tree_root;
+ }
+
+ Node_handle
+ root()
+ {
+ if(! is_built()){
+ build();
+ }
+ return tree_root;
+ }
+
+ void
+ print() const
+ {
+ if(! is_built()){
+ const_build();
+ }
+ root()->print();
+ }
+
+ const Kd_tree_rectangle<FT,D>&
+ bounding_box() const
+ {
+ if(! is_built()){
+ const_build();
+ }
+ return *bbox;
+ }
+
+ const_iterator
+ begin() const
+ {
+ return pts.begin();
+ }
+
+ const_iterator
+ end() const
+ {
+ return pts.end();
+ }
+
+ size_type
+ size() const
+ {
+ return pts.size();
+ }
+
+ // Print statistics of the tree.
+ std::ostream&
+ statistics(std::ostream& s) const
+ {
+ if(! is_built()){
+ const_build();
+ }
+ s << "Tree statistics:" << std::endl;
+ s << "Number of items stored: "
+ << root()->num_items() << std::endl;
+ s << "Number of nodes: "
+ << root()->num_nodes() << std::endl;
+ s << " Tree depth: " << root()->depth() << std::endl;
+ return s;
+ }
+
+
+};
+
+} // namespace CGAL
+
+#endif // CGAL_KD_TREE_H
diff --git a/include/gudhi_patches/CGAL/Kd_tree_node.h b/include/gudhi_patches/CGAL/Kd_tree_node.h
new file mode 100644
index 00000000..909ee260
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Kd_tree_node.h
@@ -0,0 +1,586 @@
+// Copyright (c) 2002,2011 Utrecht University (The Netherlands).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+//
+// Authors : Hans Tangelder (<hanst@cs.uu.nl>)
+
+#ifndef CGAL_KD_TREE_NODE_H
+#define CGAL_KD_TREE_NODE_H
+
+#include "CGAL/Splitters.h"
+
+#include <CGAL/Compact_container.h>
+#include <boost/cstdint.hpp>
+
+namespace CGAL {
+
+ template <class SearchTraits, class Splitter, class UseExtendedNode>
+ class Kd_tree;
+
+ template < class TreeTraits, class Splitter, class UseExtendedNode >
+ class Kd_tree_node {
+
+ friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode>;
+
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_handle Node_handle;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_const_handle Node_const_handle;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Internal_node_handle Internal_node_handle;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Internal_node_const_handle Internal_node_const_handle;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Leaf_node_handle Leaf_node_handle;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Leaf_node_const_handle Leaf_node_const_handle;
+ typedef typename TreeTraits::Point_d Point_d;
+
+ typedef typename TreeTraits::FT FT;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Separator Separator;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Point_d_iterator Point_d_iterator;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::iterator iterator;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::D D;
+
+ bool leaf;
+
+ public :
+ Kd_tree_node(bool leaf_)
+ :leaf(leaf_){}
+
+ bool is_leaf() const{
+ return leaf;
+ }
+
+ std::size_t
+ num_items() const
+ {
+ if (is_leaf()){
+ Leaf_node_const_handle node =
+ static_cast<Leaf_node_const_handle>(this);
+ return node->size();
+ }
+ else {
+ Internal_node_const_handle node =
+ static_cast<Internal_node_const_handle>(this);
+ return node->lower()->num_items() + node->upper()->num_items();
+ }
+ }
+
+ std::size_t
+ num_nodes() const
+ {
+ if (is_leaf()) return 1;
+ else {
+ Internal_node_const_handle node =
+ static_cast<Internal_node_const_handle>(this);
+ return node->lower()->num_nodes() + node->upper()->num_nodes();
+ }
+ }
+
+ int
+ depth(const int current_max_depth) const
+ {
+ if (is_leaf()){
+ return current_max_depth;
+ }
+ else {
+ Internal_node_const_handle node =
+ static_cast<Internal_node_const_handle>(this);
+ return
+ (std::max)( node->lower()->depth(current_max_depth + 1),
+ node->upper()->depth(current_max_depth + 1));
+ }
+ }
+
+ int
+ depth() const
+ {
+ return depth(1);
+ }
+
+ template <class OutputIterator>
+ OutputIterator
+ tree_items(OutputIterator it) const {
+ if (is_leaf()) {
+ Leaf_node_const_handle node =
+ static_cast<Leaf_node_const_handle>(this);
+ if (node->size()>0)
+ for (iterator i=node->begin(); i != node->end(); i++)
+ {*it=*i; ++it;}
+ }
+ else {
+ Internal_node_const_handle node =
+ static_cast<Internal_node_const_handle>(this);
+ it=node->lower()->tree_items(it);
+ it=node->upper()->tree_items(it);
+ }
+ return it;
+ }
+
+
+ boost::optional<Point_d>
+ any_tree_item() const {
+ boost::optional<Point_d> result = boost::none;
+ if (is_leaf()) {
+ Leaf_node_const_handle node =
+ static_cast<Leaf_node_const_handle>(this);
+ if (node->size()>0){
+ return boost::make_optional(*(node->begin()));
+ }
+ }
+ else {
+ Internal_node_const_handle node =
+ static_cast<Internal_node_const_handle>(this);
+ result = node->lower()->any_tree_item();
+ if(! result){
+ result = node->upper()->any_tree_item();
+ }
+ }
+ return result;
+ }
+
+
+ void
+ indent(int d) const
+ {
+ for(int i = 0; i < d; i++){
+ std::cout << " ";
+ }
+ }
+
+
+ void
+ print(int d = 0) const
+ {
+ if (is_leaf()) {
+ Leaf_node_const_handle node =
+ static_cast<Leaf_node_const_handle>(this);
+ indent(d);
+ std::cout << "leaf" << std::endl;
+ if (node->size()>0)
+ for (iterator i=node->begin(); i != node->end(); i++)
+ {indent(d);std::cout << *i << std::endl;}
+ }
+ else {
+ Internal_node_const_handle node =
+ static_cast<Internal_node_const_handle>(this);
+ indent(d);
+ std::cout << "lower tree" << std::endl;
+ node->lower()->print(d+1);
+ indent(d);
+ std::cout << "separator: dim = " << node->cutting_dimension() << " val = " << node->cutting_value() << std::endl;
+ indent(d);
+ std::cout << "upper tree" << std::endl;
+ node->upper()->print(d+1);
+ }
+ }
+
+
+ template <class OutputIterator, class FuzzyQueryItem>
+ OutputIterator
+ search(OutputIterator it, const FuzzyQueryItem& q,
+ Kd_tree_rectangle<FT,D>& b) const
+ {
+ if (is_leaf()) {
+ Leaf_node_const_handle node =
+ static_cast<Leaf_node_const_handle>(this);
+ if (node->size()>0)
+ for (iterator i=node->begin(); i != node->end(); i++)
+ if (q.contains(*i))
+ {*it++=*i;}
+ }
+ else {
+ Internal_node_const_handle node =
+ static_cast<Internal_node_const_handle>(this);
+ // after splitting b denotes the lower part of b
+ Kd_tree_rectangle<FT,D> b_upper(b);
+ b.split(b_upper, node->cutting_dimension(),
+ node->cutting_value());
+
+ if (q.outer_range_contains(b))
+ it=node->lower()->tree_items(it);
+ else
+ if (q.inner_range_intersects(b))
+ it=node->lower()->search(it,q,b);
+ if (q.outer_range_contains(b_upper))
+ it=node->upper()->tree_items(it);
+ else
+ if (q.inner_range_intersects(b_upper))
+ it=node->upper()->search(it,q,b_upper);
+ };
+ return it;
+ }
+
+
+ template <class FuzzyQueryItem>
+ boost::optional<Point_d>
+ search_any_point(const FuzzyQueryItem& q,
+ Kd_tree_rectangle<FT,D>& b) const
+ {
+ boost::optional<Point_d> result = boost::none;
+ if (is_leaf()) {
+ Leaf_node_const_handle node =
+ static_cast<Leaf_node_const_handle>(this);
+ if (node->size()>0)
+ for (iterator i=node->begin(); i != node->end(); i++)
+ if (q.contains(*i))
+ { result = *i; break; }
+ }
+ else {
+ Internal_node_const_handle node =
+ static_cast<Internal_node_const_handle>(this);
+ // after splitting b denotes the lower part of b
+ Kd_tree_rectangle<FT,D> b_upper(b);
+ b.split(b_upper, node->cutting_dimension(),
+ node->cutting_value());
+
+ if (q.outer_range_contains(b)){
+ result = node->lower()->any_tree_item();
+ }else{
+ if (q.inner_range_intersects(b)){
+ result = node->lower()->search_any_point(q,b);
+ }
+ }
+ if(result){
+ return result;
+ }
+ if (q.outer_range_contains(b_upper)){
+ result = node->upper()->any_tree_item();
+ }else{
+ if (q.inner_range_intersects(b_upper))
+ result = node->upper()->search_any_point(q,b_upper);
+ }
+ }
+ return result;
+ }
+
+ };
+
+
+ template < class TreeTraits, class Splitter, class UseExtendedNode >
+ class Kd_tree_leaf_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode >{
+
+ friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode>;
+
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::iterator iterator;
+ typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode> Base;
+ typedef typename TreeTraits::Point_d Point_d;
+
+ private:
+
+ // private variables for leaf nodes
+ boost::int32_t n; // denotes number of items in a leaf node
+ iterator data; // iterator to data in leaf node
+
+
+ public:
+
+ // default constructor
+ Kd_tree_leaf_node()
+ {}
+
+ Kd_tree_leaf_node(bool leaf_ )
+ : Base(leaf_)
+ {}
+
+ Kd_tree_leaf_node(bool leaf_,unsigned int n_ )
+ : Base(leaf_), n(n_)
+ {}
+
+ // members for all nodes
+
+ // members for leaf nodes only
+ inline
+ unsigned int
+ size() const
+ {
+ return n;
+ }
+
+ inline
+ iterator
+ begin() const
+ {
+ return data;
+ }
+
+ inline
+ iterator
+ end() const
+ {
+ return data + n;
+ }
+
+ inline
+ void
+ drop_last_point()
+ {
+ --n;
+ }
+
+ }; //leaf node
+
+
+
+ template < class TreeTraits, class Splitter, class UseExtendedNode>
+ class Kd_tree_internal_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode >{
+
+ friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode>;
+
+ typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode> Base;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_handle Node_handle;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_const_handle Node_const_handle;
+
+ typedef typename TreeTraits::FT FT;
+ typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Separator Separator;
+
+ private:
+
+ // private variables for internal nodes
+ boost::int32_t cut_dim;
+ FT cut_val;
+ Node_handle lower_ch, upper_ch;
+
+
+ // private variables for extended internal nodes
+ FT upper_low_val;
+ FT upper_high_val;
+ FT lower_low_val;
+ FT lower_high_val;
+
+
+ public:
+
+ // default constructor
+ Kd_tree_internal_node()
+ {}
+
+ Kd_tree_internal_node(bool leaf_)
+ : Base(leaf_)
+ {}
+
+
+ // members for internal node and extended internal node
+
+ inline
+ Node_const_handle
+ lower() const
+ {
+ return lower_ch;
+ }
+
+ inline
+ Node_const_handle
+ upper() const
+ {
+ return upper_ch;
+ }
+
+ inline
+ Node_handle
+ lower()
+ {
+ return lower_ch;
+ }
+
+ inline
+ Node_handle
+ upper()
+ {
+ return upper_ch;
+ }
+
+ inline
+ void
+ set_lower(Node_handle nh)
+ {
+ lower_ch = nh;
+ }
+
+ inline
+ void
+ set_upper(Node_handle nh)
+ {
+ upper_ch = nh;
+ }
+
+ // inline Separator& separator() {return sep; }
+ // use instead
+ inline
+ void set_separator(Separator& sep){
+ cut_dim = sep.cutting_dimension();
+ cut_val = sep.cutting_value();
+ }
+
+ inline
+ FT
+ cutting_value() const
+ {
+ return cut_val;
+ }
+
+ inline
+ int
+ cutting_dimension() const
+ {
+ return cut_dim;
+ }
+
+ // members for extended internal node only
+ inline
+ FT
+ upper_low_value() const
+ {
+ return upper_low_val;
+ }
+
+ inline
+ FT
+ upper_high_value() const
+ {
+ return upper_high_val;
+ }
+
+ inline
+ FT
+ lower_low_value() const
+ {
+ return lower_low_val;
+ }
+
+ inline
+ FT
+ lower_high_value() const
+ {
+ return lower_high_val;
+ }
+
+ /*Separator&
+ separator()
+ {
+ return Separator(cutting_dimension,cutting_value);
+ }*/
+
+
+ };//internal node
+
+ template < class TreeTraits, class Splitter>
+ class Kd_tree_internal_node<TreeTraits,Splitter,Tag_false> : public Kd_tree_node< TreeTraits, Splitter, Tag_false >{
+
+ friend class Kd_tree<TreeTraits,Splitter,Tag_false>;
+
+ typedef Kd_tree_node< TreeTraits, Splitter, Tag_false> Base;
+ typedef typename Kd_tree<TreeTraits,Splitter,Tag_false>::Node_handle Node_handle;
+ typedef typename Kd_tree<TreeTraits,Splitter,Tag_false>::Node_const_handle Node_const_handle;
+
+ typedef typename TreeTraits::FT FT;
+ typedef typename Kd_tree<TreeTraits,Splitter,Tag_false>::Separator Separator;
+
+ private:
+
+ // private variables for internal nodes
+ boost::uint8_t cut_dim;
+ FT cut_val;
+
+ Node_handle lower_ch, upper_ch;
+
+ public:
+
+ // default constructor
+ Kd_tree_internal_node()
+ {}
+
+ Kd_tree_internal_node(bool leaf_)
+ : Base(leaf_)
+ {}
+
+
+ // members for internal node and extended internal node
+
+ inline
+ Node_const_handle
+ lower() const
+ {
+ return lower_ch;
+ }
+
+ inline
+ Node_const_handle
+ upper() const
+ {
+ return upper_ch;
+ }
+
+ inline
+ Node_handle
+ lower()
+ {
+ return lower_ch;
+ }
+
+ inline
+ Node_handle
+ upper()
+ {
+ return upper_ch;
+ }
+
+ inline
+ void
+ set_lower(Node_handle nh)
+ {
+ lower_ch = nh;
+ }
+
+ inline
+ void
+ set_upper(Node_handle nh)
+ {
+ upper_ch = nh;
+ }
+
+ // inline Separator& separator() {return sep; }
+ // use instead
+
+ inline
+ void set_separator(Separator& sep){
+ cut_dim = sep.cutting_dimension();
+ cut_val = sep.cutting_value();
+ }
+
+ inline
+ FT
+ cutting_value() const
+ {
+ return cut_val;
+ }
+
+ inline
+ int
+ cutting_dimension() const
+ {
+ return cut_dim;
+ }
+
+ /* Separator&
+ separator()
+ {
+ return Separator(cutting_dimension,cutting_value);
+ }*/
+
+
+ };//internal node
+
+
+
+} // namespace CGAL
+#endif // CGAL_KDTREE_NODE_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h
new file mode 100644
index 00000000..c13a9801
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h
@@ -0,0 +1,177 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_CARTESIAN_LA_BASE_H
+#define CGAL_KERNEL_D_CARTESIAN_LA_BASE_H
+
+#include <CGAL/basic.h>
+#include <CGAL/Origin.h>
+#include <boost/type_traits/integral_constant.hpp>
+#include <CGAL/representation_tags.h>
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Uncertain.h>
+#include <CGAL/typeset.h>
+#include <CGAL/NewKernel_d/Dimension_base.h>
+#include <CGAL/NewKernel_d/Cartesian_LA_functors.h>
+#include <CGAL/NewKernel_d/Vector/array.h>
+#include <CGAL/NewKernel_d/Vector/vector.h>
+#include <CGAL/NewKernel_d/Vector/mix.h>
+#ifdef CGAL_EIGEN3_ENABLED
+#include <CGAL/NewKernel_d/LA_eigen/LA.h>
+#else
+#error Eigen3 is required
+#endif
+
+namespace CGAL {
+
+template < typename FT_, typename Dim_,
+#if 1
+ typename Vec_=Mix_vector<Array_vector<FT_, Dim_>,
+ Vector_vector<FT_, Dim_>,
+ FT_, Dim_>,
+#elif 0
+ typename Vec_=Array_vector<FT_, Dim_>,
+#elif 0
+ typename Vec_=Vector_vector<FT_, Dim_>,
+#else
+ // Dangerous because of alignment. Ok on x86_64 without AVX.
+ typename Vec_=LA_eigen<FT_, Dim_>,
+#endif
+ typename LA_=LA_eigen<FT_,Dim_> >
+ /* Default LA to Vec or to LA_eigen? */
+struct Cartesian_LA_base_d : public Dimension_base<Dim_>
+{
+ typedef Cartesian_LA_base_d<FT_,Dim_> Self;
+ typedef Cartesian_tag Rep_tag;
+ typedef Cartesian_tag Kernel_tag;
+ typedef Dim_ Default_ambient_dimension;
+ typedef Dim_ Max_ambient_dimension;
+ typedef Dim_ Dimension;
+ typedef LA_ LA;
+ template <class> struct Ambient_dimension { typedef Dim_ type; };
+
+ typedef Vec_ LA_vector;
+ typedef typename LA_vector::Vector Point;
+ typedef typename LA_vector::Vector Vector;
+ typedef typename LA_vector::Vector Vector_;
+ typedef typename LA_vector::Construct_vector Constructor;
+ typedef typename LA_vector::Vector_const_iterator Point_cartesian_const_iterator;
+ typedef typename LA_vector::Vector_const_iterator Vector_cartesian_const_iterator;
+
+ template<class, class=void> struct Type {};
+ template<class D> struct Type< Point_tag, D> { typedef Vector_ type; };
+ template<class D> struct Type<Vector_tag, D> { typedef Vector_ type; };
+ template<class D> struct Type< FT_tag, D> { typedef FT_ type; };
+ template<class D> struct Type< RT_tag, D> { typedef FT_ type; };
+
+ typedef typeset<Point_tag>
+ ::add<Vector_tag>::type
+ // FIXME: These have nothing to do here.
+ ::add<Segment_tag>::type
+ ::add<Hyperplane_tag>::type
+ ::add<Sphere_tag>::type
+ ::add<Weighted_point_tag>::type
+ Object_list;
+
+ typedef typeset< Point_cartesian_const_iterator_tag>::type
+ ::add<Vector_cartesian_const_iterator_tag>::type
+ Iterator_list;
+
+ template<class, class=void, class=boost::integral_constant<int,0> > struct Functor {
+ typedef Null_functor type;
+ };
+ template<class D> struct Functor<Construct_ttag<Vector_tag>,D> {
+ typedef CartesianDVectorBase::Construct_LA_vector<Self,Null_vector> type;
+ };
+ template<class D> struct Functor<Construct_ttag<Point_tag>,D> {
+ typedef CartesianDVectorBase::Construct_LA_vector<Self,Origin> type;
+ };
+ template<class D> struct Functor<Construct_ttag<Point_cartesian_const_iterator_tag>,D> {
+ typedef CartesianDVectorBase::Construct_cartesian_const_iterator<Self> type;
+ };
+ template<class D> struct Functor<Construct_ttag<Vector_cartesian_const_iterator_tag>,D> {
+ typedef CartesianDVectorBase::Construct_cartesian_const_iterator<Self> type;
+ };
+ template<class D> struct Functor<Sum_of_vectors_tag,D,
+ boost::integral_constant<int,!LA_vector::template Property<Has_vector_plus_minus_tag>::value> > {
+ typedef CartesianDVectorBase::Sum_of_vectors<Self> type;
+ };
+ template<class D> struct Functor<Difference_of_vectors_tag,D,
+ boost::integral_constant<int,!LA_vector::template Property<Has_vector_plus_minus_tag>::value> > {
+ typedef CartesianDVectorBase::Difference_of_vectors<Self> type;
+ };
+ template<class D> struct Functor<Opposite_vector_tag,D,
+ boost::integral_constant<int,!LA_vector::template Property<Has_vector_plus_minus_tag>::value> > {
+ typedef CartesianDVectorBase::Opposite_vector<Self> type;
+ };
+ template<class D> struct Functor<Midpoint_tag,D,
+ boost::integral_constant<int,
+ !LA_vector::template Property<Has_vector_plus_minus_tag>::value
+ || !LA_vector::template Property<Has_vector_scalar_ops_tag>::value> > {
+ typedef CartesianDVectorBase::Midpoint<Self> type;
+ };
+ template<class D> struct Functor<Compute_point_cartesian_coordinate_tag,D> {
+ typedef CartesianDVectorBase::Compute_cartesian_coordinate<Self> type;
+ };
+ template<class D> struct Functor<Compute_vector_cartesian_coordinate_tag,D> {
+ typedef CartesianDVectorBase::Compute_cartesian_coordinate<Self> type;
+ };
+ template<class D> struct Functor<Point_dimension_tag,D> {
+ typedef CartesianDVectorBase::PV_dimension<Self> type;
+ };
+ template<class D> struct Functor<Vector_dimension_tag,D> {
+ typedef CartesianDVectorBase::PV_dimension<Self> type;
+ };
+ template<class D> struct Functor<Orientation_of_vectors_tag,D,
+ boost::integral_constant<int,!LA_vector::template Property<Has_determinant_of_iterator_to_vectors_tag>::value> > {
+ typedef CartesianDVectorBase::Orientation_of_vectors<Self> type;
+ };
+ template<class D> struct Functor<Orientation_of_points_tag,D,
+ boost::integral_constant<int,!LA_vector::template Property<Has_determinant_of_iterator_to_points_tag>::value> > {
+ typedef CartesianDVectorBase::Orientation_of_points<Self> type;
+ };
+ template<class D> struct Functor<Scalar_product_tag,D,
+ boost::integral_constant<int,!LA_vector::template Property<Has_dot_product_tag>::value> > {
+ typedef CartesianDVectorBase::Scalar_product<Self> type;
+ };
+ template<class D> struct Functor<Squared_distance_to_origin_tag,D,
+ boost::integral_constant<int,!LA_vector::template Property<Stores_squared_norm_tag>::value> > {
+ typedef CartesianDVectorBase::Squared_distance_to_origin_stored<Self> type;
+ };
+ // Use integral_constant<int,2> in case of failure, to distinguish from the previous one.
+ template<class D> struct Functor<Squared_distance_to_origin_tag,D,
+ boost::integral_constant<int,
+ (LA_vector::template Property<Stores_squared_norm_tag>::value
+ || !LA_vector::template Property<Has_dot_product_tag>::value)*2> > {
+ typedef CartesianDVectorBase::Squared_distance_to_origin_via_dotprod<Self> type;
+ };
+ template<class D> struct Functor<Point_to_vector_tag,D> {
+ typedef CartesianDVectorBase::Identity_functor<Self> type;
+ };
+ template<class D> struct Functor<Vector_to_point_tag,D> {
+ typedef CartesianDVectorBase::Identity_functor<Self> type;
+ };
+
+ CGAL_CONSTEXPR Cartesian_LA_base_d(){}
+ CGAL_CONSTEXPR Cartesian_LA_base_d(int d):Dimension_base<Dim_>(d){}
+};
+
+} //namespace CGAL
+
+#endif // CGAL_KERNEL_D_CARTESIAN_LA_BASE_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h
new file mode 100644
index 00000000..871c463a
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h
@@ -0,0 +1,344 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_CARTESIAN_LA_FUNCTORS_H
+#define CGAL_CARTESIAN_LA_FUNCTORS_H
+
+#include <CGAL/NewKernel_d/utils.h>
+#include <CGAL/is_iterator.h>
+#include <CGAL/argument_swaps.h>
+#include <CGAL/Kernel/Return_base_tag.h>
+#include <CGAL/transforming_iterator.h>
+#include <CGAL/NewKernel_d/store_kernel.h>
+#include <CGAL/Dimension.h>
+
+namespace CGAL {
+namespace CartesianDVectorBase {
+#ifndef CGAL_CXX11
+namespace internal {
+template<class R_,class Dim_> struct Construct_LA_vector_ {
+ struct Never_use {};
+ void operator()(Never_use)const;
+};
+#define CGAL_CODE(Z,N,_) template<class R> struct Construct_LA_vector_<R,Dimension_tag<N> > { \
+ typedef typename R::Constructor Constructor; \
+ typedef typename Get_type<R, RT_tag>::type RT; \
+ typedef typename R::Vector_ result_type; \
+ result_type operator() \
+ (BOOST_PP_ENUM_PARAMS(N,RT const& t)) const { \
+ return typename Constructor::Values()(BOOST_PP_ENUM_PARAMS(N,t)); \
+ } \
+ result_type operator() \
+ (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(N),RT const& t)) const { \
+ return typename Constructor::Values_divide()(t##N,BOOST_PP_ENUM_PARAMS(N,t)); \
+ } \
+ };
+BOOST_PP_REPEAT_FROM_TO(2, 11, CGAL_CODE, _ )
+#undef CGAL_CODE
+}
+#endif
+
+template<class R_,class Zero_> struct Construct_LA_vector
+: private Store_kernel<R_>
+#ifndef CGAL_CXX11
+, public internal::Construct_LA_vector_<R_,typename R_::Default_ambient_dimension>
+#endif
+{
+ //CGAL_FUNCTOR_INIT_IGNORE(Construct_LA_vector)
+ CGAL_FUNCTOR_INIT_STORE(Construct_LA_vector)
+ typedef R_ R;
+ typedef typename R::Constructor Constructor;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename R::Vector_ result_type;
+ typedef typename R_::Default_ambient_dimension Dimension;
+ result_type operator()(int d)const{
+ CGAL_assertion(check_dimension_eq(d,this->kernel().dimension()));
+ return typename Constructor::Dimension()(d);
+ }
+ result_type operator()()const{
+ return typename Constructor::Dimension()((std::max)(0,this->kernel().dimension()));
+ }
+ result_type operator()(int d, Zero_ const&)const{
+ CGAL_assertion(check_dimension_eq(d,this->kernel().dimension()));
+ return typename Constructor::Dimension()(d);
+ }
+ result_type operator()(Zero_ const&)const{
+ // Makes no sense for an unknown dimension.
+ return typename Constructor::Dimension()(this->kernel().dimension());
+ }
+ result_type operator()(result_type const& v)const{
+ return v;
+ }
+#ifdef CGAL_CXX11
+ result_type operator()(result_type&& v)const{
+ return std::move(v);
+ }
+#endif
+#ifdef CGAL_CXX11
+ template<class...U>
+ typename std::enable_if<Constructible_from_each<RT,U...>::value &&
+ boost::is_same<Dimension_tag<sizeof...(U)>, Dimension>::value,
+ result_type>::type
+ operator()(U&&...u)const{
+ return typename Constructor::Values()(std::forward<U>(u)...);
+ }
+ //template<class...U,class=typename std::enable_if<Constructible_from_each<RT,U...>::value>::type,class=typename std::enable_if<(sizeof...(U)==static_dim+1)>::type,class=void>
+ template<class...U>
+ typename std::enable_if<Constructible_from_each<RT,U...>::value &&
+ boost::is_same<Dimension_tag<sizeof...(U)-1>, Dimension>::value,
+ result_type>::type
+ operator()(U&&...u)const{
+ return Apply_to_last_then_rest()(typename Constructor::Values_divide(),std::forward<U>(u)...);
+ }
+#else
+ using internal::Construct_LA_vector_<R_,typename R::Default_ambient_dimension>::operator();
+#endif
+ template<class Iter> inline
+ typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator()
+ (Iter f,Iter g,Cartesian_tag t)const
+ {
+ return this->operator()((int)std::distance(f,g),f,g,t);
+ }
+ template<class Iter> inline
+ typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator()
+ (int d,Iter f,Iter g,Cartesian_tag)const
+ {
+ CGAL_assertion(d==std::distance(f,g));
+ CGAL_assertion(check_dimension_eq(d,this->kernel().dimension()));
+ return typename Constructor::Iterator()(d,f,g);
+ }
+ template<class Iter> inline
+ typename boost::enable_if<is_iterator_type<Iter,std::bidirectional_iterator_tag>,result_type>::type operator()
+ (Iter f,Iter g,Homogeneous_tag)const
+ {
+ --g;
+ return this->operator()((int)std::distance(f,g),f,g,*g);
+ }
+ template<class Iter> inline
+ typename boost::enable_if<is_iterator_type<Iter,std::bidirectional_iterator_tag>,result_type>::type operator()
+ (int d,Iter f,Iter g,Homogeneous_tag)const
+ {
+ --g;
+ return this->operator()(d,f,g,*g);
+ }
+ template<class Iter> inline
+ typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator()
+ (Iter f,Iter g)const
+ {
+ // Shouldn't it try comparing dist(f,g) to the dimension if it is known?
+ return this->operator()(f,g,typename R::Rep_tag());
+ }
+ template<class Iter> inline
+ typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator()
+ (int d,Iter f,Iter g)const
+ {
+ return this->operator()(d,f,g,typename R::Rep_tag());
+ }
+
+ // Last homogeneous coordinate given separately
+ template<class Iter,class NT> inline
+ typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator()
+ (int d,Iter f,Iter g,NT const&l)const
+ {
+ CGAL_assertion(d==std::distance(f,g));
+ CGAL_assertion(check_dimension_eq(d,this->kernel().dimension()));
+ // RT? better be safe for now
+ return typename Constructor::Iterator()(d,CGAL::make_transforming_iterator(f,Divide<FT,NT>(l)),CGAL::make_transforming_iterator(g,Divide<FT,NT>(l)));
+ }
+ template<class Iter,class NT> inline
+ typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator()
+ (Iter f,Iter g,NT const&l)const
+ {
+ return this->operator()((int)std::distance(f,g),f,g,l);
+ }
+};
+
+template<class R_> struct Compute_cartesian_coordinate {
+ CGAL_FUNCTOR_INIT_IGNORE(Compute_cartesian_coordinate)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename R::Vector_ first_argument_type;
+ typedef int second_argument_type;
+ typedef Tag_true Is_exact;
+#ifdef CGAL_CXX11
+ typedef decltype(std::declval<const first_argument_type>()[0]) result_type;
+#else
+ typedef RT const& result_type;
+ // RT const& doesn't work with some LA (Eigen2 for instance) so we
+ // should use plain RT or find a way to detect this.
+#endif
+
+ result_type operator()(first_argument_type const& v,int i)const{
+ return v[i];
+ }
+};
+
+template<class R_> struct Construct_cartesian_const_iterator {
+ CGAL_FUNCTOR_INIT_IGNORE(Construct_cartesian_const_iterator)
+ typedef R_ R;
+ typedef typename R::Vector_ argument_type;
+ typedef typename R::LA_vector S_;
+ typedef typename R::Point_cartesian_const_iterator result_type;
+ // same as Vector
+ typedef Tag_true Is_exact;
+
+ result_type operator()(argument_type const& v,Begin_tag)const{
+ return S_::vector_begin(v);
+ }
+ result_type operator()(argument_type const& v,End_tag)const{
+ return S_::vector_end(v);
+ }
+};
+
+template<class R_> struct Midpoint {
+ CGAL_FUNCTOR_INIT_IGNORE(Midpoint)
+ typedef R_ R;
+ typedef typename Get_type<R, Point_tag>::type first_argument_type;
+ typedef typename Get_type<R, Point_tag>::type second_argument_type;
+ typedef typename Get_type<R, Point_tag>::type result_type;
+
+ result_type operator()(result_type const& a, result_type const& b)const{
+ return (a+b)/2;
+ }
+};
+
+template<class R_> struct Sum_of_vectors {
+ CGAL_FUNCTOR_INIT_IGNORE(Sum_of_vectors)
+ typedef R_ R;
+ typedef typename Get_type<R, Vector_tag>::type first_argument_type;
+ typedef typename Get_type<R, Vector_tag>::type second_argument_type;
+ typedef typename Get_type<R, Vector_tag>::type result_type;
+
+ result_type operator()(result_type const& a, result_type const& b)const{
+ return a+b;
+ }
+};
+
+template<class R_> struct Difference_of_vectors {
+ CGAL_FUNCTOR_INIT_IGNORE(Difference_of_vectors)
+ typedef R_ R;
+ typedef typename Get_type<R, Vector_tag>::type first_argument_type;
+ typedef typename Get_type<R, Vector_tag>::type second_argument_type;
+ typedef typename Get_type<R, Vector_tag>::type result_type;
+
+ result_type operator()(result_type const& a, result_type const& b)const{
+ return a-b;
+ }
+};
+
+template<class R_> struct Opposite_vector {
+ CGAL_FUNCTOR_INIT_IGNORE(Opposite_vector)
+ typedef R_ R;
+ typedef typename Get_type<R, Vector_tag>::type result_type;
+ typedef typename Get_type<R, Vector_tag>::type argument_type;
+
+ result_type operator()(result_type const& v)const{
+ return -v;
+ }
+};
+
+template<class R_> struct Scalar_product {
+ CGAL_FUNCTOR_INIT_IGNORE(Scalar_product)
+ typedef R_ R;
+ typedef typename R::LA_vector LA;
+ typedef typename Get_type<R, RT_tag>::type result_type;
+ typedef typename Get_type<R, Vector_tag>::type first_argument_type;
+ typedef typename Get_type<R, Vector_tag>::type second_argument_type;
+
+ result_type operator()(first_argument_type const& a, second_argument_type const& b)const{
+ return LA::dot_product(a,b);
+ }
+};
+
+template<class R_> struct Squared_distance_to_origin_stored {
+ CGAL_FUNCTOR_INIT_IGNORE(Squared_distance_to_origin_stored)
+ typedef R_ R;
+ typedef typename R::LA_vector LA;
+ typedef typename Get_type<R, RT_tag>::type result_type;
+ typedef typename Get_type<R, Point_tag>::type argument_type;
+
+ result_type operator()(argument_type const& a)const{
+ return LA::squared_norm(a);
+ }
+};
+
+template<class R_> struct Squared_distance_to_origin_via_dotprod {
+ CGAL_FUNCTOR_INIT_IGNORE(Squared_distance_to_origin_via_dotprod)
+ typedef R_ R;
+ typedef typename R::LA_vector LA;
+ typedef typename Get_type<R, RT_tag>::type result_type;
+ typedef typename Get_type<R, Point_tag>::type argument_type;
+
+ result_type operator()(argument_type const& a)const{
+ return LA::dot_product(a,a);
+ }
+};
+
+template<class R_> struct Orientation_of_vectors {
+ CGAL_FUNCTOR_INIT_IGNORE(Orientation_of_vectors)
+ typedef R_ R;
+ typedef typename R::Vector_cartesian_const_iterator first_argument_type;
+ typedef typename R::Vector_cartesian_const_iterator second_argument_type;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ typedef typename R::LA_vector LA;
+
+ template<class Iter>
+ result_type operator()(Iter const& f, Iter const& e) const {
+ return LA::determinant_of_iterators_to_vectors(f,e);
+ }
+};
+
+template<class R_> struct Orientation_of_points {
+ CGAL_FUNCTOR_INIT_IGNORE(Orientation_of_points)
+ typedef R_ R;
+ typedef typename R::Point_cartesian_const_iterator first_argument_type;
+ typedef typename R::Point_cartesian_const_iterator second_argument_type;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ typedef typename R::LA_vector LA;
+
+ template<class Iter>
+ result_type operator()(Iter const& f, Iter const& e) const {
+ return LA::determinant_of_iterators_to_points(f,e);
+ }
+};
+
+template<class R_> struct PV_dimension {
+ CGAL_FUNCTOR_INIT_IGNORE(PV_dimension)
+ typedef R_ R;
+ typedef typename R::Vector_ argument_type;
+ typedef int result_type;
+ typedef typename R::LA_vector LA;
+ typedef Tag_true Is_exact;
+
+ template<class T>
+ result_type operator()(T const& v) const {
+ return LA::size_of_vector(v);
+ }
+};
+
+template<class R_> struct Identity_functor {
+ CGAL_FUNCTOR_INIT_IGNORE(Identity_functor)
+ template<class T>
+ T const& operator()(T const&t) const { return t; }
+};
+
+}
+} // namespace CGAL
+#endif // CGAL_CARTESIAN_LA_FUNCTORS_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h
new file mode 100644
index 00000000..641bf8ae
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_CARTESIAN_BASE_H
+#define CGAL_KERNEL_D_CARTESIAN_BASE_H
+
+#include <CGAL/basic.h>
+#include <CGAL/NewKernel_d/Cartesian_complete.h>
+#include <CGAL/NewKernel_d/Cartesian_LA_base.h>
+
+namespace CGAL {
+#define CGAL_BASE \
+ Cartesian_LA_base_d< FT_, Dim_ >
+template < typename FT_, typename Dim_, typename Derived_=Default>
+struct Cartesian_base_d : public CGAL_BASE
+{
+ CGAL_CONSTEXPR Cartesian_base_d(){}
+ CGAL_CONSTEXPR Cartesian_base_d(int d):CGAL_BASE(d){}
+};
+#undef CGAL_BASE
+
+} //namespace CGAL
+
+#endif // CGAL_KERNEL_D_CARTESIAN_BASE_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h
new file mode 100644
index 00000000..e09c72d0
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h
@@ -0,0 +1,117 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_CARTESIAN_CHANGE_FT_H
+#define CGAL_KERNEL_D_CARTESIAN_CHANGE_FT_H
+
+#include <CGAL/basic.h>
+#include <CGAL/NT_converter.h>
+#include <CGAL/transforming_iterator.h>
+#include <CGAL/NewKernel_d/Cartesian_complete.h>
+
+namespace CGAL {
+
+template < typename Base_, typename FT_, typename LA_=CGAL::LA_eigen<FT_,typename Base_::Default_ambient_dimension> >
+struct Cartesian_change_FT_base : public
+ Base_
+{
+ CGAL_CONSTEXPR Cartesian_change_FT_base(){}
+ CGAL_CONSTEXPR Cartesian_change_FT_base(int d):Base_(d){}
+
+ typedef Cartesian_change_FT_base Self;
+ typedef Base_ Kernel_base;
+ typedef LA_ LA;
+
+ template <class T, class D=void> struct Type : Inherit_type<Base_, T> {};
+ template <class D> struct Type <FT_tag, D> { typedef FT_ type; };
+ template <class D> struct Type <RT_tag, D> { typedef FT_ type; };
+
+ typedef NT_converter<typename Get_type<Kernel_base, FT_tag>::type,FT_> FT_converter;
+ typedef transforming_iterator<FT_converter,typename Kernel_base::Point_cartesian_const_iterator> Point_cartesian_const_iterator;
+ typedef transforming_iterator<FT_converter,typename Kernel_base::Vector_cartesian_const_iterator> Vector_cartesian_const_iterator;
+ //FIXME: use Iterator_list!
+ /*
+ template<class T,bool=CGAL_BOOSTD is_same<typename iterator_tag_traits<T>::value_tag,FT_tag>::value>
+ struct Iterator : Get_type<Kernel_base,T> {};
+ template<class T> struct Iterator<T,true> {
+ typedef transforming_iterator<FT_converter,typename Get_type<Kernel_base,T>::type> type;
+ };
+ */
+
+ template<class Tag_,class Type_>
+ struct Construct_cartesian_const_iterator_ {
+ typedef typename Get_functor<Kernel_base, Tag_>::type Functor_base;
+ Construct_cartesian_const_iterator_(){}
+ Construct_cartesian_const_iterator_(Self const&r):f(r){}
+ Functor_base f;
+ typedef Type_ result_type;
+ template<class T>
+ result_type operator()(T const& v, Begin_tag)const{
+ return make_transforming_iterator(f(v,Begin_tag()),FT_converter());
+ }
+ template<class T>
+ result_type operator()(T const& v, End_tag)const{
+ return make_transforming_iterator(f(v,End_tag()),FT_converter());
+ }
+ };
+ typedef Construct_cartesian_const_iterator_<Construct_ttag<Point_cartesian_const_iterator_tag>,Point_cartesian_const_iterator> Construct_point_cartesian_const_iterator;
+ typedef Construct_cartesian_const_iterator_<Construct_ttag<Vector_cartesian_const_iterator_tag>,Vector_cartesian_const_iterator> Construct_vector_cartesian_const_iterator;
+
+ template<class Tag_>
+ struct Compute_cartesian_coordinate {
+ typedef typename Get_functor<Kernel_base, Tag_>::type Functor_base;
+ Compute_cartesian_coordinate(){}
+ Compute_cartesian_coordinate(Self const&r):f(r){}
+ Functor_base f;
+ typedef FT_ result_type;
+ template<class Obj_>
+ result_type operator()(Obj_ const& v,int i)const{
+ return FT_converter()(f(v,i));
+ }
+ };
+
+ template<class T,class U=void,class=typename Get_functor_category<Cartesian_change_FT_base,T>::type> struct Functor :
+ Inherit_functor<Kernel_base,T,U> { };
+ template<class T,class U> struct Functor<T,U,Compute_tag> { };
+ template<class T,class U> struct Functor<T,U,Predicate_tag> { };
+ template<class D> struct Functor<Compute_point_cartesian_coordinate_tag,D,Compute_tag> {
+ typedef Compute_cartesian_coordinate<Compute_point_cartesian_coordinate_tag> type;
+ };
+ template<class D> struct Functor<Compute_vector_cartesian_coordinate_tag,D,Compute_tag> {
+ typedef Compute_cartesian_coordinate<Compute_vector_cartesian_coordinate_tag> type;
+ };
+ template<class D> struct Functor<Construct_ttag<Point_cartesian_const_iterator_tag>,D,Construct_iterator_tag> {
+ typedef Construct_point_cartesian_const_iterator type;
+ };
+ template<class D> struct Functor<Construct_ttag<Vector_cartesian_const_iterator_tag>,D,Construct_iterator_tag> {
+ typedef Construct_vector_cartesian_const_iterator type;
+ };
+};
+
+template < typename Base_, typename FT_>
+struct Cartesian_change_FT : public
+ Cartesian_change_FT_base<Base_,FT_>
+{
+ CGAL_CONSTEXPR Cartesian_change_FT(){}
+ CGAL_CONSTEXPR Cartesian_change_FT(int d):Cartesian_change_FT_base<Base_,FT_>(d){}
+};
+
+} //namespace CGAL
+
+#endif // CGAL_KERNEL_D_CARTESIAN_CHANGE_FT_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h
new file mode 100644
index 00000000..ef8921db
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_CARTESIAN_COMPLETE_H
+#define CGAL_KERNEL_D_CARTESIAN_COMPLETE_H
+
+#include <CGAL/NewKernel_d/function_objects_cartesian.h>
+#include <CGAL/NewKernel_d/Cartesian_per_dimension.h>
+#include <CGAL/NewKernel_d/Types/Segment.h>
+#include <CGAL/NewKernel_d/Types/Sphere.h>
+#include <CGAL/NewKernel_d/Types/Hyperplane.h>
+#include <CGAL/NewKernel_d/Types/Aff_transformation.h>
+#include <CGAL/NewKernel_d/Types/Line.h>
+#include <CGAL/NewKernel_d/Types/Ray.h>
+#include <CGAL/NewKernel_d/Types/Iso_box.h>
+
+#endif // CGAL_KERNEL_D_CARTESIAN_COMPLETE_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h
new file mode 100644
index 00000000..179e97bf
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_CARTESIAN_FILTER_K_H
+#define CGAL_KERNEL_D_CARTESIAN_FILTER_K_H
+
+#include <CGAL/basic.h>
+#include <CGAL/NewKernel_d/KernelD_converter.h>
+#include <CGAL/NewKernel_d/Filtered_predicate2.h>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/and.hpp>
+
+namespace CGAL {
+
+template < typename Base_, typename AK_, typename EK_ >
+struct Cartesian_filter_K : public Base_,
+ private Store_kernel<AK_>, private Store_kernel2<EK_>
+{
+ CGAL_CONSTEXPR Cartesian_filter_K(){}
+ CGAL_CONSTEXPR Cartesian_filter_K(int d):Base_(d){}
+ //FIXME: or do we want an instance of AK and EK belonging to this kernel,
+ //instead of a reference to external ones?
+ CGAL_CONSTEXPR Cartesian_filter_K(AK_ const&a,EK_ const&b):Base_(),Store_kernel<AK_>(a),Store_kernel2<EK_>(b){}
+ CGAL_CONSTEXPR Cartesian_filter_K(int d,AK_ const&a,EK_ const&b):Base_(d),Store_kernel<AK_>(a),Store_kernel2<EK_>(b){}
+ typedef Base_ Kernel_base;
+ typedef AK_ AK;
+ typedef EK_ EK;
+ typedef typename Store_kernel<AK_>::reference_type AK_rt;
+ AK_rt approximate_kernel()const{return this->kernel();}
+ typedef typename Store_kernel2<EK_>::reference2_type EK_rt;
+ EK_rt exact_kernel()const{return this->kernel2();}
+
+ // MSVC is too dumb to perform the empty base optimization.
+ typedef boost::mpl::and_<
+ internal::Do_not_store_kernel<Kernel_base>,
+ internal::Do_not_store_kernel<AK>,
+ internal::Do_not_store_kernel<EK> > Do_not_store_kernel;
+
+ //TODO: C2A/C2E could be able to convert *this into this->kernel() or this->kernel2().
+ typedef KernelD_converter<Kernel_base,AK> C2A;
+ typedef KernelD_converter<Kernel_base,EK> C2E;
+
+ // fix the types
+ // TODO: only fix some types, based on some criterion?
+ template<class T> struct Type : Get_type<Kernel_base,T> {};
+
+ template<class T,class D=void,class=typename Get_functor_category<Cartesian_filter_K,T>::type> struct Functor :
+ Inherit_functor<Kernel_base,T,D> {};
+ template<class T,class D> struct Functor<T,D,Predicate_tag> {
+ typedef typename Get_functor<AK, T>::type AP;
+ typedef typename Get_functor<EK, T>::type EP;
+ typedef Filtered_predicate2<EP,AP,C2E,C2A> type;
+ };
+// TODO:
+// template<class T> struct Functor<T,No_filter_tag,Predicate_tag> :
+// Kernel_base::template Functor<T,No_filter_tag> {};
+// TODO:
+// detect when Less_cartesian_coordinate doesn't need filtering
+};
+
+} //namespace CGAL
+
+#endif // CGAL_KERNEL_D_CARTESIAN_FILTER_K_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h
new file mode 100644
index 00000000..c390a55c
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_CARTESIAN_FILTER_NT_H
+#define CGAL_KERNEL_D_CARTESIAN_FILTER_NT_H
+
+#include <CGAL/basic.h>
+#include <CGAL/NewKernel_d/Cartesian_change_FT.h>
+#include <CGAL/internal/Exact_type_selector.h>
+
+namespace CGAL {
+
+template < typename Base_ >
+struct Cartesian_filter_NT : public Base_
+{
+ CGAL_CONSTEXPR Cartesian_filter_NT(){}
+ CGAL_CONSTEXPR Cartesian_filter_NT(int d):Base_(d){}
+ typedef Base_ Kernel_base;
+ typedef Cartesian_change_FT<Kernel_base,Interval_nt_advanced> K1;
+ typedef typename internal::Exact_field_selector<typename Get_type<Kernel_base, FT_tag>::type>::Type Exact_nt;
+ typedef Cartesian_change_FT<Kernel_base,Exact_nt> K2;
+
+ template<class T,class D=void,class=typename Get_functor_category<Cartesian_filter_NT,T>::type> struct Functor :
+ Inherit_functor<Kernel_base,T,D> {};
+ template<class T,class D> struct Functor<T,D,Predicate_tag> {
+ struct type {
+ //TODO: use compression (derive from a compressed_pair?)
+ typedef typename Get_functor<K1, T>::type P1; P1 p1;
+ typedef typename Get_functor<K2, T>::type P2; P2 p2;
+ typedef typename P2::result_type result_type;
+ type(){}
+ type(Cartesian_filter_NT const&k):p1(reinterpret_cast<K1 const&>(k)),p2(reinterpret_cast<K2 const&>(k)){}
+ //FIXME: if predicate's constructor takes a kernel as argument, how do we translate that? reinterpret_cast is really ugly and possibly unsafe.
+
+#ifdef CGAL_CXX11
+ template<class...U> result_type operator()(U&&...u)const{
+ {
+ Protect_FPU_rounding<true> p;
+ try {
+ typename P1::result_type res=p1(u...); // don't forward as u may be reused
+ if(is_certain(res)) return get_certain(res);
+ } catch (Uncertain_conversion_exception) {}
+ }
+ return p2(std::forward<U>(u)...);
+ }
+#else
+ result_type operator()()const{ // does it make sense to have 0 argument?
+ {
+ Protect_FPU_rounding<true> p;
+ try {
+ typename P1::result_type res=p1();
+ if(is_certain(res)) return get_certain(res);
+ } catch (Uncertain_conversion_exception) {}
+ }
+ return p2();
+ }
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t))const{ \
+ { \
+ Protect_FPU_rounding<true> p; \
+ try { \
+ typename P1::result_type res=p1(BOOST_PP_ENUM_PARAMS(N,t)); \
+ if(is_certain(res)) return get_certain(res); \
+ } catch (Uncertain_conversion_exception) {} \
+ } \
+ return p2(BOOST_PP_ENUM_PARAMS(N,t)); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+
+#endif
+ };
+ };
+};
+
+} //namespace CGAL
+
+#endif // CGAL_KERNEL_D_CARTESIAN_FILTER_NT_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h
new file mode 100644
index 00000000..179f7319
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_CARTESIAN_PER_DIM_H
+#define CGAL_KD_CARTESIAN_PER_DIM_H
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/predicates/sign_of_determinant.h>
+
+// Should probably disappear.
+
+namespace CGAL {
+template <class Dim_, class R_, class Derived_>
+struct Cartesian_per_dimension : public R_ {};
+}
+
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h
new file mode 100644
index 00000000..693e962a
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_CARTESIAN_STATIC_FILTERS_H
+#define CGAL_KD_CARTESIAN_STATIC_FILTERS_H
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/internal/Static_filters/tools.h> // bug, should be included by the next one
+#include <CGAL/internal/Static_filters/Orientation_2.h>
+#include <boost/mpl/if.hpp>
+
+namespace CGAL {
+namespace SFA { // static filter adapter
+// Note that this would be quite a bit simpler without stateful kernels
+template <class Base_,class R_> struct Orientation_of_points_2 : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Orientation_of_points_2)
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, Orientation_tag>::type result_type;
+ typedef typename Get_type<R_, FT_tag>::type FT;
+ typedef typename Get_functor<R_, Compute_point_cartesian_coordinate_tag>::type CC;
+ typedef typename Get_functor<Base_, Orientation_of_points_tag>::type Orientation_base;
+ // TODO: Move this out for easy reuse
+ struct Adapter {
+ struct Point_2 {
+ R_ const&r; CC const&c; Point const& p;
+ Point_2(R_ const&r_, CC const&c_, Point const&p_):r(r_),c(c_),p(p_){}
+ // use result_of instead?
+ typename CC::result_type x()const{return c(p,0);}
+ typename CC::result_type y()const{return c(p,1);}
+ };
+ struct Vector_2 {};
+ struct Circle_2 {};
+ struct Orientation_2 {
+ typedef typename Orientation_of_points_2::result_type result_type;
+ result_type operator()(Point_2 const&A, Point_2 const&B, Point_2 const&C)const{
+ Point const* t[3]={&A.p,&B.p,&C.p};
+ return Orientation_base(A.r)(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+3));
+ }
+ };
+ };
+ template<class Iter> result_type operator()(Iter f, Iter CGAL_assertion_code(e))const{
+ CC c(this->kernel());
+ Point const& A=*f;
+ Point const& B=*++f;
+ Point const& C=*++f;
+ CGAL_assertion(++f==e);
+ typedef typename Adapter::Point_2 P;
+ return typename internal::Static_filters_predicates::Orientation_2<Adapter>()(P(this->kernel(),c,A),P(this->kernel(),c,B),P(this->kernel(),c,C));
+ }
+};
+}
+
+template <class Dim_ /* should be implicit */, class R_, class Derived_=Default>
+struct Cartesian_static_filters : public R_ {
+ CGAL_CONSTEXPR Cartesian_static_filters(){}
+ CGAL_CONSTEXPR Cartesian_static_filters(int d):R_(d){}
+};
+
+template <class R_, class Derived_>
+struct Cartesian_static_filters<Dimension_tag<2>, R_, Derived_> : public R_ {
+ CGAL_CONSTEXPR Cartesian_static_filters(){}
+ CGAL_CONSTEXPR Cartesian_static_filters(int d):R_(d){}
+ typedef Cartesian_static_filters<Dimension_tag<2>, R_, Derived_> Self;
+ typedef typename Default::Get<Derived_,Self>::type Derived;
+ template <class T, class=void> struct Functor : Inherit_functor<R_, T> {};
+ template <class D> struct Functor <Orientation_of_points_tag,D> {
+ typedef
+ //typename boost::mpl::if_ <
+ //boost::is_same<D,No_filter_tag>,
+ //typename Get_functor<R_, Orientation_of_points_tag>::type,
+ SFA::Orientation_of_points_2<R_,Derived>
+ // >::type
+ type;
+ };
+};
+
+}
+
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h b/include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h
new file mode 100644
index 00000000..43015d24
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h
@@ -0,0 +1,330 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_COAFFINE_H
+#define CGAL_KD_COAFFINE_H
+#include <vector>
+#include <algorithm>
+#include <iterator>
+#include <CGAL/Dimension.h>
+#include <CGAL/NewKernel_d/functor_tags.h>
+
+namespace CGAL {
+namespace CartesianDKernelFunctors {
+struct Flat_orientation {
+ std::vector<int> proj;
+ std::vector<int> rest;
+ bool reverse;
+};
+
+// For debugging purposes
+inline std::ostream& operator<< (std::ostream& o, Flat_orientation const& f) {
+ o << "Proj: ";
+ for(std::vector<int>::const_iterator i=f.proj.begin();
+ i!=f.proj.end(); ++i)
+ o << *i << ' ';
+ o << "\nRest: ";
+ for(std::vector<int>::const_iterator i=f.rest.begin();
+ i!=f.rest.end(); ++i)
+ o << *i << ' ';
+ o << "\nInv: " << f.reverse;
+ return o << '\n';
+}
+
+namespace internal {
+namespace coaffine {
+template<class Mat>
+inline void debug_matrix(std::ostream& o, Mat const&mat) {
+ for(int i=0;i<mat.rows();++i){
+ for(int j=0;j<mat.cols();++j){
+ o<<mat(i,j)<<' ';
+ }
+ o<<'\n';
+ }
+}
+}
+}
+
+template<class R_> struct Construct_flat_orientation : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_flat_orientation)
+ typedef R_ R;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type Dplusone;
+ typedef typename R::LA::template Rebind_dimension<Dynamic_dimension_tag,Dplusone>::Other LA;
+ typedef typename LA::Square_matrix Matrix;
+ typedef typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type CCC;
+ typedef typename Get_functor<R, Point_dimension_tag>::type PD;
+ typedef Flat_orientation result_type;
+
+ // This implementation is going to suck. Maybe we should push the
+ // functionality into LA. And we should check (in debug mode) that
+ // the points are affinely independent.
+ template<class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ Iter f_save = f;
+ PD pd (this->kernel());
+ CCC ccc (this->kernel());
+ int dim = pd(*f);
+ Matrix coord (dim+1, dim+1); // use distance(f,e)? This matrix doesn't need to be square.
+ int col = 0;
+ Flat_orientation o;
+ std::vector<int>& proj=o.proj;
+ std::vector<int>& rest=o.rest; rest.reserve(dim+1);
+ for(int i=0; i<dim+1; ++i) rest.push_back(i);
+ for( ; f != e ; ++col, ++f ) {
+ //std::cerr << "(*f)[0]=" << (*f)[0] << std::endl;
+ Point const&p=*f;
+ // use a coordinate iterator instead?
+ for(int i=0; i<dim; ++i) coord(col, i) = ccc(p, i);
+ coord(col,dim)=1;
+ int d = (int)proj.size()+1;
+ Matrix m (d, d);
+ // Fill the matrix with what we already have
+ for(int i=0; i<d; ++i)
+ for(int j=0; j<d-1; ++j)
+ m(i,j) = coord(i, proj[j]);
+ // Try to complete with any other coordinate
+ // TODO: iterate on rest by the end, or use a (forward_)list.
+ for(std::vector<int>::iterator it=rest.begin();;++it) {
+ CGAL_assertion(it!=rest.end());
+ for(int i=0; i<d; ++i) m(i,d-1) = coord(i, *it);
+ if(LA::sign_of_determinant(m)!=0) {
+ proj.push_back(*it);
+ rest.erase(it);
+ break;
+ }
+ }
+ }
+ std::sort(proj.begin(),proj.end());
+ typename Get_functor<R, In_flat_orientation_tag>::type ifo(this->kernel());
+ o.reverse = false;
+ o.reverse = ifo(o, f_save, e) != CGAL::POSITIVE;
+ return o;
+ }
+};
+
+template<class R_> struct Contained_in_affine_hull : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Contained_in_affine_hull)
+ typedef R_ R;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Bool_tag>::type result_type;
+ typedef typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type CCC;
+ typedef typename Get_functor<R, Point_dimension_tag>::type PD;
+ //typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1;
+ //typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2;
+ //typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA;
+ typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type Dplusone;
+ typedef typename R::LA::template Rebind_dimension<Dynamic_dimension_tag,Dplusone>::Other LA;
+ typedef typename LA::Square_matrix Matrix;
+
+ // mostly copied from Construct_flat_orientation. TODO: dedup this code or use LA.
+ template<class Iter>
+ result_type operator()(Iter f, Iter e, Point const&x) const {
+ // FIXME: are the points in (f,e) required to be affinely independent?
+ PD pd (this->kernel());
+ CCC ccc (this->kernel());
+ int dim=pd(*f);
+ Matrix coord (dim+1, dim+1); // use distance
+ int col = 0;
+ std::vector<int> proj;
+ std::vector<int> rest; rest.reserve(dim+1);
+ for(int i=0; i<dim+1; ++i) rest.push_back(i);
+ for( ; f != e ; ++col, ++f ) {
+ Point const&p=*f;
+ for(int i=0; i<dim; ++i) coord(col, i) = ccc(p, i);
+ coord(col,dim)=1;
+ int d = (int)proj.size()+1;
+ Matrix m (d, d);
+ for(int i=0; i<d; ++i)
+ for(int j=0; j<d-1; ++j)
+ m(i,j) = coord(i, proj[j]);
+ for(std::vector<int>::iterator it=rest.begin();it!=rest.end();++it) {
+ for(int i=0; i<d; ++i) m(i,d-1) = coord(i, *it);
+ if(LA::sign_of_determinant(m)!=0) {
+ proj.push_back(*it);
+ rest.erase(it);
+ break;
+ }
+ }
+ }
+ for(int i=0; i<dim; ++i) coord(col, i) = ccc(x, i);
+ coord(col,dim)=1;
+ int d = (int)proj.size()+1;
+ Matrix m (d, d);
+ for(int i=0; i<d; ++i)
+ for(int j=0; j<d-1; ++j)
+ m(i,j) = coord(i, proj[j]);
+ for(std::vector<int>::iterator it=rest.begin();it!=rest.end();++it) {
+ for(int i=0; i<d; ++i) m(i,d-1) = coord(i, *it);
+ if(LA::sign_of_determinant(m)!=0) return false;
+ }
+ return true;
+ }
+};
+
+template<class R_> struct In_flat_orientation : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(In_flat_orientation)
+ typedef R_ R;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1;
+ typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2;
+ typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA;
+ typedef typename LA::Square_matrix Matrix;
+
+ template<class Iter>
+ result_type operator()(Flat_orientation const&o, Iter f, Iter e) const {
+ // TODO: work in the projection instead of the ambient space.
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+ int d=pd(*f);
+ Matrix m(d+1,d+1);
+ int i=0;
+ for(;f!=e;++f,++i) {
+ Point const& p=*f;
+ m(i,0)=1;
+ for(int j=0;j<d;++j){
+ m(i,j+1)=c(p,j);
+ }
+ }
+ for(std::vector<int>::const_iterator it = o.rest.begin(); it != o.rest.end() /* i<d+1 */; ++i, ++it) {
+ m(i,0)=1;
+ for(int j=0;j<d;++j){
+ m(i,j+1)=0; // unneeded if the matrix is initialized to 0
+ }
+ if(*it != d) m(i,1+*it)=1;
+ }
+
+ result_type ret = LA::sign_of_determinant(CGAL_MOVE(m));
+ if(o.reverse) ret=-ret;
+ return ret;
+ }
+};
+
+template<class R_> struct In_flat_side_of_oriented_sphere : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(In_flat_side_of_oriented_sphere)
+ typedef R_ R;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ typedef typename Increment_dimension<typename R::Default_ambient_dimension,2>::type D1;
+ typedef typename Increment_dimension<typename R::Max_ambient_dimension,2>::type D2;
+ typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA;
+ typedef typename LA::Square_matrix Matrix;
+
+ template<class Iter>
+ result_type operator()(Flat_orientation const&o, Iter f, Iter e, Point const&x) const {
+ // TODO: can't work in the projection, but we should at least remove the row of 1s.
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+ int d=pd(*f);
+ Matrix m(d+2,d+2);
+ int i=0;
+ for(;f!=e;++f,++i) {
+ Point const& p=*f;
+ m(i,0)=1;
+ m(i,d+1)=0;
+ for(int j=0;j<d;++j){
+ m(i,j+1)=c(p,j);
+ m(i,d+1)+=CGAL_NTS square(m(i,j+1));
+ }
+ }
+ for(std::vector<int>::const_iterator it = o.rest.begin(); it != o.rest.end() /* i<d+1 */; ++i, ++it) {
+ m(i,0)=1;
+ for(int j=0;j<d;++j){
+ m(i,j+1)=0; // unneeded if the matrix is initialized to 0
+ }
+ if(*it != d) m(i,d+1)=m(i,1+*it)=1;
+ else m(i,d+1)=0;
+ }
+ m(d+1,0)=1;
+ m(d+1,d+1)=0;
+ for(int j=0;j<d;++j){
+ m(d+1,j+1)=c(x,j);
+ m(d+1,d+1)+=CGAL_NTS square(m(d+1,j+1));
+ }
+
+ result_type ret = -LA::sign_of_determinant(CGAL_MOVE(m));
+ if(o.reverse) ret=-ret;
+ return ret;
+ }
+};
+
+template<class R_> struct In_flat_power_side_of_power_sphere_raw : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(In_flat_power_side_of_power_sphere_raw)
+ typedef R_ R;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ typedef typename Increment_dimension<typename R::Default_ambient_dimension,2>::type D1;
+ typedef typename Increment_dimension<typename R::Max_ambient_dimension,2>::type D2;
+ typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA;
+ typedef typename LA::Square_matrix Matrix;
+
+ template<class Iter, class IterW, class Wt>
+ result_type operator()(Flat_orientation const&o, Iter f, Iter e, IterW fw, Point const&x, Wt const&w) const {
+ // TODO: can't work in the projection, but we should at least remove the row of 1s.
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+ int d=pd(*f);
+ Matrix m(d+2,d+2);
+ int i=0;
+ for(;f!=e;++f,++fw,++i) {
+ Point const& p=*f;
+ m(i,0)=1;
+ m(i,d+1)=-*fw;
+ for(int j=0;j<d;++j){
+ m(i,j+1)=c(p,j);
+ m(i,d+1)+=CGAL_NTS square(m(i,j+1));
+ }
+ }
+ for(std::vector<int>::const_iterator it = o.rest.begin(); it != o.rest.end() /* i<d+1 */; ++i, ++it) {
+ m(i,0)=1;
+ for(int j=0;j<d;++j){
+ m(i,j+1)=0; // unneeded if the matrix is initialized to 0
+ }
+ if(*it != d) m(i,d+1)=m(i,1+*it)=1;
+ else m(i,d+1)=0;
+ }
+ m(d+1,0)=1;
+ m(d+1,d+1)=-w;
+ for(int j=0;j<d;++j){
+ m(d+1,j+1)=c(x,j);
+ m(d+1,d+1)+=CGAL_NTS square(m(d+1,j+1));
+ }
+
+ result_type ret = -LA::sign_of_determinant(CGAL_MOVE(m));
+ if(o.reverse) ret=-ret;
+ return ret;
+ }
+};
+
+
+}
+CGAL_KD_DEFAULT_TYPE(Flat_orientation_tag,(CGAL::CartesianDKernelFunctors::Flat_orientation),(),());
+CGAL_KD_DEFAULT_FUNCTOR(In_flat_orientation_tag,(CartesianDKernelFunctors::In_flat_orientation<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag));
+CGAL_KD_DEFAULT_FUNCTOR(In_flat_side_of_oriented_sphere_tag,(CartesianDKernelFunctors::In_flat_side_of_oriented_sphere<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag));
+CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_raw_tag,(CartesianDKernelFunctors::In_flat_power_side_of_power_sphere_raw<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag));
+CGAL_KD_DEFAULT_FUNCTOR(Construct_flat_orientation_tag,(CartesianDKernelFunctors::Construct_flat_orientation<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag,In_flat_orientation_tag));
+CGAL_KD_DEFAULT_FUNCTOR(Contained_in_affine_hull_tag,(CartesianDKernelFunctors::Contained_in_affine_hull<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag));
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h b/include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h
new file mode 100644
index 00000000..6a40515b
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_DEFINE_KERNEL_TYPES_H
+#define CGAL_DEFINE_KERNEL_TYPES_H
+#include <CGAL/config.h>
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/typeset.h>
+#ifdef CGAL_CXX11
+#include <type_traits>
+#else
+#include <boost/type_traits.hpp>
+#endif
+
+namespace CGAL {
+ namespace internal {
+ template<class K,class Tag_,bool=iterator_tag_traits<Tag_>::is_iterator>
+ struct Type_or_iter : K::template Type<Tag_> {};
+ template<class K,class Tag_>
+ struct Type_or_iter<K, Tag_, true> : K::template Iterator<Tag_> {};
+ }
+ template<class K, class Base=K, class List=typename typeset_union<typename K::Object_list,typename K::Iterator_list>::type> struct Define_kernel_types;
+ template<class K, class Base>
+ struct Define_kernel_types <K, Base, typeset<> > : Base {};
+ template<class K>
+ struct Define_kernel_types <K, void, typeset<> > {};
+ template<class K, class Base, class List>
+ struct Define_kernel_types :
+ Typedef_tag_type<typename List::head,
+ typename internal::Type_or_iter<K,typename List::head>::type,
+ Define_kernel_types<K, Base, typename List::tail>
+ > {};
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h b/include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h
new file mode 100644
index 00000000..be875e63
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_DIMENSION_BASE_h
+#define CGAL_KD_DIMENSION_BASE_h
+#include <CGAL/Dimension.h>
+#include <CGAL/assertions.h>
+#include <CGAL/NewKernel_d/utils.h>
+namespace CGAL {
+struct Store_dimension_base {
+ //TODO: add some assertions
+ Store_dimension_base(int dim=UNKNOWN_DIMENSION):dim_(dim){}
+ int dimension()const{return dim_;}
+ void set_dimension(int dim){dim_=dim;}
+ private:
+ int dim_;
+};
+template<class=Dynamic_dimension_tag>
+struct Dimension_base {
+ Dimension_base(int = UNKNOWN_DIMENSION){}
+ int dimension() const { return UNKNOWN_DIMENSION; }
+ void set_dimension(int) {}
+};
+template<int dim_>
+struct Dimension_base<Dimension_tag<dim_> > {
+ Dimension_base(){}
+ Dimension_base(int CGAL_assertion_code(dim)){CGAL_assertion(dim_==dim);}
+ int dimension()const{return dim_;}
+ void set_dimension(int dim){CGAL_assertion(dim_==dim);}
+};
+}
+#endif
+
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h b/include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h
new file mode 100644
index 00000000..1a6a67bc
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h
@@ -0,0 +1,137 @@
+// Copyright (c) 2001-2005 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+//
+// Author(s) : Sylvain Pion
+
+#ifndef CGAL_FILTERED_PREDICATE2_H
+#define CGAL_FILTERED_PREDICATE2_H
+
+#include <string>
+#include <CGAL/config.h>
+#include <CGAL/Interval_nt.h>
+#include <CGAL/Uncertain.h>
+#include <CGAL/Profile_counter.h>
+#include <CGAL/NewKernel_d/store_kernel.h>
+#include <boost/preprocessor.hpp>
+
+namespace CGAL {
+
+// This template class is a wrapper that implements the filtering for any
+// predicate (dynamic filters with IA).
+
+// TODO :
+// - each predicate in the default kernel should define a tag that says if it
+// wants to be filtered or not (=> all homogeneous predicate define this
+// tag). We could even test-suite that automatically. It makes a strong
+// new requirement on the kernel though...
+// Could be done with a traits mechanism ?
+// A default template could use the current IA, but other tags or whatever
+// could specify no filtering at all, or static filtering...
+// - same thing for constructions => virtual operator() ?
+// - similarly, constructions should have a tag saying if they can throw or
+// not, or we let all this up to the compiler optimizer to figure out ?
+// - Some caching could be done at the Point_2 level.
+
+
+template <class EP, class AP, class C2E, class C2A, bool Protection = true>
+class Filtered_predicate2
+{
+//TODO: pack (at least use a tuple)
+//FIXME: is it better to store those, or just store enough to recreate them
+//(i.e. possibly references to the kernels)?
+ EP ep;
+ AP ap;
+ C2E c2e;
+ C2A c2a;
+
+ typedef typename AP::result_type Ares;
+
+public:
+
+ typedef AP Approximate_predicate;
+ typedef EP Exact_predicate;
+ typedef C2E To_exact_converter;
+ typedef C2A To_approximate_converter;
+
+ // FIXME: should use result_of, see emails by Nico
+ typedef typename EP::result_type result_type;
+ // AP::result_type must be convertible to EP::result_type.
+
+ Filtered_predicate2()
+ {}
+
+ template <class K>
+ Filtered_predicate2(const K& k)
+ : ep(k.exact_kernel()), ap(k.approximate_kernel()), c2e(k,k.exact_kernel()), c2a(k,k.approximate_kernel())
+ {}
+
+#ifdef CGAL_CXX11
+ template <typename... Args>
+ result_type
+ operator()(Args&&... args) const
+ {
+ CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
+ // Protection is outside the try block as VC8 has the CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG
+ {
+ Protect_FPU_rounding<Protection> p;
+ try
+ {
+ // No forward here, the arguments may still be needed
+ Ares res = ap(c2a(args)...);
+ if (is_certain(res))
+ return get_certain(res);
+ }
+ catch (Uncertain_conversion_exception) {}
+ }
+ CGAL_BRANCH_PROFILER_BRANCH(tmp);
+ Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
+ return ep(c2e(std::forward<Args>(args))...);
+ }
+#else
+
+#define CGAL_VAR(Z,N,C) C(a##N)
+#define CGAL_CODE(Z,N,_) \
+ template <BOOST_PP_ENUM_PARAMS(N,class A)> \
+ result_type \
+ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a)) const \
+ { \
+ CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); \
+ { \
+ Protect_FPU_rounding<Protection> p; \
+ try \
+ { \
+ Ares res = ap(BOOST_PP_ENUM(N,CGAL_VAR,c2a)); \
+ if (is_certain(res)) \
+ return get_certain(res); \
+ } \
+ catch (Uncertain_conversion_exception) {} \
+ } \
+ CGAL_BRANCH_PROFILER_BRANCH(tmp); \
+ Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST); \
+ return ep(BOOST_PP_ENUM(N,CGAL_VAR,c2e)); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1, 10, CGAL_CODE, _ )
+#undef CGAL_CODE
+#undef CGAL_VAR
+
+#endif
+};
+
+} //namespace CGAL
+
+#endif // CGAL_FILTERED_PREDICATE2_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h b/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h
new file mode 100644
index 00000000..a8896976
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h
@@ -0,0 +1,199 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_CARTESIAN_CONVERTER_H
+#define CGAL_KERNEL_D_CARTESIAN_CONVERTER_H
+
+#include <CGAL/basic.h>
+#include <CGAL/tuple.h>
+#include <CGAL/typeset.h>
+#include <CGAL/Object.h>
+#include <CGAL/Origin.h>
+#include <CGAL/NT_converter.h>
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Kernel/mpl.h>
+#include <CGAL/is_iterator.h>
+#include <CGAL/transforming_iterator.h>
+#include <boost/utility/enable_if.hpp>
+#include <boost/mpl/if.hpp>
+#include <CGAL/NewKernel_d/store_kernel.h>
+#include <CGAL/NewKernel_d/Kernel_object_converter.h>
+
+namespace CGAL {
+namespace internal {
+// Reverses order, but that shouldn't matter.
+template<class K,class T> struct Map_taglist_to_typelist :
+ Map_taglist_to_typelist<K,typename T::tail>::type
+ ::template add<typename Get_type<K, typename T::head>::type>
+{};
+template<class K> struct Map_taglist_to_typelist<K,typeset<> > : typeset<> {};
+}
+
+template<class List = typeset<> >
+struct Object_converter {
+ typedef Object result_type;
+ template<class F>
+ result_type operator()(Object const& o, F const& f) const {
+ typedef typename List::head H;
+ if (H const* ptr = object_cast<H>(&o))
+ return make_object(f(*ptr));
+ else
+ return Object_converter<typename List::tail>()(o,f);
+ }
+};
+template<>
+struct Object_converter <typeset<> > {
+ typedef Object result_type;
+ template<class F>
+ result_type operator()(Object const&,F const&)const {
+ CGAL_error_msg("Cartesiand_converter is unable to determine what is wrapped in the Object");
+ return Object();
+ }
+};
+
+
+ //TODO: special case when K1==K2 (or they are very close?)
+template<class Final_, class K1, class K2, class List>
+class KernelD_converter_
+: public KernelD_converter_<Final_,K1,K2,typename List::tail>
+{
+ typedef typename List::head Tag_;
+ typedef typename List::tail Rest;
+ typedef KernelD_converter_<Final_,K1,K2,Rest> Base;
+ typedef typename Get_type<K1,Tag_>::type K1_Obj;
+ typedef typename Get_type<K2,Tag_>::type K2_Obj;
+ typedef typename Get_functor<K1, Convert_ttag<Tag_> >::type K1_Conv;
+ typedef KO_converter<Tag_,K1,K2> KOC;
+ typedef CGAL_BOOSTD is_same<K1_Conv, Null_functor> no_converter;
+ typedef typename internal::Map_taglist_to_typelist<K1,Rest>::type::template contains<K1_Obj> duplicate;
+
+ // Disable the conversion in some cases:
+ struct Do_not_use{};
+
+ // Explicit calls to boost::mpl functions to avoid parenthesis
+ // warning on some versions of GCC
+ typedef typename boost::mpl::if_ <
+ // If Point==Vector, keep only one conversion
+ boost::mpl::or_<boost::mpl::bool_<duplicate::value>,
+ // For iterator objects, the default is make_transforming_iterator
+ boost::mpl::bool_<(iterator_tag_traits<Tag_>::is_iterator && no_converter::value)> >,
+ Do_not_use,K1_Obj>::type argument_type;
+ //typedef typename KOC::argument_type K1_Obj;
+ //typedef typename KOC::result_type K2_Obj;
+ public:
+ using Base::operator(); // don't use directly, just make it accessible to the next level
+ K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD true_type)const{
+ return KOC()(this->myself().kernel(),this->myself().kernel2(),this->myself(),o);
+ }
+ K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD false_type)const{
+ return K1_Conv(this->myself().kernel())(this->myself().kernel2(),this->myself(),o);
+ }
+ K2_Obj operator()(argument_type const& o)const{
+ return helper(o,no_converter());
+ }
+ template<class X,int=0> struct result:Base::template result<X>{};
+ template<int i> struct result<Final_(argument_type),i> {typedef K2_Obj type;};
+};
+
+template<class Final_, class K1, class K2>
+class KernelD_converter_<Final_,K1,K2,typeset<> > {
+ public:
+ struct Do_not_use2{};
+ void operator()(Do_not_use2)const{}
+ template<class T> struct result;
+ Final_& myself(){return *static_cast<Final_*>(this);}
+ Final_ const& myself()const{return *static_cast<Final_ const*>(this);}
+};
+
+
+// TODO: use the intersection of Kn::Object_list.
+template<class K1, class K2, class List_=
+typename typeset_intersection<typename K1::Object_list, typename K2::Object_list>::type
+//typeset<Point_tag>::add<Vector_tag>::type/*::add<Segment_tag>::type*/
+> class KernelD_converter
+ : public Store_kernel<K1>, public Store_kernel2<K2>,
+ public KernelD_converter_<KernelD_converter<K1,K2,List_>,K1,K2,List_>
+{
+ typedef KernelD_converter Self;
+ typedef Self Final_;
+ typedef KernelD_converter_<Self,K1,K2,List_> Base;
+ typedef typename Get_type<K1, FT_tag>::type FT1;
+ typedef typename Get_type<K2, FT_tag>::type FT2;
+ typedef NT_converter<FT1, FT2> NTc;
+ NTc c; // TODO: compressed storage as this is likely empty and the converter gets passed around (and stored in iterators)
+
+ public:
+ KernelD_converter(){}
+ KernelD_converter(K1 const&a,K2 const&b):Store_kernel<K1>(a),Store_kernel2<K2>(b){}
+
+ // For boost::result_of, used in transforming_iterator
+ template<class T,int i=is_iterator<T>::value?42:0> struct result:Base::template result<T>{};
+ template<class T> struct result<Final_(T),42> {
+ typedef transforming_iterator<Final_,T> type;
+ };
+ template<int i> struct result<Final_(K1),i>{typedef K2 type;};
+ template<int i> struct result<Final_(int),i>{typedef int type;};
+ // Ideally the next 2 would come with Point_tag and Vector_tag, but that's hard...
+ template<int i> struct result<Final_(Origin),i>{typedef Origin type;};
+ template<int i> struct result<Final_(Null_vector),i>{typedef Null_vector type;};
+ template<int i> struct result<Final_(Object),i>{typedef Object type;};
+ template<int i> struct result<Final_(FT1),i>{typedef FT2 type;};
+
+ using Base::operator();
+ typename Store_kernel2<K2>::reference2_type operator()(K1 const&)const{return this->kernel2();}
+ int operator()(int i)const{return i;}
+ Origin operator()(Origin const&o)const{return o;}
+ Null_vector operator()(Null_vector const&v)const{return v;}
+ FT2 operator()(FT1 const&x)const{return c(x);}
+ //RT2 operator()(typename First_if_different<RT1,FT1>::Type const&x)const{return cr(x);}
+
+ typename Get_type<K2, Flat_orientation_tag>::type const&
+ operator()(typename Get_type<K1, Flat_orientation_tag>::type const&o)const
+ { return o; } // Both kernels should have the same, returning a reference should warn if not.
+
+ template<class It>
+ transforming_iterator<Final_,typename boost::enable_if<is_iterator<It>,It>::type>
+ operator()(It const& it) const {
+ return make_transforming_iterator(it,*this);
+ }
+
+ template<class T>
+ //TODO: use decltype in C++11 instead of result
+ std::vector<typename result<Final_(T)>::type>
+ operator()(const std::vector<T>& v) const {
+ return std::vector<typename result<Final_(T)>::type>(operator()(v.begin()),operator()(v.begin()));
+ }
+
+ //TODO: convert std::list and other containers?
+
+ Object
+ operator()(const Object &obj) const
+ {
+ typedef typename internal::Map_taglist_to_typelist<K1,List_>::type Possibilities;
+ //TODO: add Empty, vector<Point>, etc to the list.
+ return Object_converter<Possibilities>()(obj,*this);
+ }
+
+ //TODO: convert boost::variant
+
+};
+
+} //namespace CGAL
+
+#endif // CGAL_KERNEL_D_CARTESIAN_CONVERTER_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h b/include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h
new file mode 100644
index 00000000..fa30dff0
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h
@@ -0,0 +1,104 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_KERNEL_2_INTERFACE_H
+#define CGAL_KD_KERNEL_2_INTERFACE_H
+
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/transforming_iterator.h>
+#include <CGAL/NewKernel_d/utils.h>
+#include <CGAL/tuple.h>
+
+
+namespace CGAL {
+template <class Base_> struct Kernel_2_interface : public Base_ {
+ typedef Base_ Base;
+ typedef Kernel_2_interface<Base> Kernel;
+ typedef typename Get_type<Base, RT_tag>::type RT;
+ typedef typename Get_type<Base, FT_tag>::type FT;
+ typedef typename Get_type<Base, Bool_tag>::type Boolean;
+ typedef typename Get_type<Base, Sign_tag>::type Sign;
+ typedef typename Get_type<Base, Comparison_result_tag>::type Comparison_result;
+ typedef typename Get_type<Base, Orientation_tag>::type Orientation;
+ typedef typename Get_type<Base, Oriented_side_tag>::type Oriented_side;
+ typedef typename Get_type<Base, Bounded_side_tag>::type Bounded_side;
+ typedef typename Get_type<Base, Angle_tag>::type Angle;
+ typedef typename Get_type<Base, Point_tag>::type Point_2;
+ typedef typename Get_type<Base, Vector_tag>::type Vector_2;
+ typedef typename Get_type<Base, Segment_tag>::type Segment_2;
+ typedef cpp0x::tuple<Point_2,Point_2,Point_2> Triangle_2; // triangulation insists...
+ template <class T,int i> struct Help_2p_i {
+ typedef typename Get_functor<Base, T>::type LT;
+ typedef typename LT::result_type result_type;
+ LT lt;
+ Help_2p_i(Kernel const&k):lt(k){}
+ result_type operator()(Point_2 const&a, Point_2 const&b) {
+ return lt(a,b,i);
+ }
+ };
+ typedef Help_2p_i<Less_point_cartesian_coordinate_tag,0> Less_x_2;
+ typedef Help_2p_i<Less_point_cartesian_coordinate_tag,1> Less_y_2;
+ typedef Help_2p_i<Compare_point_cartesian_coordinate_tag,0> Compare_x_2;
+ typedef Help_2p_i<Compare_point_cartesian_coordinate_tag,1> Compare_y_2;
+ struct Compare_distance_2 {
+ typedef typename Get_functor<Base, Compare_distance_tag>::type CD;
+ typedef typename CD::result_type result_type;
+ CD cd;
+ Compare_distance_2(Kernel const&k):cd(k){}
+ result_type operator()(Point_2 const&a, Point_2 const&b, Point_2 const&c) {
+ return cd(a,b,c);
+ }
+ result_type operator()(Point_2 const&a, Point_2 const&b, Point_2 const&c, Point_2 const&d) {
+ return cd(a,b,c,d);
+ }
+ };
+ struct Orientation_2 {
+ typedef typename Get_functor<Base, Orientation_of_points_tag>::type O;
+ typedef typename O::result_type result_type;
+ O o;
+ Orientation_2(Kernel const&k):o(k){}
+ result_type operator()(Point_2 const&a, Point_2 const&b, Point_2 const&c) {
+ //return o(a,b,c);
+ Point_2 const* t[3]={&a,&b,&c};
+ return o(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+3));
+
+ }
+ };
+ struct Side_of_oriented_circle_2 {
+ typedef typename Get_functor<Base, Side_of_oriented_sphere_tag>::type SOS;
+ typedef typename SOS::result_type result_type;
+ SOS sos;
+ Side_of_oriented_circle_2(Kernel const&k):sos(k){}
+ result_type operator()(Point_2 const&a, Point_2 const&b, Point_2 const&c, Point_2 const&d) {
+ //return sos(a,b,c,d);
+ Point_2 const* t[4]={&a,&b,&c,&d};
+ return sos(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+4));
+ }
+ };
+ Less_x_2 less_x_2_object()const{ return Less_x_2(*this); }
+ Less_y_2 less_y_2_object()const{ return Less_y_2(*this); }
+ Compare_x_2 compare_x_2_object()const{ return Compare_x_2(*this); }
+ Compare_y_2 compare_y_2_object()const{ return Compare_y_2(*this); }
+ Compare_distance_2 compare_distance_2_object()const{ return Compare_distance_2(*this); }
+ Orientation_2 orientation_2_object()const{ return Orientation_2(*this); }
+ Side_of_oriented_circle_2 side_of_oriented_circle_2_object()const{ return Side_of_oriented_circle_2(*this); }
+};
+}
+
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h b/include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h
new file mode 100644
index 00000000..96076aa8
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h
@@ -0,0 +1,102 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_KERNEL_3_INTERFACE_H
+#define CGAL_KD_KERNEL_3_INTERFACE_H
+
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/transforming_iterator.h>
+#include <CGAL/NewKernel_d/utils.h>
+#include <CGAL/tuple.h>
+
+
+namespace CGAL {
+template <class Base_> struct Kernel_3_interface : public Base_ {
+ typedef Base_ Base;
+ typedef Kernel_3_interface<Base> Kernel;
+ typedef typename Get_type<Base, RT_tag>::type RT;
+ typedef typename Get_type<Base, FT_tag>::type FT;
+ typedef typename Get_type<Base, Bool_tag>::type Boolean;
+ typedef typename Get_type<Base, Sign_tag>::type Sign;
+ typedef typename Get_type<Base, Comparison_result_tag>::type Comparison_result;
+ typedef typename Get_type<Base, Orientation_tag>::type Orientation;
+ typedef typename Get_type<Base, Oriented_side_tag>::type Oriented_side;
+ typedef typename Get_type<Base, Bounded_side_tag>::type Bounded_side;
+ typedef typename Get_type<Base, Angle_tag>::type Angle;
+ typedef typename Get_type<Base, Point_tag>::type Point_3;
+ typedef typename Get_type<Base, Vector_tag>::type Vector_3;
+ typedef typename Get_type<Base, Segment_tag>::type Segment_3;
+ typedef cpp0x::tuple<Point_3,Point_3,Point_3> Triangle_3; // placeholder
+ typedef cpp0x::tuple<Point_3,Point_3,Point_3,Point_3> Tetrahedron_3; // placeholder
+ struct Compare_xyz_3 {
+ typedef typename Get_functor<Base, Compare_lexicographically_tag>::type CL;
+ typedef typename CL::result_type result_type;
+ CL cl;
+ Compare_xyz_3(Kernel const&k):cl(k){}
+ result_type operator()(Point_3 const&a, Point_3 const&b) {
+ return cl(a,b);
+ }
+ };
+ struct Compare_distance_3 {
+ typedef typename Get_functor<Base, Compare_distance_tag>::type CD;
+ typedef typename CD::result_type result_type;
+ CD cd;
+ Compare_distance_3(Kernel const&k):cd(k){}
+ result_type operator()(Point_3 const&a, Point_3 const&b, Point_3 const&c) {
+ return cd(a,b,c);
+ }
+ result_type operator()(Point_3 const&a, Point_3 const&b, Point_3 const&c, Point_3 const&d) {
+ return cd(a,b,c,d);
+ }
+ };
+ struct Orientation_3 {
+ typedef typename Get_functor<Base, Orientation_of_points_tag>::type O;
+ typedef typename O::result_type result_type;
+ O o;
+ Orientation_3(Kernel const&k):o(k){}
+ result_type operator()(Point_3 const&a, Point_3 const&b, Point_3 const&c, Point_3 const&d) {
+ //return o(a,b,c,d);
+ Point_3 const* t[4]={&a,&b,&c,&d};
+ return o(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+4));
+
+ }
+ };
+ struct Side_of_oriented_sphere_3 {
+ typedef typename Get_functor<Base, Side_of_oriented_sphere_tag>::type SOS;
+ typedef typename SOS::result_type result_type;
+ SOS sos;
+ Side_of_oriented_sphere_3(Kernel const&k):sos(k){}
+ result_type operator()(Point_3 const&a, Point_3 const&b, Point_3 const&c, Point_3 const&d, Point_3 const&e) {
+ //return sos(a,b,c,d);
+ Point_3 const* t[5]={&a,&b,&c,&d,&e};
+ return sos(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+5));
+ }
+ };
+
+ // I don't have the Coplanar predicates (yet)
+
+
+ Compare_xyz_3 compare_xyz_3_object()const{ return Compare_xyz_3(*this); }
+ Compare_distance_3 compare_distance_3_object()const{ return Compare_distance_3(*this); }
+ Orientation_3 orientation_3_object()const{ return Orientation_3(*this); }
+ Side_of_oriented_sphere_3 side_of_oriented_sphere_3_object()const{ return Side_of_oriented_sphere_3(*this); }
+};
+}
+
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h b/include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h
new file mode 100644
index 00000000..dd888005
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h
@@ -0,0 +1,298 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_KERNEL_D_INTERFACE_H
+#define CGAL_KD_KERNEL_D_INTERFACE_H
+
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/transforming_iterator.h>
+#include <CGAL/NewKernel_d/utils.h>
+#include <CGAL/tuple.h>
+
+
+namespace CGAL {
+template <class Base_> struct Kernel_d_interface : public Base_ {
+ CGAL_CONSTEXPR Kernel_d_interface(){}
+ CGAL_CONSTEXPR Kernel_d_interface(int d):Base_(d){}
+
+ typedef Base_ Base;
+ typedef Kernel_d_interface<Base> Kernel;
+ typedef Base_ R_; // for the macros
+ typedef typename Get_type<Base, RT_tag>::type RT;
+ typedef typename Get_type<Base, FT_tag>::type FT;
+ typedef typename Get_type<Base, Bool_tag>::type Boolean;
+ typedef typename Get_type<Base, Sign_tag>::type Sign;
+ typedef typename Get_type<Base, Comparison_result_tag>::type Comparison_result;
+ typedef typename Get_type<Base, Orientation_tag>::type Orientation;
+ typedef typename Get_type<Base, Oriented_side_tag>::type Oriented_side;
+ typedef typename Get_type<Base, Bounded_side_tag>::type Bounded_side;
+ typedef typename Get_type<Base, Angle_tag>::type Angle;
+ typedef typename Get_type<Base, Flat_orientation_tag>::type Flat_orientation_d;
+ typedef typename Get_type<Base, Point_tag>::type Point_d;
+ typedef typename Get_type<Base, Vector_tag>::type Vector_d;
+ typedef typename Get_type<Base, Segment_tag>::type Segment_d;
+ typedef typename Get_type<Base, Sphere_tag>::type Sphere_d;
+ typedef typename Get_type<Base, Hyperplane_tag>::type Hyperplane_d;
+ typedef Vector_d Direction_d;
+ typedef typename Get_type<Base, Line_tag>::type Line_d;
+ typedef typename Get_type<Base, Ray_tag>::type Ray_d;
+ typedef typename Get_type<Base, Iso_box_tag>::type Iso_box_d;
+ typedef typename Get_type<Base, Aff_transformation_tag>::type Aff_transformation_d;
+ typedef typename Get_type<Base, Weighted_point_tag>::type Weighted_point_d;
+ typedef typename Get_functor<Base, Compute_point_cartesian_coordinate_tag>::type Compute_coordinate_d;
+ typedef typename Get_functor<Base, Compare_lexicographically_tag>::type Compare_lexicographically_d;
+ typedef typename Get_functor<Base, Equal_points_tag>::type Equal_d;
+ typedef typename Get_functor<Base, Less_lexicographically_tag>::type Less_lexicographically_d;
+ typedef typename Get_functor<Base, Less_or_equal_lexicographically_tag>::type Less_or_equal_lexicographically_d;
+ // FIXME: and vectors?
+ typedef typename Get_functor<Base, Orientation_of_points_tag>::type Orientation_d;
+ typedef typename Get_functor<Base, Less_point_cartesian_coordinate_tag>::type Less_coordinate_d;
+ typedef typename Get_functor<Base, Point_dimension_tag>::type Point_dimension_d;
+ typedef typename Get_functor<Base, Side_of_oriented_sphere_tag>::type Side_of_oriented_sphere_d;
+ typedef typename Get_functor<Base, Power_side_of_power_sphere_tag>::type Power_side_of_power_sphere_d;
+ typedef typename Get_functor<Base, Power_center_tag>::type Power_center_d;
+ typedef typename Get_functor<Base, Power_distance_tag>::type Power_distance_d;
+ typedef typename Get_functor<Base, Contained_in_affine_hull_tag>::type Contained_in_affine_hull_d;
+ typedef typename Get_functor<Base, Construct_flat_orientation_tag>::type Construct_flat_orientation_d;
+ typedef typename Get_functor<Base, In_flat_orientation_tag>::type In_flat_orientation_d;
+ typedef typename Get_functor<Base, In_flat_side_of_oriented_sphere_tag>::type In_flat_side_of_oriented_sphere_d;
+ typedef typename Get_functor<Base, In_flat_power_side_of_power_sphere_tag>::type In_flat_power_side_of_power_sphere_d;
+ typedef typename Get_functor<Base, Point_to_vector_tag>::type Point_to_vector_d;
+ typedef typename Get_functor<Base, Vector_to_point_tag>::type Vector_to_point_d;
+ typedef typename Get_functor<Base, Translated_point_tag>::type Translated_point_d;
+ typedef typename Get_functor<Base, Scaled_vector_tag>::type Scaled_vector_d;
+ typedef typename Get_functor<Base, Difference_of_vectors_tag>::type Difference_of_vectors_d;
+ typedef typename Get_functor<Base, Difference_of_points_tag>::type Difference_of_points_d;
+ //typedef typename Get_functor<Base, Construct_ttag<Point_tag> >::type Construct_point_d;
+ struct Construct_point_d : private Store_kernel<Kernel> {
+ typedef Kernel R_; // for the macro
+ CGAL_FUNCTOR_INIT_STORE(Construct_point_d)
+ typedef typename Get_functor<Base, Construct_ttag<Point_tag> >::type CP;
+ typedef Point_d result_type;
+ Point_d operator()(Weighted_point_d const&wp)const{
+ return typename Get_functor<Base, Point_drop_weight_tag>::type(this->kernel())(wp);
+ }
+#ifdef CGAL_CXX11
+ Point_d operator()(Weighted_point_d &wp)const{
+ return typename Get_functor<Base, Point_drop_weight_tag>::type(this->kernel())(wp);
+ }
+ Point_d operator()(Weighted_point_d &&wp)const{
+ return typename Get_functor<Base, Point_drop_weight_tag>::type(this->kernel())(std::move(wp));
+ }
+ Point_d operator()(Weighted_point_d const&&wp)const{
+ return typename Get_functor<Base, Point_drop_weight_tag>::type(this->kernel())(std::move(wp));
+ }
+ template<class...T>
+# if __cplusplus >= 201402L
+ decltype(auto)
+# else
+ Point_d
+# endif
+ operator()(T&&...t)const{
+ return CP(this->kernel())(std::forward<T>(t)...);
+ //return CP(this->kernel())(t...);
+ }
+#else
+# define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Point_d operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t))const{ \
+ return CP(this->kernel())(BOOST_PP_ENUM_PARAMS(N,t)); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+# undef CGAL_CODE
+ Point_d operator()()const{ \
+ return CP(this->kernel())(); \
+ }
+#endif
+ };
+ typedef typename Get_functor<Base, Construct_ttag<Vector_tag> >::type Construct_vector_d;
+ typedef typename Get_functor<Base, Construct_ttag<Segment_tag> >::type Construct_segment_d;
+ typedef typename Get_functor<Base, Construct_ttag<Sphere_tag> >::type Construct_sphere_d;
+ typedef typename Get_functor<Base, Construct_ttag<Hyperplane_tag> >::type Construct_hyperplane_d;
+ typedef Construct_vector_d Construct_direction_d;
+ typedef typename Get_functor<Base, Construct_ttag<Line_tag> >::type Construct_line_d;
+ typedef typename Get_functor<Base, Construct_ttag<Ray_tag> >::type Construct_ray_d;
+ typedef typename Get_functor<Base, Construct_ttag<Iso_box_tag> >::type Construct_iso_box_d;
+ typedef typename Get_functor<Base, Construct_ttag<Aff_transformation_tag> >::type Construct_aff_transformation_d;
+ typedef typename Get_functor<Base, Construct_ttag<Weighted_point_tag> >::type Construct_weighted_point_d;
+ typedef typename Get_functor<Base, Midpoint_tag>::type Midpoint_d;
+ struct Component_accessor_d : private Store_kernel<Kernel> {
+ typedef Kernel R_; // for the macro
+ CGAL_FUNCTOR_INIT_STORE(Component_accessor_d)
+ int dimension(Point_d const&p){
+ return this->kernel().point_dimension_d_object()(p);
+ }
+ FT cartesian(Point_d const&p, int i){
+ return this->kernel().compute_coordinate_d_object()(p,i);
+ }
+ RT homogeneous(Point_d const&p, int i){
+ if (i == dimension(p))
+ return 1;
+ return cartesian(p, i);
+ }
+ };
+ struct Construct_cartesian_const_iterator_d : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_cartesian_const_iterator_d)
+ typedef typename Get_functor<Base, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CPI;
+ typedef typename Get_functor<Base, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CVI;
+ // FIXME: The following sometimes breaks compilation. The typedef below forces instantiation of this, which forces Point_d, which itself (in the wrapper) needs the derived kernel to tell it what the base kernel is, and that's a cycle. The exact circumstances are not clear, g++ and clang++ are ok in both C++03 and C++11, it is only clang in C++11 without CGAL_CXX11 that breaks. For now, rely on result_type.
+ //typedef typename CGAL::decay<typename boost::result_of<CPI(Point_d,CGAL::Begin_tag)>::type>::type result_type;
+ typedef typename CGAL::decay<typename CPI::result_type>::type result_type;
+ // Kernel_d requires a common iterator type for points and vectors
+ // TODO: provide this mixed functor in preKernel?
+ //CGAL_static_assertion((boost::is_same<typename CGAL::decay<typename boost::result_of<CVI(Vector_d,CGAL::Begin_tag)>::type>::type, result_type>::value));
+ CGAL_static_assertion((boost::is_same<typename CGAL::decay<typename CVI::result_type>::type, result_type>::value));
+ template <class Tag_>
+ result_type operator()(Point_d const&p, Tag_ t)const{
+ return CPI(this->kernel())(p,t);
+ }
+ template <class Tag_>
+ result_type operator()(typename First_if_different<Vector_d,Point_d>::Type const&v, Tag_ t)const{
+ return CVI(this->kernel())(v,t);
+ }
+
+ template <class Obj>
+ result_type operator()(Obj const&o)const{
+ return operator()(o, Begin_tag());
+ }
+ result_type operator()(Point_d const&p, int)const{
+ return operator()(p, End_tag());
+ }
+ result_type operator()(typename First_if_different<Vector_d,Point_d>::Type const&v, int)const{
+ return operator()(v, End_tag());
+ }
+ };
+ struct Compute_squared_radius_d : private Store_kernel<Kernel> {
+ typedef Kernel R_; // for the macro
+ CGAL_FUNCTOR_INIT_STORE(Compute_squared_radius_d)
+ typedef FT result_type;
+ template<class S> FT operator()(CGAL_FORWARDABLE(S) s)const{
+ return typename Get_functor<Base, Squared_radius_tag>::type(this->kernel())(CGAL_FORWARD(S,s));
+ }
+ template<class I> FT operator()(I b, I e)const{
+ return typename Get_functor<Base, Squared_circumradius_tag>::type(this->kernel())(b,e);
+ }
+ };
+ typedef typename Construct_cartesian_const_iterator_d::result_type Cartesian_const_iterator_d;
+ typedef typename Get_functor<Base, Squared_distance_tag>::type Squared_distance_d;
+ typedef typename Get_functor<Base, Squared_length_tag>::type Squared_length_d;
+ typedef typename Get_functor<Base, Scalar_product_tag>::type Scalar_product_d;
+ typedef typename Get_functor<Base, Affine_rank_tag>::type Affine_rank_d;
+ typedef typename Get_functor<Base, Affinely_independent_tag>::type Affinely_independent_d;
+ typedef typename Get_functor<Base, Contained_in_linear_hull_tag>::type Contained_in_linear_hull_d;
+ typedef typename Get_functor<Base, Contained_in_simplex_tag>::type Contained_in_simplex_d;
+ typedef typename Get_functor<Base, Has_on_positive_side_tag>::type Has_on_positive_side_d;
+ typedef typename Get_functor<Base, Linear_rank_tag>::type Linear_rank_d;
+ typedef typename Get_functor<Base, Linearly_independent_tag>::type Linearly_independent_d;
+ typedef typename Get_functor<Base, Oriented_side_tag>::type Oriented_side_d;
+ typedef typename Get_functor<Base, Side_of_bounded_circumsphere_tag>::type Side_of_bounded_sphere_d;
+
+ typedef typename Get_functor<Base, Center_of_sphere_tag>::type Center_of_sphere_d;
+ typedef Center_of_sphere_d Construct_center_d; // RangeSearchTraits
+ typedef typename Get_functor<Base, Construct_circumcenter_tag>::type Construct_circumcenter_d;
+ typedef typename Get_functor<Base, Value_at_tag>::type Value_at_d;
+ typedef typename Get_functor<Base, Point_of_sphere_tag>::type Point_of_sphere_d;
+ typedef typename Get_functor<Base, Orthogonal_vector_tag>::type Orthogonal_vector_d;
+ typedef typename Get_functor<Base, Linear_base_tag>::type Linear_base_d;
+ typedef typename Get_functor<Base, Construct_min_vertex_tag>::type Construct_min_vertex_d;
+ typedef typename Get_functor<Base, Construct_max_vertex_tag>::type Construct_max_vertex_d;
+
+ typedef typename Get_functor<Base, Point_weight_tag>::type Compute_weight_d;
+ typedef typename Get_functor<Base, Point_drop_weight_tag>::type Point_drop_weight_d;
+
+ //TODO:
+ //typedef ??? Intersect_d;
+
+
+ Compute_coordinate_d compute_coordinate_d_object()const{ return Compute_coordinate_d(*this); }
+ Has_on_positive_side_d has_on_positive_side_d_object()const{ return Has_on_positive_side_d(*this); }
+ Compare_lexicographically_d compare_lexicographically_d_object()const{ return Compare_lexicographically_d(*this); }
+ Equal_d equal_d_object()const{ return Equal_d(*this); }
+ Less_lexicographically_d less_lexicographically_d_object()const{ return Less_lexicographically_d(*this); }
+ Less_or_equal_lexicographically_d less_or_equal_lexicographically_d_object()const{ return Less_or_equal_lexicographically_d(*this); }
+ Less_coordinate_d less_coordinate_d_object()const{ return Less_coordinate_d(*this); }
+ Orientation_d orientation_d_object()const{ return Orientation_d(*this); }
+ Oriented_side_d oriented_side_d_object()const{ return Oriented_side_d(*this); }
+ Point_dimension_d point_dimension_d_object()const{ return Point_dimension_d(*this); }
+ Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); }
+ Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); }
+ Power_side_of_power_sphere_d power_side_of_power_sphere_d_object()const{ return Power_side_of_power_sphere_d(*this); }
+ Power_center_d power_center_d_object()const{ return Power_center_d(*this); }
+ Power_distance_d power_distance_d_object()const{ return Power_distance_d(*this); }
+ Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); }
+ Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); }
+ Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); }
+ Contained_in_simplex_d contained_in_simplex_d_object()const{ return Contained_in_simplex_d(*this); }
+ Construct_flat_orientation_d construct_flat_orientation_d_object()const{ return Construct_flat_orientation_d(*this); }
+ In_flat_orientation_d in_flat_orientation_d_object()const{ return In_flat_orientation_d(*this); }
+ In_flat_side_of_oriented_sphere_d in_flat_side_of_oriented_sphere_d_object()const{ return In_flat_side_of_oriented_sphere_d(*this); }
+ In_flat_power_side_of_power_sphere_d in_flat_power_side_of_power_sphere_d_object()const{ return In_flat_power_side_of_power_sphere_d(*this); }
+ Point_to_vector_d point_to_vector_d_object()const{ return Point_to_vector_d(*this); }
+ Vector_to_point_d vector_to_point_d_object()const{ return Vector_to_point_d(*this); }
+ Translated_point_d translated_point_d_object()const{ return Translated_point_d(*this); }
+ Scaled_vector_d scaled_vector_d_object()const{ return Scaled_vector_d(*this); }
+ Difference_of_vectors_d difference_of_vectors_d_object()const{ return Difference_of_vectors_d(*this); }
+ Difference_of_points_d difference_of_points_d_object()const{ return Difference_of_points_d(*this); }
+ Affine_rank_d affine_rank_d_object()const{ return Affine_rank_d(*this); }
+ Affinely_independent_d affinely_independent_d_object()const{ return Affinely_independent_d(*this); }
+ Linear_base_d linear_base_d_object()const{ return Linear_base_d(*this); }
+ Linear_rank_d linear_rank_d_object()const{ return Linear_rank_d(*this); }
+ Linearly_independent_d linearly_independent_d_object()const{ return Linearly_independent_d(*this); }
+ Midpoint_d midpoint_d_object()const{ return Midpoint_d(*this); }
+ Value_at_d value_at_d_object()const{ return Value_at_d(*this); }
+ /// Intersect_d intersect_d_object()const{ return Intersect_d(*this); }
+ Component_accessor_d component_accessor_d_object()const{ return Component_accessor_d(*this); }
+ Orthogonal_vector_d orthogonal_vector_d_object()const{ return Orthogonal_vector_d(*this); }
+ Construct_cartesian_const_iterator_d construct_cartesian_const_iterator_d_object()const{ return Construct_cartesian_const_iterator_d(*this); }
+ Construct_point_d construct_point_d_object()const{ return Construct_point_d(*this); }
+ Construct_vector_d construct_vector_d_object()const{ return Construct_vector_d(*this); }
+ Construct_segment_d construct_segment_d_object()const{ return Construct_segment_d(*this); }
+ Construct_sphere_d construct_sphere_d_object()const{ return Construct_sphere_d(*this); }
+ Construct_hyperplane_d construct_hyperplane_d_object()const{ return Construct_hyperplane_d(*this); }
+ Compute_squared_radius_d compute_squared_radius_d_object()const{ return Compute_squared_radius_d(*this); }
+ Squared_distance_d squared_distance_d_object()const{ return Squared_distance_d(*this); }
+ Squared_length_d squared_length_d_object()const{ return Squared_length_d(*this); }
+ Scalar_product_d scalar_product_d_object()const{ return Scalar_product_d(*this); }
+ Center_of_sphere_d center_of_sphere_d_object()const{ return Center_of_sphere_d(*this); }
+ Construct_circumcenter_d construct_circumcenter_d_object()const{ return Construct_circumcenter_d(*this); }
+ Construct_direction_d construct_direction_d_object()const{ return Construct_direction_d(*this); }
+ Construct_line_d construct_line_d_object()const{ return Construct_line_d(*this); }
+ Construct_ray_d construct_ray_d_object()const{ return Construct_ray_d(*this); }
+ Construct_iso_box_d construct_iso_box_d_object()const{ return Construct_iso_box_d(*this); }
+ Construct_aff_transformation_d construct_aff_transformation_d_object()const{ return Construct_aff_transformation_d(*this); }
+ Construct_min_vertex_d construct_min_vertex_d_object()const{ return Construct_min_vertex_d(*this); }
+ Construct_max_vertex_d construct_max_vertex_d_object()const{ return Construct_max_vertex_d(*this); }
+ Construct_weighted_point_d construct_weighted_point_d_object()const{ return Construct_weighted_point_d(*this); }
+
+ Compute_weight_d compute_weight_d_object()const{ return Compute_weight_d(*this); }
+ Point_drop_weight_d point_drop_weight_d_object()const{ return Point_drop_weight_d(*this); }
+
+ // Dummies for those required functors missing a concept.
+ typedef Null_functor Position_on_line_d;
+ Position_on_line_d position_on_line_d_object()const{return Null_functor();}
+ typedef Null_functor Barycentric_coordinates_d;
+ Barycentric_coordinates_d barycentric_coordinates_d_object()const{return Null_functor();}
+
+ /* Not provided because they don't make sense here:
+ Lift_to_paraboloid_d
+ Project_along_d_axis_d
+ */
+};
+}
+
+#endif // CGAL_KD_KERNEL_D_INTERFACE_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h b/include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h
new file mode 100644
index 00000000..99918ed2
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h
@@ -0,0 +1,134 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_KO_CONVERTER_H
+#define CGAL_KD_KO_CONVERTER_H
+#include <CGAL/NewKernel_d/utils.h>
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Kernel/mpl.h> // First_if_different
+#include <CGAL/Dimension.h>
+namespace CGAL {
+template <class Tag_, class K1, class K2> struct KO_converter;
+//TODO: It would probably be better if this was a Misc Functor in K1.
+// This way K1 could chose how it wants to present its points (sparse
+// iterator?) and derived classes would inherit it.
+
+namespace internal {
+template <class D /*=Dynamic_dimension_tag*/, class K1, class K2>
+struct Point_converter_help {
+ typedef typename Get_type<K1, Point_tag>::type argument_type;
+ typedef typename Get_type<K2, Point_tag>::type result_type;
+ template <class C>
+ result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& p) const {
+ typename Get_functor<K1, Construct_ttag<Point_cartesian_const_iterator_tag> >::type i(k1);
+ typename Get_functor<K2, Construct_ttag<Point_tag> >::type cp(k2);
+ return cp(conv(i(p,Begin_tag())),conv(i(p,End_tag())));
+ }
+};
+#ifdef CGAL_CXX11
+// This doesn't seem so useful, the compiler should be able to handle
+// the iterators just as efficiently.
+template <int d, class K1, class K2>
+struct Point_converter_help<Dimension_tag<d>,K1,K2> {
+ typedef typename Get_type<K1, Point_tag>::type argument_type;
+ typedef typename Get_type<K2, Point_tag>::type result_type;
+ template <class C,int...I>
+ result_type help(Indices<I...>, K1 const& k1, K2 const& k2, C const& conv, argument_type const& p) const {
+ typename Get_functor<K1, Compute_point_cartesian_coordinate_tag>::type cc(k1);
+ typename Get_functor<K2, Construct_ttag<Point_tag> >::type cp(k2);
+ return cp(conv(cc(p,I))...);
+ }
+ template <class C>
+ result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& p) const {
+ return help(typename N_increasing_indices<d>::type(),k1,k2,conv,p);
+ }
+};
+#endif
+}
+template <class K1, class K2> struct KO_converter<Point_tag,K1,K2>
+: internal::Point_converter_help<typename K1::Default_ambient_dimension,K1,K2>
+{};
+
+template <class K1, class K2> struct KO_converter<Vector_tag,K1,K2>{
+ typedef typename Get_type<K1, Vector_tag>::type K1_Vector;
+
+ // Disabling is now done in KernelD_converter
+ // // can't use vector without at least a placeholder point because of this
+ // typedef typename K1:: Point K1_Point;
+ // typedef typename First_if_different<K1_Vector,K1_Point>::Type argument_type;
+
+ typedef K1_Vector argument_type;
+ typedef typename Get_type<K2, Vector_tag>::type result_type;
+ template <class C>
+ result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& v) const {
+ typename Get_functor<K1, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type i(k1);
+ typename Get_functor<K2, Construct_ttag<Vector_tag> >::type cp(k2);
+ return cp(conv(i(v,Begin_tag())),conv(i(v,End_tag())));
+ }
+};
+
+template <class K1, class K2> struct KO_converter<Segment_tag,K1,K2>{
+ typedef typename Get_type<K1, Segment_tag>::type argument_type;
+ typedef typename Get_type<K2, Segment_tag>::type result_type;
+ template <class C>
+ result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& s) const {
+ typename Get_functor<K1, Segment_extremity_tag>::type f(k1);
+ typename Get_functor<K2, Construct_ttag<Segment_tag> >::type cs(k2);
+ return cs(conv(f(s,0)),conv(f(s,1)));
+ }
+};
+
+template <class K1, class K2> struct KO_converter<Hyperplane_tag,K1,K2>{
+ typedef typename Get_type<K1, Hyperplane_tag>::type argument_type;
+ typedef typename Get_type<K2, Hyperplane_tag>::type result_type;
+ template <class C>
+ result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& h) const {
+ typename Get_functor<K1, Orthogonal_vector_tag>::type ov(k1);
+ typename Get_functor<K1, Hyperplane_translation_tag>::type ht(k1);
+ typename Get_functor<K2, Construct_ttag<Hyperplane_tag> >::type ch(k2);
+ return ch(conv(ov(h)),conv(ht(h)));
+ }
+};
+
+template <class K1, class K2> struct KO_converter<Sphere_tag,K1,K2>{
+ typedef typename Get_type<K1, Sphere_tag>::type argument_type;
+ typedef typename Get_type<K2, Sphere_tag>::type result_type;
+ template <class C>
+ result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& s) const {
+ typename Get_functor<K1, Center_of_sphere_tag>::type cos(k1);
+ typename Get_functor<K1, Squared_radius_tag>::type sr(k1);
+ typename Get_functor<K2, Construct_ttag<Sphere_tag> >::type cs(k2);
+ return cs(conv(cos(s)),conv(sr(s)));
+ }
+};
+
+template <class K1, class K2> struct KO_converter<Weighted_point_tag,K1,K2>{
+ typedef typename Get_type<K1, Weighted_point_tag>::type argument_type;
+ typedef typename Get_type<K2, Weighted_point_tag>::type result_type;
+ template <class C>
+ result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& s) const {
+ typename Get_functor<K1, Point_drop_weight_tag>::type pdw(k1);
+ typename Get_functor<K1, Point_weight_tag>::type pw(k1);
+ typename Get_functor<K2, Construct_ttag<Weighted_point_tag> >::type cwp(k2);
+ return cwp(conv(pdw(s)),conv(pw(s)));
+ }
+};
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h b/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h
new file mode 100644
index 00000000..ddbdc37b
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h
@@ -0,0 +1,175 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_LA_EIGEN_H
+#define CGAL_LA_EIGEN_H
+#include <CGAL/config.h>
+#ifndef CGAL_EIGEN3_ENABLED
+#error Requires Eigen
+#endif
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <CGAL/Dimension.h>
+#include <Eigen/Dense>
+#include <CGAL/NewKernel_d/LA_eigen/constructors.h>
+#include <CGAL/iterator_from_indices.h>
+
+namespace CGAL {
+
+//FIXME: where could we use Matrix_base instead of Matrix?
+// Dim_ real dimension
+// Max_dim_ upper bound on the dimension
+template<class NT_,class Dim_,class Max_dim_=Dim_> struct LA_eigen {
+ typedef NT_ NT;
+ typedef Dim_ Dimension;
+ typedef Max_dim_ Max_dimension;
+ enum { dimension = Eigen_dimension<Dimension>::value };
+ enum { max_dimension = Eigen_dimension<Max_dimension>::value };
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef LA_eigen< NT, D2, D3 > Other;
+ };
+ template<class,class=void> struct Property : boost::false_type {};
+ template<class D> struct Property<Has_vector_plus_minus_tag,D> : boost::true_type {};
+ template<class D> struct Property<Has_vector_scalar_ops_tag,D> : boost::true_type {};
+ template<class D> struct Property<Has_dot_product_tag,D> : boost::true_type {};
+
+ typedef Eigen::Matrix<NT,Eigen_dimension<Dim_>::value,1,Eigen::ColMajor|Eigen::AutoAlign,Eigen_dimension<Max_dim_>::value,1> Vector;
+ typedef Eigen::Matrix<NT,Eigen::Dynamic,1> Dynamic_vector;
+ typedef Construct_eigen<Vector> Construct_vector;
+
+#if (EIGEN_WORLD_VERSION>=3)
+ typedef NT const* Vector_const_iterator;
+#else
+ typedef Iterator_from_indices<const type,const NT
+#ifndef CGAL_CXX11
+ ,NT
+#endif
+ > Vector_const_iterator;
+#endif
+
+ template<class Vec_>static Vector_const_iterator vector_begin(Vec_ const&a){
+#if (EIGEN_WORLD_VERSION>=3)
+ return &a[0];
+#else
+ return Vector_const_iterator(a,0);
+#endif
+ }
+
+ template<class Vec_>static Vector_const_iterator vector_end(Vec_ const&a){
+#if (EIGEN_WORLD_VERSION>=3)
+ // FIXME: Isn't that dangerous if a is an expression and not a concrete vector?
+ return &a[0]+a.size();
+#else
+ return Vector_const_iterator(a,a.size());
+#endif
+ }
+
+ typedef Eigen::Matrix<NT,dimension,dimension,Eigen::ColMajor|Eigen::AutoAlign,max_dimension,max_dimension> Square_matrix;
+ typedef Eigen::Matrix<NT,dimension,Eigen::Dynamic,Eigen::ColMajor|Eigen::AutoAlign,max_dimension,Eigen::Dynamic> Dynamic_matrix;
+ //TODO: don't pass on the values of Max_* for an expensive NT
+ // typedef ... Constructor
+ // typedef ... Accessor
+#if 0
+ private:
+ template <class T> class Canonicalize_vector {
+ typedef typename Dimension_eigen<T::SizeAtCompileTime>::type S1;
+ typedef typename Dimension_eigen<T::MaxSizeAtCompileTime>::type S2;
+ public:
+ typedef typename Vector<S1,S2>::type type;
+ };
+ public:
+#endif
+
+ template<class Vec_>static int size_of_vector(Vec_ const&v){
+ return (int)v.size();
+ }
+
+ template<class Vec_>static NT dot_product(Vec_ const&a,Vec_ const&b){
+ return a.dot(b);
+ }
+
+ template<class Vec_> static int rows(Vec_ const&v) {
+ return (int)v.rows();
+ }
+ template<class Vec_> static int columns(Vec_ const&v) {
+ return (int)v.cols();
+ }
+
+ template<class Mat_> static NT determinant(Mat_ const&m,bool=false){
+ return m.determinant();
+ }
+
+ template<class Mat_> static typename
+ Same_uncertainty_nt<CGAL::Sign, NT>::type
+ sign_of_determinant(Mat_ const&m,bool=false)
+ {
+ return CGAL::sign(m.determinant());
+ }
+
+ template<class Mat_> static int rank(Mat_ const&m){
+ // return m.rank();
+ // This one uses sqrt so cannot be used with Gmpq
+ // TODO: use different algo for different NT?
+ // Eigen::ColPivHouseholderQR<Mat_> decomp(m);
+ Eigen::FullPivLU<Mat_> decomp(m);
+ // decomp.setThreshold(0);
+ return static_cast<int>(decomp.rank());
+ }
+
+ // m*a==b
+ template<class DV, class DM, class V>
+ static void solve(DV&a, DM const&m, V const& b){
+ //a = m.colPivHouseholderQr().solve(b);
+ a = m.fullPivLu().solve(b);
+ }
+ template<class DV, class DM, class V>
+ static bool solve_and_check(DV&a, DM const&m, V const& b){
+ //a = m.colPivHouseholderQr().solve(b);
+ a = m.fullPivLu().solve(b);
+ return b.isApprox(m*a);
+ }
+
+ static Dynamic_matrix basis(Dynamic_matrix const&m){
+ return m.fullPivLu().image(m);
+ }
+
+ template<class Vec1,class Vec2> static Vector homogeneous_add(Vec1 const&a,Vec2 const&b){
+ //TODO: use compile-time size when available
+ int d=a.size();
+ Vector v(d);
+ v << b[d-1]*a.topRows(d-1)+a[d-1]*b.topRows(d-1), a[d-1]*b[d-1];
+ return v;
+ }
+
+ template<class Vec1,class Vec2> static Vector homogeneous_sub(Vec1 const&a,Vec2 const&b){
+ int d=a.size();
+ Vector v(d);
+ v << b[d-1]*a.topRows(d-1)-a[d-1]*b.topRows(d-1), a[d-1]*b[d-1];
+ return v;
+ }
+
+ template<class Vec1,class Vec2> static std::pair<NT,NT> homogeneous_dot_product(Vec1 const&a,Vec2 const&b){
+ int d=a.size();
+ return make_pair(a.topRows(d-1).dot(b.topRows(d-1)), a[d-1]*b[d-1]);
+ }
+
+};
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h b/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h
new file mode 100644
index 00000000..3636996f
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h
@@ -0,0 +1,162 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_LA_EIGEN_CONSTRUCTORS_H
+#define CGAL_LA_EIGEN_CONSTRUCTORS_H
+#include <CGAL/config.h>
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4003) // not enough actual parameters for macro 'BOOST_PP_EXPAND_I'
+ // http://lists.boost.org/boost-users/2014/11/83291.php
+#endif
+
+#ifndef CGAL_EIGEN3_ENABLED
+#error Requires Eigen
+#endif
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <CGAL/Dimension.h>
+#include <Eigen/Dense>
+#include <CGAL/iterator_from_indices.h>
+#include <CGAL/NewKernel_d/utils.h>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+
+namespace CGAL {
+ template <class Vector_> struct Construct_eigen {
+ typedef Vector_ result_type;
+ typedef typename Vector_::Scalar NT;
+
+ private:
+ static void check_dim(int CGAL_assertion_code(d)){
+ CGAL_assertion_code(int m = result_type::MaxSizeAtCompileTime;)
+ CGAL_assertion((m == Eigen::Dynamic) || (d <= m));
+ }
+ public:
+
+ struct Dimension {
+ // Initialize with NaN if possible?
+ result_type operator()(int d) const {
+ check_dim(d);
+ return result_type(d);
+ }
+ };
+
+ struct Iterator {
+ template<typename Iter>
+ result_type operator()(int d,Iter const& f,Iter const& e) const {
+ check_dim(d);
+ CGAL_assertion(d==std::distance(f,e));
+ result_type a(d);
+ // TODO: check the right way to do this
+ std::copy(f,e,&a[0]);
+ return a;
+ }
+ };
+
+#if 0
+ struct Iterator_add_one {
+ template<typename Iter>
+ result_type operator()(int d,Iter const& f,Iter const& e) const {
+ check_dim(d);
+ CGAL_assertion(d==std::distance(f,e)+1);
+ result_type a(d);
+ std::copy(f,e,&a[0]);
+ a[d-1]=1;
+ return a;
+ }
+ };
+#endif
+
+ struct Iterator_and_last {
+ template<typename Iter,typename T>
+ result_type operator()(int d,Iter const& f,Iter const& e,CGAL_FORWARDABLE(T) t) const {
+ check_dim(d);
+ CGAL_assertion(d==std::distance(f,e)+1);
+ result_type a(d);
+ std::copy(f,e,&a[0]);
+ a[d-1]=CGAL_FORWARD(T,t);
+ return a;
+ }
+ };
+
+#ifdef CGAL_CXX11
+ struct Initializer_list {
+ // Fix T==NT?
+ template<class T>
+ result_type operator()(std::initializer_list<T> l) const {
+ return Iterator()(l.size(),l.begin(),l.end());
+ }
+ };
+#endif
+
+ struct Values {
+#ifdef CGAL_CXX11
+ // TODO avoid going through Initializer_list which may cause extra copies. Possibly use forward_as_tuple.
+ template<class...U>
+ result_type operator()(U&&...u) const {
+ check_dim(sizeof...(U)); // TODO: use static_assert
+ return Initializer_list()({forward_safe<NT,U>(u)...});
+ }
+#else
+
+#define CGAL_CODE(Z,N,_) result_type operator()(BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \
+ check_dim(N); \
+ result_type a(N); \
+ a << BOOST_PP_ENUM_PARAMS(N,t); \
+ return a; \
+}
+BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ )
+#undef CGAL_CODE
+
+#endif
+ };
+
+ struct Values_divide {
+#ifdef CGAL_CXX11
+ template<class H,class...U>
+ result_type operator()(H const&h,U&&...u) const {
+ check_dim(sizeof...(U)); // TODO: use static_assert
+ return Initializer_list()({Rational_traits<NT>().make_rational(std::forward<U>(u),h)...});
+ }
+#else
+
+#define CGAL_VAR(Z,N,_) ( Rational_traits<NT>().make_rational( t##N ,h) )
+#define CGAL_CODE(Z,N,_) template <class H> result_type \
+ operator()(H const&h, BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \
+ check_dim(N); \
+ result_type a(N); \
+ a << BOOST_PP_ENUM(N,CGAL_VAR,); \
+ return a; \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ )
+#undef CGAL_CODE
+#undef CGAL_VAR
+
+#endif
+ };
+ };
+}
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h b/include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h
new file mode 100644
index 00000000..9ecc2b63
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h
@@ -0,0 +1,188 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_LAZY_CARTESIAN_H
+#define CGAL_KERNEL_D_LAZY_CARTESIAN_H
+
+#include <CGAL/basic.h>
+#include <CGAL/algorithm.h>
+#include <CGAL/Lazy.h>
+#include <CGAL/Default.h>
+#include <CGAL/NewKernel_d/Filtered_predicate2.h>
+#include <CGAL/iterator_from_indices.h>
+#include <CGAL/NewKernel_d/Define_kernel_types.h>
+
+namespace CGAL {
+
+template<class K,class T>
+struct Nth_iterator_element : private Store_kernel<K> {
+ Nth_iterator_element(){}
+ Nth_iterator_element(K const&k):Store_kernel<K>(k){}
+ typedef typename Get_type<K, typename iterator_tag_traits<T>::value_tag>::type result_type;
+ template<class U> result_type operator()(CGAL_FORWARDABLE(U) u, int i) const {
+ typename Get_functor<K, Construct_ttag<T> >::type ci(this->kernel());
+ return *cpp0x::next(ci(CGAL_FORWARD(U,u),Begin_tag()),i);
+ }
+};
+ //typedef typename Functor<typename iterator_tag_traits<T>::nth_element>::type nth_elem;
+template<class K, class T, bool = iterator_tag_traits<T>::has_nth_element>
+struct Select_nth_element_functor {
+ typedef Nth_iterator_element<K, T> type;
+};
+template<class K, class T>
+struct Select_nth_element_functor <K, T, true> :
+ Get_functor<K, typename iterator_tag_traits<T>::nth_element> {};
+
+namespace internal {
+ template<class A,class B,class C,bool/*is_NT=false*/>
+ struct Lazy_construction_maybe_nt {
+ typedef Lazy_construction<A,B,C> type;
+ };
+ template<class A,class B,class C>
+ struct Lazy_construction_maybe_nt<A,B,C,true> {
+ typedef Lazy_construction_nt<A,B,C> type;
+ };
+}
+
+template <class EK_, class AK_, class E2A_, class Kernel_>
+struct Lazy_cartesian_types
+{
+ typedef typename typeset_intersection<
+ typename AK_::Object_list,
+ typename EK_::Object_list
+ >::type Object_list;
+
+ typedef typename typeset_intersection<
+ typename AK_::Iterator_list,
+ typename EK_::Iterator_list
+ >::type Iterator_list;
+
+ template <class T,class=typename Get_type_category<Kernel_,T>::type> struct Type {};
+ template <class T> struct Type<T,Object_tag> {
+ typedef Lazy<
+ typename Get_type<AK_,T>::type,
+ typename Get_type<EK_,T>::type,
+ typename Get_type<EK_, FT_tag>::type,
+ E2A_> type;
+ };
+ template <class T> struct Type<T,Number_tag> {
+ typedef CGAL::Lazy_exact_nt<typename Get_type<EK_,T>::type> type;
+ };
+
+ template <class T> struct Iterator {
+ typedef typename iterator_tag_traits<T>::value_tag Vt;
+ typedef typename Type<Vt>::type V;
+ typedef typename Select_nth_element_functor<AK_,T>::type AF;
+ typedef typename Select_nth_element_functor<EK_,T>::type EF;
+
+ typedef typename internal::Lazy_construction_maybe_nt<
+ Kernel_, AF, EF, is_NT_tag<Vt>::value
+ >::type nth_elem;
+
+ typedef Iterator_from_indices<
+ const typename Type<typename iterator_tag_traits<T>::container>::type,
+ const V, V, nth_elem
+ > type;
+ };
+};
+
+template <class EK_, class AK_, class E2A_/*, class Kernel_=Default*/>
+struct Lazy_cartesian : Dimension_base<typename EK_::Default_ambient_dimension>,
+ Lazy_cartesian_types<EK_,AK_,E2A_,Lazy_cartesian<EK_,AK_,E2A_> >
+{
+ //CGAL_CONSTEXPR Lazy_cartesian(){}
+ //CGAL_CONSTEXPR Lazy_cartesian(int d):Base_(d){}
+
+ //TODO: Do we want to store an AK and an EK? Or just references?
+ //FIXME: references would be better I guess.
+ //TODO: In any case, make sure that we don't end up storing this kernel for
+ //nothing (it is not empty but references empty kernels or something)
+ AK_ ak; EK_ ek;
+ AK_ const& approximate_kernel()const{return ak;}
+ EK_ const& exact_kernel()const{return ek;}
+
+ typedef Lazy_cartesian Self;
+ typedef Lazy_cartesian_types<EK_,AK_,E2A_,Self> Base;
+ //typedef typename Default::Get<Kernel_,Self>::type Kernel;
+ typedef Self Kernel;
+ typedef AK_ Approximate_kernel;
+ typedef EK_ Exact_kernel;
+ typedef E2A_ E2A;
+ typedef Approx_converter<Kernel, Approximate_kernel> C2A;
+ typedef Exact_converter<Kernel, Exact_kernel> C2E;
+
+ typedef typename Exact_kernel::Rep_tag Rep_tag;
+ typedef typename Exact_kernel::Kernel_tag Kernel_tag;
+ typedef typename Exact_kernel::Default_ambient_dimension Default_ambient_dimension;
+ typedef typename Exact_kernel::Max_ambient_dimension Max_ambient_dimension;
+ //typedef typename Exact_kernel::Flat_orientation Flat_orientation;
+ // Check that Approximate_kernel agrees with all that...
+
+ template<class T,class D=void,class=typename Get_functor_category<Lazy_cartesian,T,D>::type> struct Functor {
+ typedef Null_functor type;
+ };
+ //FIXME: what do we do with D here?
+ template<class T,class D> struct Functor<T,D,Predicate_tag> {
+ typedef typename Get_functor<Approximate_kernel, T>::type FA;
+ typedef typename Get_functor<Exact_kernel, T>::type FE;
+ typedef Filtered_predicate2<FE,FA,C2E,C2A> type;
+ };
+ template<class T,class D> struct Functor<T,D,Compute_tag> {
+ typedef typename Get_functor<Approximate_kernel, T>::type FA;
+ typedef typename Get_functor<Exact_kernel, T>::type FE;
+ typedef Lazy_construction_nt<Kernel,FA,FE> type;
+ };
+ template<class T,class D> struct Functor<T,D,Construct_tag> {
+ typedef typename Get_functor<Approximate_kernel, T>::type FA;
+ typedef typename Get_functor<Exact_kernel, T>::type FE;
+ typedef Lazy_construction<Kernel,FA,FE> type;
+ };
+
+ //typedef typename Iterator<Point_cartesian_const_iterator_tag>::type Point_cartesian_const_iterator;
+ //typedef typename Iterator<Vector_cartesian_const_iterator_tag>::type Vector_cartesian_const_iterator;
+
+ template<class U>
+ struct Construct_iter : private Store_kernel<Kernel> {
+ Construct_iter(){}
+ Construct_iter(Kernel const&k):Store_kernel<Kernel>(k){}
+ //FIXME: pass the kernel to the functor in the iterator
+ typedef U result_type;
+ template<class T>
+ result_type operator()(T const& t,Begin_tag)const{
+ return result_type(t,0,this->kernel());
+ }
+ template<class T>
+ result_type operator()(T const& t,End_tag)const{
+ return result_type(t,Self().dimension(),this->kernel());
+ }
+ };
+ template<class T,class D> struct Functor<T,D,Construct_iterator_tag> {
+ typedef Construct_iter<typename Base::template Iterator<typename map_result_tag<T>::type>::type> type;
+ };
+
+
+ //TODO: what about other functors of the Misc category?
+ // for Point_dimension, we should apply it to the approximate point
+ // for printing, we should??? just not do printing this way?
+};
+
+
+} //namespace CGAL
+
+#endif // CGAL_KERNEL_D_LAZY_CARTESIAN_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h b/include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h
new file mode 100644
index 00000000..6d9f070f
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_TYPE_AFF_TRANSFORMATION_H
+#define CGAL_KD_TYPE_AFF_TRANSFORMATION_H
+#include <CGAL/config.h>
+#include <CGAL/NewKernel_d/store_kernel.h>
+#include <boost/preprocessor/repetition.hpp>
+
+// Dummy, that's all the Kernel_d concept requires, so a useful class will wait.
+
+namespace CGAL {
+template<class R_>
+struct Aff_transformation {
+ typedef R_ R;
+};
+namespace CartesianDKernelFunctors {
+template<class R_> struct Construct_aff_transformation {
+ CGAL_FUNCTOR_INIT_IGNORE(Construct_aff_transformation)
+ typedef R_ R;
+ typedef typename Get_type<R, Aff_transformation_tag>::type result_type;
+#ifdef CGAL_CXX11
+ template<class...T>
+ result_type operator()(T&&...)const{return result_type();}
+#else
+ result_type operator()()const{
+ return result_type();
+ }
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> \
+ result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const& BOOST_PP_INTERCEPT))const{ \
+ return result_type(); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1, 9, CGAL_CODE, _ )
+#undef CGAL_CODE
+
+#endif
+};
+}
+CGAL_KD_DEFAULT_TYPE(Aff_transformation_tag,(CGAL::Aff_transformation<K>),(),());
+CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Aff_transformation_tag>,(CartesianDKernelFunctors::Construct_aff_transformation<K>),(Aff_transformation_tag),());
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h b/include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h
new file mode 100644
index 00000000..14e35b01
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h
@@ -0,0 +1,159 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_TYPE_HYPERPLANE_H
+#define CGAL_KD_TYPE_HYPERPLANE_H
+#include <CGAL/enum.h>
+#include <CGAL/number_utils.h>
+#include <CGAL/NewKernel_d/store_kernel.h>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/iterator/counting_iterator.hpp>
+namespace CGAL {
+template <class R_> class Hyperplane {
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename Get_type<R_, Vector_tag>::type Vector_;
+ Vector_ v_;
+ FT_ s_;
+
+ public:
+ Hyperplane(Vector_ const&v, FT_ const&s): v_(v), s_(s) {}
+ // TODO: Add a piecewise constructor?
+
+ Vector_ const& orthogonal_vector()const{return v_;}
+ FT_ translation()const{return s_;}
+};
+namespace CartesianDKernelFunctors {
+template <class R_> struct Construct_hyperplane : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_hyperplane)
+ typedef typename Get_type<R_, Hyperplane_tag>::type result_type;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, Vector_tag>::type Vector;
+ typedef typename Get_type<R_, FT_tag>::type FT;
+ private:
+ struct One {
+ typedef int result_type;
+ template<class T>int const& operator()(T const&)const{
+ static const int one = 1;
+ return one;
+ }
+ };
+ public:
+
+ result_type operator()(Vector const&a, FT const&b)const{
+ return result_type(a,b);
+ }
+ // Not really needed
+ result_type operator()()const{
+ typename Get_functor<R_, Construct_ttag<Vector_tag> >::type cv(this->kernel());
+ return result_type(cv(),0);
+ }
+
+ template <class Iter>
+ result_type through(Iter f, Iter e)const{
+ typedef typename R_::LA LA;
+ typedef typename R_::Default_ambient_dimension D1;
+ typedef typename R_::Max_ambient_dimension D2;
+ typedef typename Increment_dimension<D1>::type D1i;
+ typedef typename Increment_dimension<D2>::type D2i;
+
+ typedef Eigen::Matrix<FT, Eigen_dimension<D1>::value, Eigen_dimension<D1i>::value,
+ Eigen::ColMajor|Eigen::AutoAlign, Eigen_dimension<D2>::value, Eigen_dimension<D2i>::value> Matrix;
+ typedef Eigen::Matrix<FT, Eigen_dimension<D1i>::value, 1,
+ Eigen::ColMajor|Eigen::AutoAlign, Eigen_dimension<D2i>::value, 1> Vec;
+ typename Get_functor<R_, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R_, Construct_ttag<Vector_tag> >::type cv(this->kernel());
+ typename Get_functor<R_, Point_dimension_tag>::type pd(this->kernel());
+
+ Point const& p0=*f;
+ int d = pd(p0);
+ Matrix m(d,d+1);
+ for(int j=0;j<d;++j)
+ m(0,j)=c(p0,j);
+ // Write the point coordinates in lines.
+ int i;
+ for (i=1; ++f!=e; ++i) {
+ Point const& p=*f;
+ for(int j=0;j<d;++j)
+ m(i,j)=c(p,j);
+ }
+ CGAL_assertion (i == d);
+ for(i=0;i<d;++i)
+ m(i,d)=-1;
+ Eigen::FullPivLU<Matrix> lu(m);
+ Vec res = lu.kernel().col(0);
+ return this->operator()(cv(d,LA::vector_begin(res),LA::vector_end(res)-1),res(d));
+ }
+ template <class Iter>
+ result_type operator()(Iter f, Iter e, Point const&p, CGAL::Oriented_side s=ON_ORIENTED_BOUNDARY)const{
+ result_type ret = through(f, e);
+ // I don't really like using ON_ORIENTED_BOUNDARY to mean that we don't care, we might as well not pass 'p' at all.
+ if (s == ON_ORIENTED_BOUNDARY)
+ return ret;
+ typename Get_functor<R_, Oriented_side_tag>::type os(this->kernel());
+ CGAL::Oriented_side o = os(ret, p);
+ if (o == ON_ORIENTED_BOUNDARY || o == s)
+ return ret;
+ typename Get_functor<R_, Opposite_vector_tag>::type ov(this->kernel());
+ typename Get_functor<R_, Construct_ttag<Vector_tag> >::type cv(this->kernel());
+ return this->operator()(ov(ret.orthogonal_vector()), -ret.translation());
+ }
+};
+template <class R_> struct Orthogonal_vector {
+ CGAL_FUNCTOR_INIT_IGNORE(Orthogonal_vector)
+ typedef typename Get_type<R_, Hyperplane_tag>::type Hyperplane;
+ typedef typename Get_type<R_, Vector_tag>::type const& result_type;
+ result_type operator()(Hyperplane const&s)const{
+ return s.orthogonal_vector();
+ }
+};
+template <class R_> struct Hyperplane_translation {
+ CGAL_FUNCTOR_INIT_IGNORE(Hyperplane_translation)
+ typedef typename Get_type<R_, Hyperplane_tag>::type Hyperplane;
+ typedef typename Get_type<R_, FT_tag>::type result_type;
+ // TODO: Is_exact?
+ result_type operator()(Hyperplane const&s)const{
+ return s.translation();
+ }
+};
+template <class R_> struct Value_at : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Value_at)
+ typedef typename Get_type<R_, Hyperplane_tag>::type Hyperplane;
+ typedef typename Get_type<R_, Vector_tag>::type Vector;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, FT_tag>::type FT;
+ typedef FT result_type;
+ typedef typename Get_functor<R_, Scalar_product_tag>::type Dot;
+ typedef typename Get_functor<R_, Point_to_vector_tag>::type P2V;
+ result_type operator()(Hyperplane const&h, Point const&p)const{
+ Dot dot(this->kernel());
+ P2V p2v(this->kernel());
+ return dot(h.orthogonal_vector(),p2v(p));
+ // Use Orthogonal_vector to make it generic?
+ // Copy the code from Scalar_product to avoid p2v?
+ }
+};
+}
+//TODO: Add a condition that the hyperplane type is the one from this file.
+CGAL_KD_DEFAULT_TYPE(Hyperplane_tag,(CGAL::Hyperplane<K>),(Vector_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Hyperplane_tag>,(CartesianDKernelFunctors::Construct_hyperplane<K>),(Vector_tag,Hyperplane_tag),(Opposite_vector_tag,Oriented_side_tag));
+CGAL_KD_DEFAULT_FUNCTOR(Orthogonal_vector_tag,(CartesianDKernelFunctors::Orthogonal_vector<K>),(Vector_tag,Hyperplane_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Hyperplane_translation_tag,(CartesianDKernelFunctors::Hyperplane_translation<K>),(Hyperplane_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Value_at_tag,(CartesianDKernelFunctors::Value_at<K>),(Point_tag,Vector_tag,Hyperplane_tag),(Scalar_product_tag,Point_to_vector_tag));
+} // namespace CGAL
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h b/include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h
new file mode 100644
index 00000000..d053f351
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNELD_TYPES_ISO_BOX_H
+#define CGAL_KERNELD_TYPES_ISO_BOX_H
+#include <utility>
+#include <CGAL/basic.h>
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Kernel/mpl.h>
+#include <CGAL/transforming_pair_iterator.h>
+namespace CGAL {
+template <class R_> class Iso_box {
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ typedef std::pair<Point_,Point_> Data_;
+ Data_ data;
+ public:
+ Iso_box(){}
+ Iso_box(Point_ const&a, Point_ const&b): data(a,b) {}
+ Point_ min BOOST_PREVENT_MACRO_SUBSTITUTION ()const{
+ return data.first;
+ }
+ Point_ max BOOST_PREVENT_MACRO_SUBSTITUTION ()const{
+ return data.second;
+ }
+};
+namespace CartesianDKernelFunctors {
+ template <class R_> struct Construct_iso_box : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_iso_box)
+ typedef typename Get_type<R_, Iso_box_tag>::type result_type;
+ typedef typename Get_type<R_, RT_tag>::type RT;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_functor<R_, Construct_ttag<Point_tag> >::type Cp_;
+ typedef typename Get_functor<R_, Construct_ttag<Point_cartesian_const_iterator_tag> >::type Ci_;
+ result_type operator()(Point const&a, Point const&b)const{
+ Cp_ cp(this->kernel());
+ Ci_ ci(this->kernel());
+ return result_type(cp(
+ make_transforming_pair_iterator(ci(a,Begin_tag()), ci(b,Begin_tag()), Min<RT>()),
+ make_transforming_pair_iterator(ci(a,End_tag()), ci(b,End_tag()), Min<RT>())),
+ cp(
+ make_transforming_pair_iterator(ci(a,Begin_tag()), ci(b,Begin_tag()), Max<RT>()),
+ make_transforming_pair_iterator(ci(a,End_tag()), ci(b,End_tag()), Max<RT>())));
+ }
+ };
+
+ template <class R_> struct Construct_min_vertex {
+ CGAL_FUNCTOR_INIT_IGNORE(Construct_min_vertex)
+ typedef typename Get_type<R_, Iso_box_tag>::type argument_type;
+ //TODO: make result_type a reference
+ typedef typename Get_type<R_, Point_tag>::type result_type;
+ result_type operator()(argument_type const&b)const{
+ return b.min BOOST_PREVENT_MACRO_SUBSTITUTION ();
+ }
+ };
+ template <class R_> struct Construct_max_vertex {
+ CGAL_FUNCTOR_INIT_IGNORE(Construct_max_vertex)
+ typedef typename Get_type<R_, Iso_box_tag>::type argument_type;
+ typedef typename Get_type<R_, Point_tag>::type result_type;
+ result_type operator()(argument_type const&b)const{
+ return b.max BOOST_PREVENT_MACRO_SUBSTITUTION ();
+ }
+ };
+}
+//TODO (other types as well) only enable these functors if the Iso_box type is the one defined in this file...
+CGAL_KD_DEFAULT_TYPE(Iso_box_tag,(CGAL::Iso_box<K>),(Point_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Iso_box_tag>,(CartesianDKernelFunctors::Construct_iso_box<K>),(Iso_box_tag,Point_tag),(Construct_ttag<Point_cartesian_const_iterator_tag>,Construct_ttag<Point_tag>));
+CGAL_KD_DEFAULT_FUNCTOR(Construct_min_vertex_tag,(CartesianDKernelFunctors::Construct_min_vertex<K>),(Iso_box_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Construct_max_vertex_tag,(CartesianDKernelFunctors::Construct_max_vertex<K>),(Iso_box_tag),());
+} // namespace CGAL
+
+#endif // CGAL_KERNELD_TYPES_ISO_BOX_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h b/include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h
new file mode 100644
index 00000000..6a09571c
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNELD_TYPES_LINE_H
+#define CGAL_KERNELD_TYPES_LINE_H
+#include <utility>
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Kernel/mpl.h>
+namespace CGAL {
+template <class R_> class Line {
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ typedef std::pair<Point_,Point_> Data_;
+ Data_ data;
+ public:
+ Line(){}
+ Line(Point_ const&a, Point_ const&b): data(a,b) {}
+ Point_ point(int i)const{
+ if(i==0) return data.first;
+ if(i==1) return data.second;
+ throw "not implemented";
+ }
+ Line opposite()const{
+ return Line(data.second,data.first);
+ }
+};
+namespace CartesianDKernelFunctors {
+ template <class R_> struct Construct_line : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_line)
+ typedef typename Get_type<R_, Line_tag>::type result_type;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, Vector_tag>::type Vector;
+ typedef typename Get_functor<R_, Translated_point_tag>::type Tp_;
+ //typedef typename Get_functor<R_, Difference_of_points_tag>::type Dp_;
+ //typedef typename Get_functor<R_, Scaled_vector_tag>::type Sv_;
+ result_type operator()(Point const&a, Point const&b)const{
+ return result_type(a,b);
+ }
+ result_type operator()(Point const&a, typename First_if_different<Vector,Point>::Type const&b)const{
+ Tp_ tp(this->kernel());
+ return result_type(a,tp(a,b));
+ }
+ };
+}
+CGAL_KD_DEFAULT_TYPE(Line_tag,(CGAL::Line<K>),(Point_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Line_tag>,(CartesianDKernelFunctors::Construct_line<K>),(Line_tag,Point_tag,Vector_tag),(Translated_point_tag));
+
+} // namespace CGAL
+
+#endif // CGAL_KERNELD_TYPES_LINE_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h b/include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h
new file mode 100644
index 00000000..be845e76
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNELD_TYPES_RAY_H
+#define CGAL_KERNELD_TYPES_RAY_H
+#include <utility>
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Kernel/mpl.h>
+namespace CGAL {
+template <class R_> class Ray {
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ typedef typename Get_type<R_, Vector_tag>::type Vector_;
+ typedef std::pair<Point_,Vector_> Data_;
+ Data_ data;
+ public:
+ Ray(){}
+ Ray(Point_ const&a, Vector_ const&b): data(a,b) {}
+ Point_ source()const{
+ return data.first;
+ }
+ // FIXME: return a R_::Direction?
+ Vector_ direction()const{
+ return data.second;
+ }
+};
+namespace CartesianDKernelFunctors {
+ template <class R_> struct Construct_ray : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_ray)
+ typedef typename Get_type<R_, Ray_tag>::type result_type;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, Vector_tag>::type Vector;
+ typedef typename Get_functor<R_, Difference_of_points_tag>::type Dp_;
+ //typedef typename Get_functor<R_, Translated_point_tag>::type Tp_;
+ //typedef typename Get_functor<R_, Scaled_vector_tag>::type Sv_;
+ result_type operator()(Point const&a, Vector const&b)const{
+ return result_type(a,b);
+ }
+ result_type operator()(Point const&a, typename First_if_different<Point,Vector>::Type const&b)const{
+ Dp_ dp(this->kernel());
+ return result_type(a,dp(b,a));
+ }
+ };
+}
+CGAL_KD_DEFAULT_TYPE(Ray_tag,(CGAL::Ray<K>),(Point_tag,Vector_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Ray_tag>,(CartesianDKernelFunctors::Construct_ray<K>),(Point_tag,Ray_tag,Vector_tag),(Difference_of_points_tag));
+
+} // namespace CGAL
+
+#endif // CGAL_KERNELD_TYPES_RAY_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h b/include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h
new file mode 100644
index 00000000..38361c2b
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h
@@ -0,0 +1,121 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNELD_SEGMENTD_H
+#define CGAL_KERNELD_SEGMENTD_H
+#include <CGAL/config.h>
+#include <utility>
+#include <CGAL/NewKernel_d/functor_tags.h>
+namespace CGAL {
+template <class R_> class Segment {
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ //typedef typename R_::Vector Vector_;
+ //typedef typename Get_functor<R_, Construct_ttag<Vector_tag> >::type Cv_;
+// typedef typename R_::Squared_distance Csd_;
+ typedef std::pair<Point_,Point_> Data_;
+ Data_ data;
+ public:
+ //typedef Segmentd<R_> Segment;
+#ifdef CGAL_CXX11
+ //FIXME: don't forward directly, piecewise_constuct should call the point construction functor (I guess? or is it unnecessary?)
+ template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Segment>>::value>::type>
+ Segment(U&&...u):data(std::forward<U>(u)...){}
+#else
+ Segment(){}
+ Segment(Point_ const&a, Point_ const&b): data(a,b) {}
+ //template<class A,class T1,class T2>
+ //Segment(A const&,T1 const&t1,T2 const&t2)
+#endif
+ Point_ source()const{return data.first;}
+ Point_ target()const{return data.second;}
+ Point_ operator[](int i)const{
+ if((i%2)==0)
+ return source();
+ else
+ return target();
+ }
+ Segment opposite()const{
+ return Segment(target(),source());
+ }
+ //Vector_ vector()const{
+ // return Cv_()(data.first,data.second);
+ //}
+// FT_ squared_length()const{
+// return Csd_()(data.first,data.second);
+// }
+};
+
+namespace CartesianDKernelFunctors {
+
+template<class R_> struct Construct_segment : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_segment)
+ typedef R_ R;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, Segment_tag>::type Segment;
+ typedef typename Get_functor<R_, Construct_ttag<Point_tag> >::type CP;
+ typedef Segment result_type;
+ result_type operator()(Point const&a, Point const&b)const{
+ return result_type(a,b);
+ }
+ // Not really needed, especially since it forces us to store the kernel
+ result_type operator()()const{
+ Point p = typename Get_functor<R_, Construct_ttag<Point_tag> >::type (this->kernel()) ();
+ return result_type (p, p);
+ }
+ // T should only be std::piecewise_construct_t, but we shouldn't fail if it doesn't exist.
+ template<class T,class U,class V>
+ result_type operator()(CGAL_FORWARDABLE(T),CGAL_FORWARDABLE(U) u,CGAL_FORWARDABLE(V) v)const{
+ CP cp(this->kernel());
+ result_type r = {{
+ call_on_tuple_elements<Point>(cp, CGAL_FORWARD(U,u)),
+ call_on_tuple_elements<Point>(cp, CGAL_FORWARD(V,v)) }};
+ return r;
+ }
+};
+
+// This should be part of Construct_point, according to Kernel_23 conventions
+template<class R_> struct Segment_extremity {
+ CGAL_FUNCTOR_INIT_IGNORE(Segment_extremity)
+ typedef R_ R;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, Segment_tag>::type Segment;
+ typedef Point result_type;
+ result_type operator()(Segment const&s, int i)const{
+ if(i==0) return s.source();
+ CGAL_assertion(i==1);
+ return s.target();
+ }
+#ifdef CGAL_CXX11
+ result_type operator()(Segment &&s, int i)const{
+ if(i==0) return std::move(s.source());
+ CGAL_assertion(i==1);
+ return std::move(s.target());
+ }
+#endif
+};
+} // CartesianDKernelFunctors
+
+CGAL_KD_DEFAULT_TYPE(Segment_tag,(CGAL::Segment<K>),(Point_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Segment_tag>,(CartesianDKernelFunctors::Construct_segment<K>),(Segment_tag,Point_tag),(Construct_ttag<Point_tag>));
+CGAL_KD_DEFAULT_FUNCTOR(Segment_extremity_tag,(CartesianDKernelFunctors::Segment_extremity<K>),(Segment_tag,Point_tag),());
+
+} // namespace CGAL
+
+#endif // CGAL_KERNELD_SEGMENTD_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h b/include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h
new file mode 100644
index 00000000..114410b4
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h
@@ -0,0 +1,132 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_TYPE_SPHERE_H
+#define CGAL_KD_TYPE_SPHERE_H
+#include <CGAL/NewKernel_d/store_kernel.h>
+#include <boost/iterator/counting_iterator.hpp>
+namespace CGAL {
+template <class R_> class Sphere {
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ Point_ c_;
+ FT_ r2_;
+
+ public:
+ Sphere(Point_ const&p, FT_ const&r2): c_(p), r2_(r2) {}
+ // TODO: Add a piecewise constructor?
+
+ Point_ const& center()const{return c_;}
+ FT_ const& squared_radius()const{return r2_;}
+};
+
+namespace CartesianDKernelFunctors {
+template <class R_> struct Construct_sphere : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_sphere)
+ typedef typename Get_type<R_, Sphere_tag>::type result_type;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, FT_tag>::type FT;
+ result_type operator()(Point const&a, FT const&b)const{
+ return result_type(a,b);
+ }
+ // Not really needed
+ result_type operator()()const{
+ typename Get_functor<R_, Construct_ttag<Point_tag> >::type cp(this->kernel());
+ return result_type(cp(),0);
+ }
+ template <class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ typename Get_functor<R_, Construct_circumcenter_tag>::type cc(this->kernel());
+ typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel());
+
+ // It should be possible to avoid copying the center by moving this code to a constructor.
+ Point center = cc(f, e);
+ FT const& r2 = sd(center, *f);
+ return this->operator()(CGAL_MOVE(center), r2);
+ }
+};
+
+template <class R_> struct Center_of_sphere : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Center_of_sphere)
+ typedef typename Get_type<R_, Sphere_tag>::type Sphere;
+ // No reference because of the second overload
+ typedef typename Get_type<R_, Point_tag>::type result_type;
+
+ result_type const& operator()(Sphere const&s)const{
+ return s.center();
+ }
+
+ template<class Iter>
+ result_type operator()(Iter b, Iter e)const{
+ typename Get_functor<R_, Construct_ttag<Sphere_tag> >::type cs(this->kernel());
+ return operator()(cs(b,e)); // computes the radius needlessly
+ }
+};
+
+template <class R_> struct Squared_radius {
+ CGAL_FUNCTOR_INIT_IGNORE(Squared_radius)
+ typedef typename Get_type<R_, Sphere_tag>::type Sphere;
+ typedef typename Get_type<R_, FT_tag>::type const& result_type;
+ // TODO: Is_exact?
+ result_type operator()(Sphere const&s)const{
+ return s.squared_radius();
+ }
+};
+
+// FIXME: Move it to the generic functors, using the two above and conditional to the existence of sqrt(FT)
+template<class R_> struct Point_of_sphere : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Point_of_sphere)
+ typedef R_ R;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Sphere_tag>::type Sphere;
+ typedef typename Get_functor<R, Construct_ttag<Point_tag> >::type CP;
+ typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI;
+ typedef typename Get_functor<R, Point_dimension_tag>::type PD;
+ typedef Point result_type;
+ typedef Sphere first_argument_type;
+ typedef int second_argument_type;
+ struct Trans : std::binary_function<FT,int,FT> {
+ FT const& r_; int idx; bool sgn;
+ Trans (int n, FT const& r, bool b) : r_(r), idx(n), sgn(b) {}
+ FT operator()(FT const&x, int i)const{
+ return (i == idx) ? sgn ? x + r_ : x - r_ : x;
+ }
+ };
+ result_type operator()(Sphere const&s, int i)const{
+ CI ci(this->kernel());
+ PD pd(this->kernel());
+ typedef boost::counting_iterator<int,std::random_access_iterator_tag> Count;
+ Point const&c = s.center();
+ int d=pd(c);
+ bool last = (i == d);
+ FT r = sqrt(s.squared_radius());
+ Trans t(last ? 0 : i, r, !last);
+ return CP(this->kernel())(make_transforming_pair_iterator(ci(c,Begin_tag()),Count(0),t),make_transforming_pair_iterator(ci(c,End_tag()),Count(d),t));
+ }
+};
+}
+CGAL_KD_DEFAULT_TYPE(Sphere_tag,(CGAL::Sphere<K>),(Point_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Sphere_tag>,(CartesianDKernelFunctors::Construct_sphere<K>),(Sphere_tag,Point_tag),(Construct_ttag<Point_tag>,Compute_point_cartesian_coordinate_tag,Squared_distance_tag,Squared_distance_to_origin_tag,Point_dimension_tag));
+CGAL_KD_DEFAULT_FUNCTOR(Center_of_sphere_tag,(CartesianDKernelFunctors::Center_of_sphere<K>),(Sphere_tag,Point_tag),(Construct_ttag<Sphere_tag>));
+CGAL_KD_DEFAULT_FUNCTOR(Squared_radius_tag,(CartesianDKernelFunctors::Squared_radius<K>),(Sphere_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Point_of_sphere_tag,(CartesianDKernelFunctors::Point_of_sphere<K>),(Sphere_tag,Point_tag),(Construct_ttag<Point_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>));
+} // namespace CGAL
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h b/include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h
new file mode 100644
index 00000000..1caf8701
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h
@@ -0,0 +1,205 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_TYPE_WP_H
+#define CGAL_KD_TYPE_WP_H
+#include <CGAL/NewKernel_d/store_kernel.h>
+#include <boost/iterator/counting_iterator.hpp>
+namespace CGAL {
+namespace KerD {
+template <class R_> class Weighted_point {
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ Point_ c_;
+ FT_ w_;
+
+ public:
+ Weighted_point(Point_ const&p, FT_ const&w): c_(p), w_(w) {}
+ // TODO: Add a piecewise constructor?
+
+ Point_ const& point()const{return c_;}
+ FT_ const& weight()const{return w_;}
+};
+}
+
+namespace CartesianDKernelFunctors {
+template <class R_> struct Construct_weighted_point : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_weighted_point)
+ typedef typename Get_type<R_, Weighted_point_tag>::type result_type;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, FT_tag>::type FT;
+ result_type operator()(Point const&a, FT const&b)const{
+ return result_type(a,b);
+ }
+ // Not really needed
+ result_type operator()()const{
+ typename Get_functor<R_, Construct_ttag<Point_tag> >::type cp(this->kernel());
+ return result_type(cp(),0);
+ }
+};
+
+template <class R_> struct Point_drop_weight {
+ CGAL_FUNCTOR_INIT_IGNORE(Point_drop_weight)
+ typedef typename Get_type<R_, Weighted_point_tag>::type argument_type;
+ typedef typename Get_type<R_, Point_tag>::type const& result_type;
+ // Returning a reference is fragile
+
+ result_type operator()(argument_type const&s)const{
+ return s.point();
+ }
+};
+
+template <class R_> struct Point_weight {
+ CGAL_FUNCTOR_INIT_IGNORE(Point_weight)
+ typedef typename Get_type<R_, Weighted_point_tag>::type argument_type;
+ typedef typename Get_type<R_, FT_tag>::type result_type;
+
+ result_type operator()(argument_type const&s)const{
+ return s.weight();
+ }
+};
+
+template <class R_> struct Power_distance : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Power_distance)
+ typedef typename Get_type<R_, Weighted_point_tag>::type first_argument_type;
+ typedef first_argument_type second_argument_type;
+ typedef typename Get_type<R_, FT_tag>::type result_type;
+
+ result_type operator()(first_argument_type const&a, second_argument_type const&b)const{
+ typename Get_functor<R_, Point_drop_weight_tag>::type pdw(this->kernel());
+ typename Get_functor<R_, Point_weight_tag>::type pw(this->kernel());
+ typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel());
+ return sd(pdw(a),pdw(b))-pw(a)-pw(b);
+ }
+};
+template <class R_> struct Power_distance_to_point : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Power_distance_to_point)
+ typedef typename Get_type<R_, Weighted_point_tag>::type first_argument_type;
+ typedef typename Get_type<R_, Point_tag>::type second_argument_type;
+ typedef typename Get_type<R_, FT_tag>::type result_type;
+
+ result_type operator()(first_argument_type const&a, second_argument_type const&b)const{
+ typename Get_functor<R_, Point_drop_weight_tag>::type pdw(this->kernel());
+ typename Get_functor<R_, Point_weight_tag>::type pw(this->kernel());
+ typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel());
+ return sd(pdw(a),b)-pw(a);
+ }
+};
+
+template<class R_> struct Power_side_of_power_sphere : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere)
+ typedef R_ R;
+ typedef typename Get_type<R, Oriented_side_tag>::type result_type;
+
+ template<class Iter, class Pt>
+ result_type operator()(Iter const& f, Iter const& e, Pt const& p0) const {
+ typename Get_functor<R, Power_side_of_power_sphere_raw_tag>::type ptr(this->kernel());
+ typename Get_functor<R, Point_drop_weight_tag>::type pdw(this->kernel());
+ typename Get_functor<R, Point_weight_tag>::type pw(this->kernel());
+ return ptr (
+ make_transforming_iterator (f, pdw),
+ make_transforming_iterator (e, pdw),
+ make_transforming_iterator (f, pw),
+ pdw (p0),
+ pw (p0));
+ }
+};
+
+template<class R_> struct In_flat_power_side_of_power_sphere : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(In_flat_power_side_of_power_sphere)
+ typedef R_ R;
+ typedef typename Get_type<R, Oriented_side_tag>::type result_type;
+
+ template<class Fo, class Iter, class Pt>
+ result_type operator()(Fo const& fo, Iter const& f, Iter const& e, Pt const& p0) const {
+ typename Get_functor<R, In_flat_power_side_of_power_sphere_raw_tag>::type ptr(this->kernel());
+ typename Get_functor<R, Point_drop_weight_tag>::type pdw(this->kernel());
+ typename Get_functor<R, Point_weight_tag>::type pw(this->kernel());
+ return ptr (
+ fo,
+ make_transforming_iterator (f, pdw),
+ make_transforming_iterator (e, pdw),
+ make_transforming_iterator (f, pw),
+ pdw (p0),
+ pw (p0));
+ }
+};
+
+// Construct a point at (weighted) distance 0 from all the input
+template <class R_> struct Power_center : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Power_center)
+ typedef typename Get_type<R_, Weighted_point_tag>::type WPoint;
+ typedef WPoint result_type;
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename Get_type<R_, FT_tag>::type FT;
+ template <class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ // 2*(x-y).c == (x^2-wx^2)-(y^2-wy^2)
+ typedef typename R_::LA LA;
+ typedef typename LA::Square_matrix Matrix;
+ typedef typename LA::Vector Vec;
+ typedef typename LA::Construct_vector CVec;
+ typename Get_functor<R_, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R_, Construct_ttag<Point_tag> >::type cp(this->kernel());
+ typename Get_functor<R_, Point_dimension_tag>::type pd(this->kernel());
+ typename Get_functor<R_, Squared_distance_to_origin_tag>::type sdo(this->kernel());
+ typename Get_functor<R_, Power_distance_to_point_tag>::type pdp(this->kernel());
+ typename Get_functor<R_, Point_drop_weight_tag>::type pdw(this->kernel());
+ typename Get_functor<R_, Point_weight_tag>::type pw(this->kernel());
+ typename Get_functor<R_, Construct_ttag<Weighted_point_tag> >::type cwp(this->kernel());
+
+ WPoint const& wp0 = *f;
+ Point const& p0 = pdw(wp0);
+ int d = pd(p0);
+ FT const& n0 = sdo(p0) - pw(wp0);
+ Matrix m(d,d);
+ Vec b = typename CVec::Dimension()(d);
+ // Write the point coordinates in lines.
+ int i;
+ for(i=0; ++f!=e; ++i) {
+ WPoint const& wp=*f;
+ Point const& p=pdw(wp);
+ FT const& np = sdo(p) - pw(wp);
+ for(int j=0;j<d;++j) {
+ m(i,j)=2*(c(p,j)-c(p0,j));
+ b[i] = np - n0;
+ }
+ }
+ CGAL_assertion (i == d);
+ Vec res = typename CVec::Dimension()(d);;
+ //std::cout << "Mat: " << m << "\n Vec: " << one << std::endl;
+ LA::solve(res, CGAL_MOVE(m), CGAL_MOVE(b));
+ //std::cout << "Sol: " << res << std::endl;
+ Point center = cp(d,LA::vector_begin(res),LA::vector_end(res));
+ FT const& r2 = pdp (wp0, center);
+ return cwp(CGAL_MOVE(center), r2);
+ }
+};
+}
+CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::KerD::Weighted_point<K>),(Point_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Weighted_point_tag>,(CartesianDKernelFunctors::Construct_weighted_point<K>),(Weighted_point_tag,Point_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_drop_weight<K>),(Weighted_point_tag,Point_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight<K>),(Weighted_point_tag,Point_tag),());
+CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_power_sphere_tag,(CartesianDKernelFunctors::Power_side_of_power_sphere<K>),(Weighted_point_tag),(Power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag));
+CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_tag,(CartesianDKernelFunctors::In_flat_power_side_of_power_sphere<K>),(Weighted_point_tag),(In_flat_power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag));
+CGAL_KD_DEFAULT_FUNCTOR(Power_distance_tag,(CartesianDKernelFunctors::Power_distance<K>),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag));
+CGAL_KD_DEFAULT_FUNCTOR(Power_distance_to_point_tag,(CartesianDKernelFunctors::Power_distance_to_point<K>),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag));
+CGAL_KD_DEFAULT_FUNCTOR(Power_center_tag,(CartesianDKernelFunctors::Power_center<K>),(Weighted_point_tag,Point_tag),(Compute_point_cartesian_coordinate_tag,Construct_ttag<Point_tag>,Construct_ttag<Weighted_point_tag>,Point_dimension_tag,Squared_distance_to_origin_tag,Point_drop_weight_tag,Point_weight_tag,Power_distance_to_point_tag));
+} // namespace CGAL
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h
new file mode 100644
index 00000000..0ad9bb36
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h
@@ -0,0 +1,165 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_ARRAY_H
+#define CGAL_VECTOR_ARRAY_H
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <CGAL/Dimension.h>
+#include <CGAL/NewKernel_d/utils.h>
+#include <CGAL/array.h>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+
+#include <CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h>
+#include <CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h>
+#include <CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h>
+#include <CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h>
+#include <CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h>
+
+
+
+namespace CGAL {
+
+// May not be safe to use with dim!=max_dim.
+// In that case, we should store the real dim next to the array.
+template<class NT_,class Dim_,class Max_dim_=Dim_> struct Array_vector {
+ typedef NT_ NT;
+ typedef Dim_ Dimension;
+ typedef Max_dim_ Max_dimension;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef Array_vector< NT, D2, D3 > Other;
+ };
+ template<class> struct Property : boost::false_type {};
+
+ static const unsigned d_=Max_dim_::value;
+ CGAL_static_assertion(d_ != (unsigned)UNKNOWN_DIMENSION);
+
+ typedef cpp0x::array<NT,d_> Vector;
+ struct Construct_vector {
+ struct Dimension {
+ // Initialize with NaN if possible?
+ Vector operator()(unsigned CGAL_assertion_code(d)) const {
+ CGAL_assertion(d<=d_);
+ return Vector();
+ }
+ };
+
+ struct Iterator {
+ template<typename Iter>
+ Vector operator()(unsigned CGAL_assertion_code(d),Iter const& f,Iter const& e) const {
+ CGAL_assertion(d==(unsigned) std::distance(f,e));
+ CGAL_assertion(d<=d_);
+ //TODO: optimize for forward iterators
+ Vector a;
+ std::copy(f,e,a.begin());
+ return a;
+ }
+ };
+
+#if 0
+ struct Iterator_add_one {
+ template<typename Iter>
+ Vector operator()(unsigned d,Iter const& f,Iter const& e) const {
+ CGAL_assertion(d==std::distance(f,e)+1);
+ CGAL_assertion(d<=d_);
+ //TODO: optimize
+ Vector a;
+ std::copy(f,e,a.begin());
+ a.back()=1;
+ return a;
+ }
+ };
+#endif
+
+ struct Iterator_and_last {
+ template<typename Iter,typename T>
+ Vector operator()(unsigned CGAL_assertion_code(d),Iter const& f,Iter const& e,CGAL_FORWARDABLE(T) t) const {
+ CGAL_assertion(d==std::distance(f,e)+1);
+ CGAL_assertion(d<=d_);
+ //TODO: optimize for forward iterators
+ Vector a;
+ std::copy(f,e,a.begin());
+ a.back()=CGAL_FORWARD(T,t);
+ return a;
+ }
+ };
+
+ struct Values {
+#ifdef CGAL_CXX11
+ template<class...U>
+ Vector operator()(U&&...u) const {
+ static_assert(sizeof...(U)<=d_,"too many arguments");
+ Vector a={{forward_safe<NT,U>(u)...}};
+ return a;
+ }
+#else
+
+#define CGAL_CODE(Z,N,_) Vector operator()(BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \
+ CGAL_assertion(N<=d_); \
+ Vector a={{BOOST_PP_ENUM_PARAMS(N,t)}}; \
+ return a; \
+}
+BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ )
+#undef CGAL_CODE
+
+#endif
+ };
+
+ struct Values_divide {
+#ifdef CGAL_CXX11
+ template<class H,class...U>
+ Vector operator()(H const& h,U&&...u) const {
+ static_assert(sizeof...(U)<=d_,"too many arguments");
+ Vector a={{Rational_traits<NT>().make_rational(std::forward<U>(u),h)...}};
+ return a;
+ }
+#else
+
+#define CGAL_VAR(Z,N,_) Rational_traits<NT>().make_rational( t##N , h)
+#define CGAL_CODE(Z,N,_) template <class H> Vector \
+ operator()(H const&h, BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \
+ CGAL_assertion(N<=d_); \
+ Vector a={{BOOST_PP_ENUM(N,CGAL_VAR,_)}}; \
+ return a; \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ )
+#undef CGAL_CODE
+#undef CGAL_VAR
+
+#endif
+ };
+ };
+
+ typedef NT const* Vector_const_iterator;
+ static Vector_const_iterator vector_begin(Vector const&a){
+ return &a[0];
+ }
+ static Vector_const_iterator vector_end(Vector const&a){
+ return &a[0]+d_; // Don't know the real size
+ }
+ static unsigned size_of_vector(Vector const&){
+ return d_; // Don't know the real size
+ }
+
+};
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h
new file mode 100644
index 00000000..954a3c1b
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h
@@ -0,0 +1,213 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_AVX4_H
+#define CGAL_VECTOR_AVX4_H
+
+#if !defined __AVX__ || (__GNUC__ * 100 + __GNUC_MINOR__ < 408)
+#error Requires AVX and gcc 4.8+
+#endif
+#include <x86intrin.h>
+
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/enum.h> // CGAL::Sign
+#include <CGAL/number_utils.h> // CGAL::sign
+
+
+
+namespace CGAL {
+
+ struct Avx_vector_4 {
+ typedef double NT;
+ typedef Dimension_tag<4> Dimension;
+ typedef Dimension_tag<4> Max_dimension;
+ // No Rebind_dimension, this is a building block
+ template<class,bool=true> struct Property : boost::false_type {};
+ template<bool b> struct Property<Has_vector_plus_minus_tag,b>
+ : boost::true_type {};
+ /* MAYBE?
+ template<bool b> struct Property<Has_vector_scalar_ops_tag,b>
+ : boost::true_type {};
+ */
+ template<bool b> struct Property<Has_determinant_of_vectors_tag,b>
+ : boost::true_type {};
+ template<bool b> struct Property<Has_dot_product_tag,b>
+ : boost::true_type {};
+ template<bool b> struct Property<Has_determinant_of_vectors_omit_last_tag,b>
+ : boost::true_type {};
+
+ typedef __m256d Vector;
+ struct Construct_vector {
+ struct Dimension {
+ // Initialize with NaN?
+ Vector operator()(unsigned d) const {
+ CGAL_assertion(d==4);
+ return Vector();
+ }
+ };
+
+ struct Iterator {
+ template<typename Iter>
+ Vector operator()(unsigned d,Iter const& f,Iter const& e) const {
+ CGAL_assertion(d==4);
+ double x0 = *f;
+ double x1 = *++f;
+ double x2 = *++f;
+ double x3 = *++f;
+ CGAL_assertion(++f==e);
+ Vector a = { x0, x1, x2, x3 };
+ return a;
+ }
+ };
+
+ struct Iterator_and_last {
+ template<typename Iter,typename T>
+ Vector operator()(unsigned d,Iter const& f,Iter const& e,double t) const {
+ CGAL_assertion(d==4);
+ double x0 = *f;
+ double x1 = *++f;
+ double x2 = *++f;
+ CGAL_assertion(++f==e);
+ Vector a = { x0, x1, x2, t };
+ return a;
+ }
+ };
+
+ struct Values {
+ Vector operator()(double a,double b,double c,double d) const {
+ Vector r = { a, b, c, d };
+ return r;
+ }
+ };
+
+ struct Values_divide {
+ Vector operator()(double h,double a,double b,double c,double d) const {
+ // {a,b,c,d}/{h,h,h,h} should be roughly the same
+ Vector r = { a/h, b/h, c/h, d/h };
+ return r;
+ }
+ };
+ };
+
+ public:
+ typedef double const* Vector_const_iterator;
+ static inline Vector_const_iterator vector_begin(Vector const&a){
+ return (Vector_const_iterator)(&a);
+ }
+ static inline Vector_const_iterator vector_end(Vector const&a){
+ return (Vector_const_iterator)(&a)+4;
+ }
+ static inline unsigned size_of_vector(Vector){
+ return 4;
+ }
+ static inline double dot_product(__m256d x, __m256d y){
+ __m256d p=x*y;
+ __m256d z=_mm256_hadd_pd(p,p);
+ return z[0]+z[2];
+ }
+ private:
+ static inline __m256d avx_sym(__m256d x){
+#if 0
+ return __builtin_shuffle(x,(__m256i){2,3,0,1});
+#else
+ return _mm256_permute2f128_pd(x,x,1);
+#endif
+ }
+ static inline __m256d avx_left(__m256d x){
+#if 0
+ return __builtin_shuffle(x,(__m256i){1,2,3,0});
+#else
+#ifdef __AVX2__
+ return _mm256_permute4x64_pd(x,1+2*4+3*16+0*64);
+#else
+ __m256d s = _mm256_permute2f128_pd(x,x,1);
+ return _mm256_shuffle_pd(x,s,5);
+#endif
+#endif
+ }
+ static inline __m256d avx_right(__m256d x){
+#if 0
+ return __builtin_shuffle(x,(__m256i){3,0,1,2});
+#else
+#ifdef __AVX2__
+ return _mm256_permute4x64_pd(x,3+0*4+1*16+2*64);
+#else
+ __m256d s = _mm256_permute2f128_pd(x,x,1);
+ return _mm256_shuffle_pd(s,x,5);
+#endif
+#endif
+ }
+ static inline double avx_altprod(__m256d x, __m256d y){
+ __m256d p=x*y;
+ __m256d z=_mm256_hsub_pd(p,p);
+ return z[0]+z[2];
+ }
+ public:
+ static double
+ determinant_of_vectors(Vector a, Vector b, Vector c, Vector d) {
+ __m256d x=a*avx_left(b)-avx_left(a)*b;
+ __m256d yy=a*avx_sym(b);
+ __m256d y=yy-avx_sym(yy);
+ __m256d z0=x*avx_sym(c);
+ __m256d z1=avx_left(x)*c;
+ __m256d z2=y*avx_left(c);
+ __m256d z=z0+z1-z2;
+ return avx_altprod(z,avx_right(d));
+ }
+ static CGAL::Sign
+ sign_of_determinant_of_vectors(Vector a, Vector b, Vector c, Vector d) {
+ return CGAL::sign(determinant_of_vectors(a,b,c,d));
+ }
+
+ private:
+ static inline __m256d avx3_right(__m256d x){
+#if 0
+ return __builtin_shuffle(x,(__m256i){2,0,1,3}); // can replace 3 with anything
+#else
+#ifdef __AVX2__
+ return _mm256_permute4x64_pd(x,2+0*4+1*16+3*64);
+#else
+ __m256d s = _mm256_permute2f128_pd(x,x,1);
+ return _mm256_shuffle_pd(s,x,12);
+#endif
+#endif
+ }
+ public:
+ static inline double dot_product_omit_last(__m256d x, __m256d y){
+ __m256d p=x*y;
+ __m128d q=_mm256_extractf128_pd(p,0);
+ double z=_mm_hadd_pd(q,q)[0];
+ return z+p[2];
+ }
+ // Note: without AVX2, is it faster than the scalar computation?
+ static double
+ determinant_of_vectors_omit_last(Vector a, Vector b, Vector c) {
+ __m256d x=a*avx3_right(b)-avx3_right(a)*b;
+ return dot_product_omit_last(c,avx3_right(x));
+ }
+ static CGAL::Sign
+ sign_of_determinant_of_vectors_omit_last(Vector a, Vector b, Vector c) {
+ return CGAL::sign(determinant_of_vectors_omit_last(a,b,c));
+ }
+
+ };
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h
new file mode 100644
index 00000000..b8efbe28
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_DET_ITER_PTS_ITER_VEC_H
+#define CGAL_VECTOR_DET_ITER_PTS_ITER_VEC_H
+#include <functional>
+#include <CGAL/transforming_iterator.h>
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Dimension.h>
+
+namespace CGAL {
+
+template <class LA, class Dim_=typename LA::Dimension,
+ class Max_dim_=typename LA::Max_dimension,
+ bool = LA::template Property<Has_determinant_of_iterator_to_points_tag>::value,
+ bool = LA::template Property<Has_determinant_of_iterator_to_vectors_tag>::value>
+struct Add_determinant_of_iterator_to_points_from_iterator_to_vectors : LA {
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_points_from_iterator_to_vectors<LA2> Other;
+ };
+};
+
+template <class LA, class Dim_,class Max_dim_>
+struct Add_determinant_of_iterator_to_points_from_iterator_to_vectors
+<LA, Dim_, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_points_from_iterator_to_vectors<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> :
+ boost::true_type {};
+
+ // TODO: use std::minus, boost::bind, etc
+ template<class T> struct Minus_fixed {
+ T const& a;
+ Minus_fixed(T const&a_):a(a_){}
+ T operator()(T const&b)const{return b-a;}
+ };
+ template<class Iter>
+ static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Minus_fixed<Vector> f(a);
+ return LA::determinant_of_iterator_to_vectors(make_transforming_iterator(first,f),make_transforming_iterator(end,f));
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Minus_fixed<Vector> f(a);
+ return LA::sign_of_determinant_of_iterator_to_vectors(make_transforming_iterator(first,f),make_transforming_iterator(end,f));
+ }
+};
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h
new file mode 100644
index 00000000..71a31d81
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h
@@ -0,0 +1,211 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_DET_ITER_PTS_PTS_H
+#define CGAL_VECTOR_DET_ITER_PTS_PTS_H
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Dimension.h>
+
+namespace CGAL {
+
+template <class LA, class Dim_=typename LA::Dimension,
+ class Max_dim_=typename LA::Max_dimension,
+ bool = LA::template Property<Has_determinant_of_iterator_to_points_tag>::value,
+ bool = LA::template Property<Has_determinant_of_points_tag>::value>
+struct Add_determinant_of_iterator_to_points_from_points : LA {
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other;
+ };
+};
+
+//FIXME: Use variadics and boost so it works in any dimension.
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_points_from_points
+<LA, Dimension_tag<2>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_points(a,b,c);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_points(a,b,c);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_points_from_points
+<LA, Dimension_tag<3>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_points(a,b,c,d);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_points(a,b,c,d);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_points_from_points
+<LA, Dimension_tag<4>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_points(a,b,c,d,e);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_points(a,b,c,d,e);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_points_from_points
+<LA, Dimension_tag<5>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; ++first;
+ Vector const&f=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_points(a,b,c,d,e,f);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; ++first;
+ Vector const&f=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_points(a,b,c,d,e,f);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_points_from_points
+<LA, Dimension_tag<6>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; ++first;
+ Vector const&f=*first; ++first;
+ Vector const&g=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_points(a,b,c,d,e,f,g);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; ++first;
+ Vector const&f=*first; ++first;
+ Vector const&g=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_points(a,b,c,d,e,f,g);
+ }
+};
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h
new file mode 100644
index 00000000..f096d6c7
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h
@@ -0,0 +1,201 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_DET_ITER_VEC_VEC_H
+#define CGAL_VECTOR_DET_ITER_VEC_VEC_H
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Dimension.h>
+
+namespace CGAL {
+
+template <class LA, class Dim_=typename LA::Dimension,
+ class Max_dim_=typename LA::Max_dimension,
+ bool = LA::template Property<Has_determinant_of_iterator_to_vectors_tag>::value,
+ bool = LA::template Property<Has_determinant_of_vectors_tag>::value>
+struct Add_determinant_of_iterator_to_vectors_from_vectors : LA {
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other;
+ };
+};
+
+//FIXME: Use variadics and boost so it works in any dimension.
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_vectors_from_vectors
+<LA, Dimension_tag<2>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_vectors(a,b);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_vectors(a,b);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_vectors_from_vectors
+<LA, Dimension_tag<3>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_vectors(a,b,c);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_vectors(a,b,c);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_vectors_from_vectors
+<LA, Dimension_tag<4>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_vectors(a,b,c,d);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_vectors(a,b,c,d);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_vectors_from_vectors
+<LA, Dimension_tag<5>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_vectors(a,b,c,d,e);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_vectors(a,b,c,d,e);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_iterator_to_vectors_from_vectors
+<LA, Dimension_tag<6>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> :
+ boost::true_type {};
+
+ template<class Iter>
+ static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; ++first;
+ Vector const&f=*first; CGAL_assertion(++first==end);
+ return LA::determinant_of_vectors(a,b,c,d,e,f);
+ }
+ template<class Iter>
+ static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){
+ Vector const&a=*first; ++first;
+ Vector const&b=*first; ++first;
+ Vector const&c=*first; ++first;
+ Vector const&d=*first; ++first;
+ Vector const&e=*first; ++first;
+ Vector const&f=*first; CGAL_assertion(++first==end);
+ return LA::sign_of_determinant_of_vectors(a,b,c,d,e,f);
+ }
+};
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h
new file mode 100644
index 00000000..7ddb73c3
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h
@@ -0,0 +1,164 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_DETPTS_H
+#define CGAL_VECTOR_DETPTS_H
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Dimension.h>
+
+namespace CGAL {
+
+template <class LA, class Dim_=typename LA::Dimension,
+ class Max_dim_=typename LA::Max_dimension,
+ bool = LA::template Property<Has_determinant_of_points_tag>::value,
+ bool = LA::template Property<Has_determinant_of_vectors_tag>::value
+ && LA::template Property<Has_vector_plus_minus_tag>::value>
+struct Add_determinant_of_points_from_vectors_and_minus : LA {
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other;
+ };
+};
+
+//FIXME: Use variadics and boost so it works in any dimension.
+template <class LA, class Max_dim_>
+struct Add_determinant_of_points_from_vectors_and_minus
+<LA, Dimension_tag<2>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_points_tag, D> :
+ boost::true_type {};
+
+ static NT determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c){
+ return LA::determinant_of_vectors(b-a,c-a);
+ }
+ static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c){
+ return LA::sign_of_determinant_of_vectors(b-a,c-a);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_points_from_vectors_and_minus
+<LA, Dimension_tag<3>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_points_tag, D> :
+ boost::true_type {};
+
+ static NT determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d){
+ return LA::determinant_of_vectors(b-a,c-a,d-a);
+ }
+ static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d){
+ return LA::sign_of_determinant_of_vectors(b-a,c-a,d-a);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_points_from_vectors_and_minus
+<LA, Dimension_tag<4>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_points_tag, D> :
+ boost::true_type {};
+
+ static NT determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e){
+ return LA::determinant_of_vectors(b-a,c-a,d-a,e-a);
+ }
+ static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e){
+ return LA::sign_of_determinant_of_vectors(b-a,c-a,d-a,e-a);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_points_from_vectors_and_minus
+<LA, Dimension_tag<5>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_points_tag, D> :
+ boost::true_type {};
+
+ static NT determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e, Vector const&f){
+ return LA::determinant_of_vectors(b-a,c-a,d-a,e-a,f-a);
+ }
+ static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e, Vector const&f){
+ return LA::sign_of_determinant_of_vectors(b-a,c-a,d-a,e-a,f-a);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct Add_determinant_of_points_from_vectors_and_minus
+<LA, Dimension_tag<6>, Max_dim_, false, true> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<Has_determinant_of_points_tag, D> :
+ boost::true_type {};
+
+ static NT determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e, Vector const&f,
+ Vector const&g){
+ return LA::determinant_of_vectors(b-a,c-a,d-a,e-a,f-a,g-a);
+ }
+ static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e, Vector const&f,
+ Vector const&g){
+ return LA::sign_of_determinant_of_vectors(b-a,c-a,d-a,e-a,f-a,g-a);
+ }
+};
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h
new file mode 100644
index 00000000..64eafe69
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_DETVEC_SMALL_H
+#define CGAL_VECTOR_DETVEC_SMALL_H
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/determinant_of_vectors.h>
+
+#define CGAL_ALLOWED_INCLUSION 1
+
+#define CGAL_CLASS Add_determinant_of_vectors_small_dim
+#define CGAL_TAG Has_determinant_of_vectors_tag
+#define CGAL_FUNC determinant_of_vectors
+#define CGAL_SIGN_FUNC sign_of_determinant_of_vectors
+#define CGAL_SHIFT 0
+
+#include <CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h>
+
+#undef CGAL_CLASS
+#undef CGAL_TAG
+#undef CGAL_FUNC
+#undef CGAL_SIGN_FUNC
+#undef CGAL_SHIFT
+
+#define CGAL_CLASS Add_determinant_of_vectors_omit_last_small_dim
+#define CGAL_TAG Has_determinant_of_vectors_omit_last_tag
+#define CGAL_FUNC determinant_of_vectors_omit_last
+#define CGAL_SIGN_FUNC sign_of_determinant_of_vectors_omit_last
+#define CGAL_SHIFT 1
+
+#include <CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h>
+
+#undef CGAL_CLASS
+#undef CGAL_TAG
+#undef CGAL_FUNC
+#undef CGAL_SIGN_FUNC
+#undef CGAL_SHIFT
+
+#undef CGAL_ALLOWED_INCLUSION
+
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h
new file mode 100644
index 00000000..b4856742
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h
@@ -0,0 +1,164 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_ALLOWED_INCLUSION
+#error Must not include this header directly
+#endif
+#if !defined(CGAL_TAG) \
+ || ! defined(CGAL_CLASS) \
+ || ! defined(CGAL_FUNC) \
+ || ! defined(CGAL_SIGN_FUNC) \
+ || ! defined(CGAL_SHIFT)
+
+#error Forgot one macro
+#endif
+
+namespace CGAL {
+
+template <class LA, class Dim_=typename LA::Dimension,
+ class Max_dim_=typename LA::Max_dimension,
+ bool=LA::template Property<CGAL_TAG>::value>
+struct CGAL_CLASS : LA {
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef CGAL_CLASS<LA2> Other;
+ };
+};
+
+template <class LA, class Max_dim_>
+struct CGAL_CLASS
+<LA, Dimension_tag<2+CGAL_SHIFT>, Max_dim_, false> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef CGAL_CLASS<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<CGAL_TAG, D> :
+ boost::true_type {};
+
+ static NT CGAL_FUNC(Vector const&a, Vector const&b){
+ return CGAL::determinant_of_vectors<NT>(a,b);
+ }
+ template <class V1, class V2>
+ static Sign CGAL_SIGN_FUNC(V1 const&a, V2 const&b){
+ return CGAL::sign_of_determinant_of_vectors<NT>(a,b);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct CGAL_CLASS
+<LA, Dimension_tag<3+CGAL_SHIFT>, Max_dim_, false> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef CGAL_CLASS<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<CGAL_TAG, D> :
+ boost::true_type {};
+
+ static NT CGAL_FUNC(Vector const&a, Vector const&b,
+ Vector const&c){
+ return CGAL::determinant_of_vectors<NT>(a,b,c);
+ }
+ static Sign CGAL_SIGN_FUNC(Vector const&a, Vector const&b,
+ Vector const&c){
+ return CGAL::sign_of_determinant_of_vectors<NT>(a,b,c);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct CGAL_CLASS
+<LA, Dimension_tag<4+CGAL_SHIFT>, Max_dim_, false> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef CGAL_CLASS<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<CGAL_TAG, D> :
+ boost::true_type {};
+
+ static NT CGAL_FUNC(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d){
+ return CGAL::determinant_of_vectors<NT>(a,b,c,d);
+ }
+ static Sign CGAL_SIGN_FUNC(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d){
+ return CGAL::sign_of_determinant_of_vectors<NT>(a,b,c,d);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct CGAL_CLASS
+<LA, Dimension_tag<5+CGAL_SHIFT>, Max_dim_, false> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef CGAL_CLASS<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<CGAL_TAG, D> :
+ boost::true_type {};
+
+ static NT CGAL_FUNC(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e){
+ return CGAL::determinant_of_vectors<NT>(a,b,c,d,e);
+ }
+ static Sign CGAL_SIGN_FUNC(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e){
+ return CGAL::sign_of_determinant_of_vectors<NT>(a,b,c,d,e);
+ }
+};
+
+template <class LA, class Max_dim_>
+struct CGAL_CLASS
+<LA, Dimension_tag<6+CGAL_SHIFT>, Max_dim_, false> : LA {
+ typedef typename LA::NT NT;
+ typedef typename LA::Vector Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef typename LA::template Rebind_dimension<D2,D3> LA2;
+ typedef CGAL_CLASS<LA2> Other;
+ };
+ template<class P,class=void> struct Property : LA::template Property<P> {};
+ template<class D> struct Property<CGAL_TAG, D> :
+ boost::true_type {};
+
+ static NT CGAL_FUNC(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e, Vector const&f){
+ return CGAL::determinant_of_vectors<NT>(a,b,c,d,e,f);
+ }
+ static Sign CGAL_SIGN_FUNC(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e, Vector const&f){
+ return CGAL::sign_of_determinant_of_vectors<NT>(a,b,c,d,e,f);
+ }
+};
+
+}
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h
new file mode 100644
index 00000000..d4cfeeb1
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KD_MIX_VECTOR_H
+#define CGAL_KD_MIX_VECTOR_H
+#include <CGAL/Dimension.h>
+namespace CGAL {
+
+template <class Static_, class Dynamic_, class NT_ ,class Dim_, class Max_dim_ = Dim_>
+struct Mix_vector
+: Dynamic_::template Rebind_dimension<Dim_, Max_dim_>::Other
+{
+ template <class D2, class D3 = D2>
+ struct Rebind_dimension {
+ typedef Mix_vector<Static_, Dynamic_, NT_, D2, D3> Other;
+ };
+};
+
+template <class Static_, class Dynamic_, class NT_, int d, class Max_dim_>
+struct Mix_vector<Static_, Dynamic_, NT_, Dimension_tag<d>, Max_dim_>
+: Static_::template Rebind_dimension<Dimension_tag<d>, Max_dim_>::Other
+{
+ template <class D2, class D3 = D2>
+ struct Rebind_dimension {
+ typedef Mix_vector<Static_, Dynamic_, NT_, D2, D3> Other;
+ };
+};
+}
+#endif
+
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h
new file mode 100644
index 00000000..2a75385c
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h
@@ -0,0 +1,145 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_SSE2_H
+#define CGAL_VECTOR_SSE2_H
+
+// Check what needs adapting for clang, intel and microsoft
+#if !defined __SSE2__ || (__GNUC__ * 100 + __GNUC_MINOR__ < 408)
+#error Requires SSE2 and gcc 4.8+
+#endif
+#include <x86intrin.h> // FIXME: other platforms call it differently
+
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/enum.h> // CGAL::Sign
+#include <CGAL/number_utils.h> // CGAL::sign
+
+
+
+namespace CGAL {
+
+ struct Sse_vector_2 {
+ typedef double NT;
+ typedef Dimension_tag<2> Dimension;
+ typedef Dimension_tag<2> Max_dimension;
+ // No Rebind_dimension, this is a building block
+ template<class,bool=true> struct Property : boost::false_type {};
+ template<bool b> struct Property<Has_vector_plus_minus_tag,b>
+ : boost::true_type {};
+ /* MAYBE?
+ template<bool b> struct Property<Has_vector_scalar_ops_tag,b>
+ : boost::true_type {};
+ */
+ template<bool b> struct Property<Has_determinant_of_vectors_tag,b>
+ : boost::true_type {};
+ template<bool b> struct Property<Has_dot_product_tag,b>
+ : boost::true_type {};
+
+ typedef __m128d Vector;
+ struct Construct_vector {
+ struct Dimension {
+ // Initialize with NaN?
+ Vector operator()(unsigned d) const {
+ CGAL_assertion(d==2);
+ return Vector();
+ }
+ };
+
+ struct Iterator {
+ template<typename Iter>
+ Vector operator()(unsigned d,Iter const& f,Iter const& e) const {
+ CGAL_assertion(d==2);
+ double x0 = *f;
+ double x1 = *++f;
+ CGAL_assertion(++f==e);
+ Vector a = { x0, x1 };
+ return a;
+ }
+ };
+
+ struct Iterator_and_last {
+ template<typename Iter,typename T>
+ Vector operator()(unsigned d,Iter const& f,Iter const& e,double t) const {
+ CGAL_assertion(d==2);
+ Vector a = { *f, t };
+ CGAL_assertion(++f==e);
+ return a;
+ }
+ };
+
+ struct Values {
+ Vector operator()(double a,double b) const {
+ Vector r = { a, b };
+ return r;
+ }
+ };
+
+ struct Values_divide {
+ Vector operator()(double h,double a,double b) const {
+ // {a,b}/{h,h} is probably slower
+ Vector r = { a/h, b/h };
+ return r;
+ }
+ };
+ };
+
+ typedef double const* Vector_const_iterator;
+ static inline Vector_const_iterator vector_begin(Vector const&a){
+ return (Vector_const_iterator)(&a);
+ }
+ static inline Vector_const_iterator vector_end(Vector const&a){
+ return (Vector_const_iterator)(&a)+2;
+ }
+ static inline unsigned size_of_vector(Vector){
+ return 2;
+ }
+ public:
+
+ static double determinant_of_vectors(Vector a, Vector b) {
+ __m128d c = _mm_shuffle_pd (b, b, 1); // b1, b0
+ __m128d d = a * c; // a0*b1, a1*b0
+#ifdef __SSE3__
+ __m128d e = _mm_hsub_pd (d, d);
+ return e[0];
+#else
+ return d[0]-d[1];
+#endif
+ }
+ static CGAL::Sign sign_of_determinant_of_vectors(Vector a, Vector b) {
+ return CGAL::sign(determinant_of_vectors(a,b));
+ }
+
+ static double dot_product(Vector a,Vector b){
+#ifdef __SSE4_1__
+ return _mm_dp_pd (a, b, 1+16+32)[0];
+#else
+ __m128d p = a * b;
+#if defined __SSE3__
+ __m128d s = _mm_hadd_pd (p, p);
+ return s[0];
+#else
+ return p[0]+p[1];
+#endif
+#endif
+ };
+ };
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h
new file mode 100644
index 00000000..b85a3734
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h
@@ -0,0 +1,181 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_2INT_H
+#define CGAL_VECTOR_2INT_H
+
+#include <stdint.h>
+#include <cmath>
+#include <CGAL/array.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/enum.h>
+#include <CGAL/number_utils.h>
+#include <CGAL/NT_converter.h>
+#include <CGAL/transforming_iterator.h>
+#include <CGAL/determinant_of_vectors.h>
+#include <CGAL/NewKernel_d/functor_tags.h>
+
+
+// What are the pros and cons of having NT be int vs double?
+
+namespace CGAL {
+ struct Vector_2_int_prop1 {
+ typedef double NT; // try lying a bit
+ typedef int32_t NT1; // what is really stored
+ typedef int32_t NT1b; // slightly longer
+ typedef int_fast64_t NT2; // longer type for computations
+ typedef int_fast64_t NT2b; // slightly longer
+ bool check_limits(int32_t x){return std::abs(x)<(1<<30);}
+ // TODO: find nice bounds
+ };
+#ifdef __SIZEOF_INT128__
+ struct Vector_2_int_prop2 {
+ typedef double NT;
+ typedef int32_t NT1;
+ typedef int_fast64_t NT1b;
+ typedef int_fast64_t NT2;
+ typedef __int128 NT2b;
+ bool check_limits(int32_t){return true;}
+ // take a template/int64_t input and still check the limits?
+ };
+ struct Vector_2_int_prop3 {
+ typedef long double NT;
+ typedef int64_t NT1;
+ typedef int64_t NT1b;
+ typedef __int128 NT2;
+ typedef __int128 NT2b;
+ enum { has_limit=true };
+ bool check_limits(int32_t x){return std::abs(x)<(1L<<62);}
+ // TODO: find nice bounds
+ };
+#endif
+
+ template<class Prop=Vector_2_int_prop1>
+ struct Vector_2_int : Prop {
+ using typename Prop::NT;
+ using typename Prop::NT1;
+ using typename Prop::NT1b;
+ using typename Prop::NT2;
+ using typename Prop::NT2b;
+ using Prop::check_limits;
+
+ typedef Dimension_tag<2> Dimension;
+ typedef Dimension_tag<2> Max_dimension;
+ // No Rebind_dimension, this is a building block
+ template<class,bool=true> struct Property : boost::false_type {};
+ //template<bool b> struct Property<Has_vector_plus_minus_tag,b>
+ // : boost::true_type {};
+ template<bool b> struct Property<Has_determinant_of_vectors_tag,b>
+ : boost::true_type {};
+ //template<bool b> struct Property<Has_determinant_of_points_tag,b>
+ // : boost::true_type {};
+ // Advertise somehow that the sign_of_determinant* are exact?
+
+ typedef cpp0x::array<NT1,2> Vector;
+ struct Construct_vector {
+ struct Dimension {
+ Vector operator()(unsigned d) const {
+ CGAL_assertion(d==2);
+ return Vector();
+ }
+ };
+
+ // TODO (for all constructors): check that input fits in NT1...
+ struct Iterator {
+ template<typename Iter>
+ Vector operator()(unsigned d,Iter const& f,Iter const& e) const {
+ CGAL_assertion(d==2);
+ NT1 x0 = *f;
+ NT1 x1 = *++f;
+ CGAL_assertion (++f == e);
+ CGAL_assertion (check_limits(x0) && check_limits(x1));
+ Vector a = { x0, x1 };
+ return a;
+ }
+ };
+
+ struct Iterator_and_last {
+ template<typename Iter,typename T>
+ Vector operator()(unsigned d,Iter const& f,Iter const& e,double t) const {
+ CGAL_assertion(d==2);
+ NT1 x = *f;
+ CGAL_assertion (++f == e);
+ CGAL_assertion (check_limits(x) && check_limits(t));
+ Vector a = { x, t };
+ return a;
+ }
+ };
+
+ struct Values {
+ Vector operator()(NT1 a,NT1 b) const {
+ CGAL_assertion (check_limits(a) && check_limits(b));
+ Vector r = { a, b };
+ return r;
+ }
+ };
+
+ /*
+ // Maybe safer not to provide it
+ struct Values_divide {
+ Vector operator()(double h,double a,double b) const {
+ Vector r = { a/h, b/h };
+ return r;
+ }
+ };
+ */
+ };
+
+ // Since we lie about NT, be consistent about it
+ typedef transforming_iterator<NT_converter<NT1,NT>,NT1 const*> Vector_const_iterator;
+ static inline Vector_const_iterator vector_begin(Vector const&a){
+ return Vector_const_iterator(a.begin());
+ }
+ static inline Vector_const_iterator vector_end(Vector const&a){
+ return Vector_const_iterator(a.end());
+ }
+ static inline unsigned size_of_vector(Vector){
+ return 2;
+ }
+
+ // for unsigned NT1, check what changes to do.
+ // return NT or NT2?
+ static NT determinant_of_vectors(Vector a, Vector b) {
+ return CGAL::determinant_of_vectors<NT2>(a,b);
+ }
+ static CGAL::Sign sign_of_determinant_of_vectors(Vector a, Vector b) {
+ return CGAL::sign_of_determinant_of_vectors<NT2>(a,b);
+ }
+
+ static NT determinant_of_points(Vector a, Vector b, Vector c) {
+ // could be faster to convert to NT directly
+ NT1b a0=a[0]; NT1b a1=a[1];
+ NT1b x0=b[0]-a0; NT1b x1=b[1]-a1;
+ NT1b y0=c[0]-a0; NT1b y1=c[1]-a1;
+ return CGAL::determinant<NT>(x0,x1,y0,y1);
+ }
+ static CGAL::Sign sign_of_determinant_of_points(Vector a, Vector b, Vector c) {
+ NT1b a0=a[0]; NT1b a1=a[1];
+ NT1b x0=b[0]-a0; NT1b x1=b[1]-a1;
+ NT2b y0=c[0]-a0; NT2b y1=c[1]-a1;
+ return CGAL::compare(x0*y1,x1*y0);
+ }
+ };
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h b/include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h
new file mode 100644
index 00000000..f9cc4e3c
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h
@@ -0,0 +1,167 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_VECTOR_VECTOR_H
+#define CGAL_VECTOR_VECTOR_H
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <CGAL/Dimension.h>
+#include <CGAL/NewKernel_d/utils.h>
+#include <vector>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+namespace CGAL {
+
+//Derive from a class that doesn't depend on Dim, or still use Dim for checking?
+template<class NT_,class Dim_,class Max_dim_=Dim_> struct Vector_vector {
+ typedef NT_ NT;
+ typedef Dim_ Dimension;
+ typedef Max_dim_ Max_dimension;
+ typedef std::vector<NT> Vector;
+ template< class D2, class D3=D2 >
+ struct Rebind_dimension {
+ typedef Vector_vector< NT, D2, D3 > Other;
+ };
+ template<class> struct Property : boost::false_type {};
+
+ struct Construct_vector {
+ struct Dimension {
+ Vector operator()(int d) const {
+ return Vector(d);
+ }
+ };
+
+ struct Iterator {
+ template<typename Iter>
+ Vector operator()(int CGAL_assertion_code(d),Iter const& f,Iter const& e) const {
+ CGAL_assertion(d==std::distance(f,e));
+ return Vector(f,e);
+ }
+ };
+
+ // unneeded thanks to Iterator_and_last?
+#if 0
+ struct Iterator_add_one {
+ template<typename Iter>
+ Vector operator()(int CGAL_assertion_code(d),Iter const& f,Iter const& e) const {
+ CGAL_assertion(d==std::distance(f,e)+1);
+ Vector a;
+ a.reserve(d+1);
+ a.insert(a.end(),f,e);
+ a.push_back(1);
+ return a;
+ }
+ };
+#endif
+
+ struct Iterator_and_last {
+ template<typename Iter,typename T>
+ Vector operator()(int d,Iter const& f,Iter const& e,CGAL_FORWARDABLE(T) t) const {
+ CGAL_assertion(d==std::distance(f,e)+1);
+ Vector a;
+ a.reserve(d+1);
+ a.insert(a.end(),f,e);
+ a.push_back(CGAL_FORWARD(T,t));
+ return a;
+ }
+ };
+
+ // useless, use a transform_iterator?
+#if 0
+ struct Iterator_and_last_divide {
+ template<typename Iter,typename T>
+ Vector operator()(int d,Iter f,Iter const& e,T const&t) const {
+ CGAL_assertion(d==std::distance(f,e)+1);
+ Vector a;
+ a.reserve(d+1);
+ for(;f!=e;++f){
+ a.push_back(*f/t);
+ }
+ return a;
+ }
+ };
+#endif
+
+ struct Values {
+#ifdef CGAL_CXX11
+ template<class...U>
+ Vector operator()(U&&...u) const {
+ //TODO: check the right number of {}, g++ accepts one and two
+ Vector a={forward_safe<NT,U>(u)...};
+ return a;
+ }
+#else
+
+#define CGAL_VAR(Z,N,_) a.push_back(t##N);
+#define CGAL_CODE(Z,N,_) Vector operator()(BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \
+ Vector a; \
+ a.reserve(N); \
+ BOOST_PP_REPEAT(N,CGAL_VAR,) \
+ return a; \
+}
+BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ )
+#undef CGAL_CODE
+#undef CGAL_VAR
+
+#endif
+ };
+
+ struct Values_divide {
+#ifdef CGAL_CXX11
+ template<class H,class...U>
+ Vector operator()(H const&h,U&&...u) const {
+ //TODO: do we want to cast at some point?
+ //e.g. to avoid 1/2 in integers
+ // ==> use Rational_traits<NT>().make_rational(x,y) ?
+ Vector a={Rational_traits<NT>().make_rational(std::forward<U>(u),h)...};
+ return a;
+ }
+#else
+
+#define CGAL_VAR(Z,N,_) a.push_back(Rational_traits<NT>().make_rational( t##N ,h));
+#define CGAL_CODE(Z,N,_) template<class H> Vector \
+ operator()(H const&h, BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \
+ Vector a; \
+ a.reserve(N); \
+ BOOST_PP_REPEAT(N,CGAL_VAR,) \
+ return a; \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ )
+#undef CGAL_CODE
+#undef CGAL_VAR
+
+#endif
+ };
+ };
+ typedef typename Vector::const_iterator Vector_const_iterator;
+ static Vector_const_iterator vector_begin(Vector const&a){
+ return a.begin();
+ }
+ static Vector_const_iterator vector_end(Vector const&a){
+ return a.end();
+ }
+ static int size_of_vector(Vector const&a){
+ return (int)a.size();
+ }
+};
+
+
+}
+#endif
+
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h
new file mode 100644
index 00000000..44e9aa96
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h
@@ -0,0 +1,305 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_CARTESIAN_WRAP_H
+#define CGAL_KERNEL_D_CARTESIAN_WRAP_H
+
+#include <CGAL/basic.h>
+#include <CGAL/is_iterator.h>
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4003) // not enough actual parameters for macro 'BOOST_PP_EXPAND_I'
+ // http://lists.boost.org/boost-users/2014/11/83291.php
+#endif
+#include <CGAL/NewKernel_d/Wrapper/Point_d.h>
+#include <CGAL/NewKernel_d/Wrapper/Vector_d.h>
+#include <CGAL/NewKernel_d/Wrapper/Segment_d.h>
+#include <CGAL/NewKernel_d/Wrapper/Sphere_d.h>
+#include <CGAL/NewKernel_d/Wrapper/Hyperplane_d.h>
+#include <CGAL/NewKernel_d/Wrapper/Weighted_point_d.h>
+
+#include <CGAL/NewKernel_d/Wrapper/Ref_count_obj.h>
+
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/mpl/vector.hpp>
+
+//TODO: do we want to store the kernel ref in the Object wrappers? It would allow for additions and operator[] and things like that to work, but objects would still need to be created by functors.
+
+namespace CGAL {
+namespace internal {
+BOOST_MPL_HAS_XXX_TRAIT_DEF(Is_wrapper)
+template<class T,bool=has_Is_wrapper<T>::value> struct Is_wrapper {
+ enum { value=false };
+ typedef Tag_false type;
+};
+template<class T> struct Is_wrapper<T,true> {
+ typedef typename T::Is_wrapper type;
+ enum { value=type::value };
+};
+
+template<class T,bool=is_iterator_type<T,std::input_iterator_tag>::value> struct Is_wrapper_iterator {
+ enum { value=false };
+ typedef Tag_false type;
+};
+template<class T> struct Is_wrapper_iterator<T,true> :
+ Is_wrapper<typename std::iterator_traits<typename CGAL::decay<T>::type>::value_type>
+{ };
+
+struct Forward_rep {
+//TODO: make a good C++0X version with perfect forwarding
+//#ifdef CGAL_CXX11
+//template <class T,class=typename std::enable_if<!Is_wrapper<typename std::decay<T>::type>::value&&!Is_wrapper_iterator<typename std::decay<T>::type>::value>::type>
+//T&& operator()(typename std::remove_reference<T>::type&& t) const {return static_cast<T&&>(t);};
+//template <class T,class=typename std::enable_if<!Is_wrapper<typename std::decay<T>::type>::value&&!Is_wrapper_iterator<typename std::decay<T>::type>::value>::type>
+//T&& operator()(typename std::remove_reference<T>::type& t) const {return static_cast<T&&>(t);};
+//
+//template <class T,class=typename std::enable_if<Is_wrapper<typename std::decay<T>::type>::value>::type>
+//typename Type_copy_cvref<T,typename std::decay<T>::type::Rep>::type&&
+//operator()(T&& t) const {
+// return static_cast<typename Type_copy_cvref<T,typename std::decay<T>::type::Rep>::type&&>(t.rep());
+//};
+//
+//template <class T,class=typename std::enable_if<Is_wrapper_iterator<typename std::decay<T>::type>::value>::type>
+//transforming_iterator<Forward_rep,typename std::decay<T>::type>
+//operator()(T&& t) const {
+// return make_transforming_iterator(std::forward<T>(t),Forward_rep());
+//};
+//#else
+template <class T,bool=Is_wrapper<T>::value,bool=Is_wrapper_iterator<T>::value> struct result_;
+template <class T> struct result_<T,false,false>{typedef T const& type;};
+template <class T> struct result_<T,true,false>{typedef typename decay<T>::type::Rep const& type;};
+template <class T> struct result_<T,false,true>{typedef transforming_iterator<Forward_rep,typename decay<T>::type> type;};
+template<class> struct result;
+template<class T> struct result<Forward_rep(T)> : result_<T> {};
+
+template <class T> typename boost::disable_if<boost::mpl::or_<Is_wrapper<T>,Is_wrapper_iterator<T> >,T>::type const& operator()(T const& t) const {return t;}
+template <class T> typename boost::disable_if<boost::mpl::or_<Is_wrapper<T>,Is_wrapper_iterator<T> >,T>::type& operator()(T& t) const {return t;}
+
+template <class T> typename T::Rep const& operator()(T const& t, typename boost::enable_if<Is_wrapper<T> >::type* = 0) const {return t.rep();}
+
+template <class T> transforming_iterator<Forward_rep,typename boost::enable_if<Is_wrapper_iterator<T>,T>::type> operator()(T const& t) const {return make_transforming_iterator(t,Forward_rep());}
+//#endif
+};
+}
+
+template <class B, class K, class T, bool = Provides_type<B, T>::value>
+struct Map_wrapping_type : Get_type<B, T> {};
+#define CGAL_REGISTER_OBJECT_WRAPPER(X) \
+ template <class B, class K> \
+ struct Map_wrapping_type <B, K, X##_tag, true> { \
+ typedef Wrap::X##_d<K> type; \
+ }
+CGAL_REGISTER_OBJECT_WRAPPER(Point);
+CGAL_REGISTER_OBJECT_WRAPPER(Vector);
+CGAL_REGISTER_OBJECT_WRAPPER(Segment);
+CGAL_REGISTER_OBJECT_WRAPPER(Sphere);
+CGAL_REGISTER_OBJECT_WRAPPER(Hyperplane);
+CGAL_REGISTER_OBJECT_WRAPPER(Weighted_point);
+#undef CGAL_REGISTER_OBJECT_WRAPPER
+
+// Note: this tends to be an all or nothing thing currently, wrapping
+// only some types breaks, probably because we don't check whether the
+// return type is indeed wrapped.
+template < typename Base_ , typename Derived_ = Default >
+struct Cartesian_wrap : public Base_
+{
+ CGAL_CONSTEXPR Cartesian_wrap(){}
+ CGAL_CONSTEXPR Cartesian_wrap(int d):Base_(d){}
+ typedef Base_ Kernel_base;
+ typedef Cartesian_wrap Self;
+ // TODO: pass the 2 types Self and Derived to the wrappers, they can use Self for most purposes and Derived only for Kernel_traits' typedef R.
+ typedef typename Default::Get<Derived_, Self>::type Derived;
+ // FIXME: The list doesn't belong here.
+ typedef boost::mpl::vector<Point_tag,Segment_tag,Sphere_tag,Vector_tag,Hyperplane_tag> Wrapped_list;
+
+ template <class T>
+ struct Type : Map_wrapping_type<Base_, Derived, T> {};
+
+ //Translate the arguments
+ template <class T, class D = void,
+ class=typename Get_functor_category<Derived,T>::type,
+ bool=Provides_functor<Kernel_base, T>::value,
+ bool=boost::mpl::contains<Wrapped_list,typename map_result_tag<T>::type>::type::value>
+ struct Functor {
+ typedef typename Get_functor<Kernel_base, T>::type B;
+ struct type {
+ B b;
+ type(){}
+ type(Self const&k):b(k){}
+ typedef typename B::result_type result_type;
+#ifdef CGAL_CXX11
+ template<class...U> result_type operator()(U&&...u)const{
+ return b(internal::Forward_rep()(u)...);
+ }
+#else
+#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N)
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> result_type \
+ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \
+ return b(BOOST_PP_ENUM(N,CGAL_VAR,)); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+#undef CGAL_VAR
+// In case the last argument needs to be non-const. Fragile...
+#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N)
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U),class V> result_type \
+ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u),V&v)const{ \
+ return b(BOOST_PP_ENUM(N,CGAL_VAR,),internal::Forward_rep()(v)); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1,8,CGAL_CODE,_)
+#undef CGAL_CODE
+#undef CGAL_VAR
+#endif
+ };
+ };
+
+ // Preserve the difference between Null_functor and nothing.
+ template <class T, class D, class C, bool b>
+ struct Functor <T, D, C, false, b>
+ : Get_functor <Kernel_base, T> {};
+
+ //Translate both the arguments and the result
+ //TODO: Check Is_wrapper instead of relying on map_result_tag?
+ template<class T,class D> struct Functor<T,D,Construct_tag,true,true> {
+ typedef typename Get_functor<Kernel_base, T>::type B;
+ struct type {
+ B b;
+ type(){}
+ type(Self const&k):b(k){}
+ typedef typename map_result_tag<T>::type result_tag;
+ // FIXME: Self or Derived?
+ typedef typename Get_type<Self,result_tag>::type result_type;
+#ifdef CGAL_CXX11
+ template<class...U> result_type operator()(U&&...u)const{
+ return result_type(Eval_functor(),b,internal::Forward_rep()(u)...);
+ }
+#else
+#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N)
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> result_type \
+ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \
+ return result_type(Eval_functor(),b,BOOST_PP_ENUM(N,CGAL_VAR,)); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+#undef CGAL_VAR
+#endif
+ };
+ };
+
+};
+
+template < typename Base_ >
+struct Cartesian_refcount : public Base_
+{
+ CGAL_CONSTEXPR Cartesian_refcount(){}
+ CGAL_CONSTEXPR Cartesian_refcount(int d):Base_(d){}
+ typedef Base_ Kernel_base;
+ typedef Cartesian_refcount Self;
+
+ // FIXME: Use object_list, or a list passed as argument, or anything
+ // automatic.
+ template <class T, class=void> struct Type : Get_type<Base_, T> {};
+#define CGAL_Kernel_obj(X,Y) \
+ template <class D> struct Type<X##_tag, D> { typedef Ref_count_obj<Cartesian_refcount, X##_tag> type; };
+
+ CGAL_Kernel_obj(Point,point)
+ CGAL_Kernel_obj(Vector,vector)
+#undef CGAL_Kernel_obj
+
+ template<class T> struct Dispatch {
+ //typedef typename map_functor_type<T>::type f_t;
+ typedef typename map_result_tag<T>::type r_t;
+ enum {
+ is_nul = boost::is_same<typename Get_functor<Kernel_base, T>::type,Null_functor>::value,
+ ret_rcobj = boost::is_same<r_t,Point_tag>::value || boost::is_same<r_t,Vector_tag>::value
+ };
+ };
+
+ //Translate the arguments
+ template<class T,class D=void,bool=Dispatch<T>::is_nul,bool=Dispatch<T>::ret_rcobj> struct Functor {
+ typedef typename Get_functor<Kernel_base, T>::type B;
+ struct type {
+ B b;
+ type(){}
+ type(Self const&k):b(k){}
+ typedef typename B::result_type result_type;
+#ifdef CGAL_CXX11
+ template<class...U> result_type operator()(U&&...u)const{
+ return b(internal::Forward_rep()(u)...);
+ }
+#else
+ result_type operator()()const{
+ return b();
+ }
+#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N)
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> result_type \
+ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \
+ return b(BOOST_PP_ENUM(N,CGAL_VAR,)); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+#undef CGAL_VAR
+#endif
+ };
+ };
+
+ //Translate both the arguments and the result
+ template<class T,class D,bool b> struct Functor<T,D,true,b> {
+ typedef Null_functor type;
+ };
+
+ template<class T,class D> struct Functor<T,D,false,true> {
+ typedef typename Get_functor<Kernel_base, T>::type B;
+ struct type {
+ B b;
+ type(){}
+ type(Self const&k):b(k){}
+ typedef typename map_result_tag<T>::type result_tag;
+ typedef typename Get_type<Self,result_tag>::type result_type;
+#ifdef CGAL_CXX11
+ template<class...U> result_type operator()(U&&...u)const{
+ return result_type(Eval_functor(),b,internal::Forward_rep()(u)...);
+ }
+#else
+ result_type operator()()const{
+ return result_type(Eval_functor(),b);
+ }
+#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N)
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> result_type \
+ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \
+ return result_type(Eval_functor(),b,BOOST_PP_ENUM(N,CGAL_VAR,)); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+#undef CGAL_VAR
+#endif
+ };
+ };
+
+};
+
+} //namespace CGAL
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#endif // CGAL_KERNEL_D_CARTESIAN_WRAP_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h
new file mode 100644
index 00000000..54fd50bd
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h
@@ -0,0 +1,131 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_WRAPPER_HYPERPLANE_D_H
+#define CGAL_WRAPPER_HYPERPLANE_D_H
+
+#include <CGAL/representation_tags.h>
+#include <CGAL/assertions.h>
+#include <boost/type_traits.hpp>
+#include <CGAL/Kernel/Return_base_tag.h>
+#include <CGAL/Dimension.h>
+#ifndef CGAL_CXX11
+#include <boost/preprocessor/repetition.hpp>
+#endif
+#include <boost/utility/result_of.hpp>
+
+namespace CGAL {
+namespace Wrap {
+
+template <class R_>
+class Hyperplane_d : public Get_type<typename R_::Kernel_base, Hyperplane_tag>::type
+{
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename R_::Kernel_base Kbase;
+ typedef typename Get_type<R_, Vector_tag>::type Vector_;
+ typedef typename Get_functor<Kbase, Construct_ttag<Hyperplane_tag> >::type CHBase;
+ typedef typename Get_functor<Kbase, Orthogonal_vector_tag>::type OVBase;
+ typedef typename Get_functor<Kbase, Hyperplane_translation_tag>::type HTBase;
+
+ typedef Hyperplane_d Self;
+ CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Hyperplane_tag>::type>::value));
+
+public:
+
+ typedef Tag_true Is_wrapper;
+ typedef typename R_::Default_ambient_dimension Ambient_dimension;
+ typedef typename Increment_dimension<Ambient_dimension,-1>::type Feature_dimension;
+
+ typedef typename Get_type<Kbase, Hyperplane_tag>::type Rep;
+
+ const Rep& rep() const
+ {
+ return *this;
+ }
+
+ Rep& rep()
+ {
+ return *this;
+ }
+
+ typedef R_ R;
+
+#ifdef CGAL_CXX11
+ template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Hyperplane_d> >::value>::type> explicit Hyperplane_d(U&&...u)
+ : Rep(CHBase()(std::forward<U>(u)...)){}
+
+// // called from Construct_point_d
+// template<class...U> explicit Point_d(Eval_functor&&,U&&...u)
+// : Rep(Eval_functor(), std::forward<U>(u)...){}
+ template<class F,class...U> explicit Hyperplane_d(Eval_functor&&,F&&f,U&&...u)
+ : Rep(std::forward<F>(f)(std::forward<U>(u)...)){}
+
+#if 0
+ // the new standard may make this necessary
+ Point_d(Point_d const&)=default;
+ Point_d(Point_d &);//=default;
+ Point_d(Point_d &&)=default;
+#endif
+
+ // try not to use these
+ Hyperplane_d(Rep const& v) : Rep(v) {}
+ Hyperplane_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {}
+ Hyperplane_d(Rep&& v) : Rep(std::move(v)) {}
+
+#else
+
+ Hyperplane_d() : Rep(CHBase()()) {}
+
+ Hyperplane_d(Rep const& v) : Rep(v) {} // try not to use it
+
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ explicit Hyperplane_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(CHBase()( \
+ BOOST_PP_ENUM_PARAMS(N,t))) {} \
+ \
+ template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Hyperplane_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {}
+ /*
+ template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {}
+ */
+
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+
+#endif
+
+ //TODO: if OVBase returns a reference to a base vector, cast it to a
+ //reference to a wrapper vector. Ugly but should be safe.
+ Vector_ orthogonal_vector()const{
+ return Vector_(Eval_functor(),OVBase(),rep());
+ }
+ FT_ translation()const{
+ return HTBase()(rep());
+ }
+
+
+};
+
+} //namespace Wrap
+} //namespace CGAL
+
+#endif // CGAL_WRAPPER_SPHERE_D_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h
new file mode 100644
index 00000000..0718c947
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h
@@ -0,0 +1,284 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_WRAPPER_POINT_D_H
+#define CGAL_WRAPPER_POINT_D_H
+
+#include <ostream>
+#include <CGAL/Origin.h>
+#include <CGAL/Kernel/mpl.h>
+#include <CGAL/representation_tags.h>
+#include <CGAL/assertions.h>
+#include <boost/type_traits.hpp>
+#include <CGAL/Kernel/Return_base_tag.h>
+#include <CGAL/Dimension.h>
+#ifndef CGAL_CXX11
+#include <boost/preprocessor/repetition.hpp>
+#endif
+#include <boost/utility/result_of.hpp>
+
+namespace CGAL {
+namespace Wrap {
+
+template <class R_>
+class Point_d : public Get_type<typename R_::Kernel_base, Point_tag>::type
+ // Deriving won't work if the point is just a __m256d.
+ // Test boost/std::is_class for instance
+{
+ typedef typename Get_type<R_, RT_tag>::type RT_;
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename R_::Kernel_base Kbase;
+ typedef typename Get_type<R_, Vector_tag>::type Vector_;
+ typedef typename Get_functor<Kbase, Construct_ttag<Point_tag> >::type CPBase;
+ typedef typename Get_functor<Kbase, Compute_point_cartesian_coordinate_tag>::type CCBase;
+ typedef typename Get_functor<Kbase, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CPI;
+
+
+ typedef Point_d Self;
+ CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Point_tag>::type>::value));
+
+public:
+
+ typedef Tag_true Is_wrapper;
+ typedef typename R_::Default_ambient_dimension Ambient_dimension;
+ typedef Dimension_tag<0> Feature_dimension;
+
+ typedef typename Get_type<Kbase, Point_tag>::type Rep;
+ //typedef typename CGAL::decay<typename boost::result_of<CPI(Rep,Begin_tag)>::type>::type Cartesian_const_iterator;
+
+ const Rep& rep() const
+ {
+ return *this;
+ }
+
+ Rep& rep()
+ {
+ return *this;
+ }
+
+ typedef R_ R;
+
+#ifdef CGAL_CXX11
+ template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Point_d> >::value>::type> explicit Point_d(U&&...u)
+ : Rep(CPBase()(std::forward<U>(u)...)){}
+
+// // called from Construct_point_d
+// template<class...U> explicit Point_d(Eval_functor&&,U&&...u)
+// : Rep(Eval_functor(), std::forward<U>(u)...){}
+ template<class F,class...U> explicit Point_d(Eval_functor&&,F&&f,U&&...u)
+ : Rep(std::forward<F>(f)(std::forward<U>(u)...)){}
+
+#if 0
+ // the new standard may make this necessary
+ Point_d(Point_d const&)=default;
+ Point_d(Point_d &);//=default;
+ Point_d(Point_d &&)=default;
+#endif
+
+ // try not to use these
+ Point_d(Rep const& v) : Rep(v) {}
+ Point_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {}
+ Point_d(Rep&& v) : Rep(std::move(v)) {}
+
+ // this one should be implicit
+ Point_d(Origin const& v)
+ : Rep(CPBase()(v)) {}
+ Point_d(Origin& v)
+ : Rep(CPBase()(v)) {}
+ Point_d(Origin&& v)
+ : Rep(CPBase()(std::move(v))) {}
+
+#else
+
+ Point_d() : Rep(CPBase()()) {}
+
+ Point_d(Rep const& v) : Rep(v) {} // try not to use it
+
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ explicit Point_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(CPBase()( \
+ BOOST_PP_ENUM_PARAMS(N,t))) {} \
+ \
+ template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Point_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {}
+ /*
+ template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {}
+ */
+
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+
+ // this one should be implicit
+ Point_d(Origin const& o)
+ : Rep(CPBase()(o)) {}
+
+#endif
+
+ typename boost::result_of<CCBase(Rep,int)>::type cartesian(int i)const{
+ return CCBase()(rep(),i);
+ }
+ typename boost::result_of<CCBase(Rep,int)>::type operator[](int i)const{
+ return CCBase()(rep(),i);
+ }
+
+ typename boost::result_of<CPI(Rep,Begin_tag)>::type cartesian_begin()const{
+ return CPI()(rep(),Begin_tag());
+ }
+
+ typename boost::result_of<CPI(Rep,End_tag)>::type cartesian_end()const{
+ return CPI()(rep(),End_tag());
+ }
+
+ int dimension() const {
+ typedef typename Get_functor<Kbase, Point_dimension_tag>::type PDBase;
+ return PDBase()(rep());
+ }
+
+ /*
+ Direction_d direction() const
+ {
+ return R().construct_direction_d_object()(*this);
+ }
+
+ Vector_d transform(const Aff_transformation_d &t) const
+ {
+ return t.transform(*this);
+ }
+
+ Vector_d operator/(const RT& c) const
+ {
+ return R().construct_divided_vector_d_object()(*this,c);
+ }
+
+ Vector_d operator/(const typename First_if_different<FT_,RT>::Type & c) const
+ {
+ return R().construct_divided_vector_d_object()(*this,c);
+ }
+
+ typename Qualified_result_of<typename R::Compute_x_3, Vector_3>::type
+ x() const
+ {
+ return R().compute_x_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_y_3, Vector_3>::type
+ y() const
+ {
+ return R().compute_y_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_z_3, Vector_3>::type
+ z() const
+ {
+ return R().compute_z_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_hx_3, Vector_3>::type
+ hx() const
+ {
+ return R().compute_hx_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_hy_3, Vector_3>::type
+ hy() const
+ {
+ return R().compute_hy_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_hz_3, Vector_3>::type
+ hz() const
+ {
+ return R().compute_hz_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_hw_3, Vector_3>::type
+ hw() const
+ {
+ return R().compute_hw_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_x_3, Vector_3>::type
+ cartesian(int i) const
+ {
+ CGAL_kernel_precondition( (i == 0) || (i == 1) || (i == 2) );
+ if (i==0) return x();
+ if (i==1) return y();
+ return z();
+ }
+
+ typename Qualified_result_of<typename R::Compute_hw_3, Vector_3>::type
+ homogeneous(int i) const
+ {
+ CGAL_kernel_precondition( (i >= 0) || (i <= 3) );
+ if (i==0) return hx();
+ if (i==1) return hy();
+ if (i==2) return hz();
+ return hw();
+ }
+
+ typename Qualified_result_of<typename R::Compute_squared_length_3, Vector_3>::type
+ squared_length() const
+ {
+ return R().compute_squared_length_3_object()(*this);
+ }
+*/
+};
+#if 0
+template <class R_> Point_d<R_>::Point_d(Point_d &)=default;
+#endif
+
+//TODO: IO
+
+template <class R_>
+std::ostream& operator <<(std::ostream& os, const Point_d<R_>& p)
+{
+ typedef typename R_::Kernel_base Kbase;
+ typedef typename Get_functor<Kbase, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CPI;
+ // Should just be "auto"...
+ typename CGAL::decay<typename boost::result_of<
+ CPI(typename Point_d<R_>::Rep,Begin_tag)
+ >::type>::type
+ b = p.cartesian_begin(),
+ e = p.cartesian_end();
+ os << p.dimension();
+ for(; b != e; ++b){
+ os << " " << *b;
+ }
+ return os;
+}
+
+//template <class R_>
+//Vector_d<R_> operator+(const Vector_d<R_>& v,const Vector_d<R_>& w) const
+//{
+// return typename R::template Construct<Sum_of_vectors_tag>::type()(v,w);
+//}
+//
+//template <class R_>
+//Vector_d<R_> operator-(const Vector_d<R_>& v,const Vector_d<R_>& w) const
+//{
+// return typename R::template Construct<Difference_of_vectors_tag>::type()(v,w);
+//}
+
+} //namespace Wrap
+} //namespace CGAL
+
+#endif // CGAL_WRAPPER_POINT_D_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h
new file mode 100644
index 00000000..f33e14c0
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h
@@ -0,0 +1,120 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_WRAPPER_REF_COUNT_OBJ_H
+#define CGAL_WRAPPER_REF_COUNT_OBJ_H
+
+#include <CGAL/Origin.h>
+#include <CGAL/Handle_for.h>
+#include <CGAL/Kernel/mpl.h>
+#include <CGAL/representation_tags.h>
+#include <CGAL/assertions.h>
+#include <boost/type_traits.hpp>
+#include <CGAL/Kernel/Return_base_tag.h>
+#include <CGAL/Dimension.h>
+#ifndef CGAL_CXX11
+#include <boost/preprocessor/repetition.hpp>
+#endif
+#include <boost/utility/result_of.hpp>
+
+// no need for a fancy interface here, people can use the Point_d wrapper on
+// top.
+
+namespace CGAL {
+
+template <class R_, class Tag_>
+class Ref_count_obj
+{
+ typedef typename R_::Kernel_base Kbase;
+ typedef typename Get_functor<Kbase, Construct_ttag<Tag_> >::type CBase;
+
+ typedef Ref_count_obj Self;
+ CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Tag_>::type>::value));
+
+public:
+ typedef R_ R;
+
+ typedef Tag_true Is_wrapper;
+ typedef typename R_::Default_ambient_dimension Ambient_dimension;
+ //typedef Dimension_tag<0> Feature_dimension;
+
+ typedef typename Get_type<Kbase, Tag_>::type Rep;
+ typedef Handle_for<Rep> Data;
+
+private:
+ Data data;
+public:
+
+ const Rep& rep() const
+ {
+ return CGAL::get_pointee_or_identity(data);
+ }
+
+#ifdef CGAL_CXX11
+ template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Ref_count_obj> >::value>::type> explicit Ref_count_obj(U&&...u)
+ : data(Eval_functor(),CBase(),std::forward<U>(u)...){}
+
+ template<class F,class...U> explicit Ref_count_obj(Eval_functor&&,F&&f,U&&...u)
+ : data(Eval_functor(),std::forward<F>(f),std::forward<U>(u)...){}
+
+ // try not to use these
+ Ref_count_obj(Rep const& v) : data(v) {}
+ Ref_count_obj(Rep& v) : data(static_cast<Rep const&>(v)) {}
+ Ref_count_obj(Rep&& v) : data(std::move(v)) {}
+
+ // Do we really need this for point?
+// // this one should be implicit
+// Ref_count_obj(Origin const& v)
+// : data(Eval_functor(),CBase(),v) {}
+// Ref_count_obj(Origin& v)
+// : data(Eval_functor(),CBase(),v) {}
+// Ref_count_obj(Origin&& v)
+// : data(Eval_functor(),CBase(),std::move(v)) {}
+
+#else
+
+ Ref_count_obj() : data(Eval_functor(),CBase()) {}
+
+ Ref_count_obj(Rep const& v) : data(v) {} // try not to use it
+
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ explicit Ref_count_obj(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : data(Eval_functor(),CBase(),BOOST_PP_ENUM_PARAMS(N,t)) {} \
+ \
+ template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Ref_count_obj(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : data(Eval_functor(),f,BOOST_PP_ENUM_PARAMS(N,t)) {}
+
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+ template<class F>
+ Ref_count_obj(Eval_functor,F const& f)
+ : data(Eval_functor(),f) {}
+
+// // this one should be implicit
+// Ref_count_obj(Origin const& o)
+// : data(Eval_functor(),CBase(),o) {}
+
+#endif
+
+};
+
+} //namespace CGAL
+
+#endif
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h
new file mode 100644
index 00000000..bfb20a77
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_WRAPPER_SEGMENT_D_H
+#define CGAL_WRAPPER_SEGMENT_D_H
+
+#include <CGAL/Origin.h>
+#include <CGAL/Kernel/mpl.h>
+#include <CGAL/representation_tags.h>
+#include <CGAL/assertions.h>
+#include <boost/type_traits.hpp>
+#include <CGAL/Kernel/Return_base_tag.h>
+#include <CGAL/Dimension.h>
+#ifndef CGAL_CXX11
+#include <boost/preprocessor/repetition.hpp>
+#endif
+#include <boost/utility/result_of.hpp>
+
+namespace CGAL {
+namespace Wrap {
+
+template <class R_>
+class Segment_d : public Get_type<typename R_::Kernel_base, Segment_tag>::type
+{
+ typedef typename Get_type<R_, RT_tag>::type RT_;
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename R_::Kernel_base Kbase;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ typedef typename Get_functor<Kbase, Construct_ttag<Point_tag> >::type CPBase;
+ typedef typename Get_functor<Kbase, Construct_ttag<Segment_tag> >::type CSBase;
+ typedef typename Get_functor<Kbase, Segment_extremity_tag>::type CSEBase;
+
+ typedef Segment_d Self;
+ CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Segment_tag>::type>::value));
+
+public:
+
+ typedef Tag_true Is_wrapper;
+ typedef typename R_::Default_ambient_dimension Ambient_dimension;
+ typedef Dimension_tag<1> Feature_dimension;
+
+ typedef typename Get_type<Kbase, Segment_tag>::type Rep;
+
+ const Rep& rep() const
+ {
+ return *this;
+ }
+
+ Rep& rep()
+ {
+ return *this;
+ }
+
+ typedef R_ R;
+
+#ifdef CGAL_CXX11
+ template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Segment_d> >::value>::type> explicit Segment_d(U&&...u)
+ : Rep(CSBase()(std::forward<U>(u)...)){}
+
+// // called from Construct_point_d
+// template<class...U> explicit Point_d(Eval_functor&&,U&&...u)
+// : Rep(Eval_functor(), std::forward<U>(u)...){}
+ template<class F,class...U> explicit Segment_d(Eval_functor&&,F&&f,U&&...u)
+ : Rep(std::forward<F>(f)(std::forward<U>(u)...)){}
+
+#if 0
+ // the new standard may make this necessary
+ Point_d(Point_d const&)=default;
+ Point_d(Point_d &);//=default;
+ Point_d(Point_d &&)=default;
+#endif
+
+ // try not to use these
+ Segment_d(Rep const& v) : Rep(v) {}
+ Segment_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {}
+ Segment_d(Rep&& v) : Rep(std::move(v)) {}
+
+#else
+
+ Segment_d() : Rep(CSBase()()) {}
+
+ Segment_d(Rep const& v) : Rep(v) {} // try not to use it
+
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ explicit Segment_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(CSBase()( \
+ BOOST_PP_ENUM_PARAMS(N,t))) {} \
+ \
+ template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Segment_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {}
+ /*
+ template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {}
+ */
+
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+
+#endif
+
+ //TODO: if CSEBase returns a reference to a base point, cast it to a
+ //reference to a wrapper point. Ugly but should be safe.
+ Point_ source()const{
+ return Point_(Eval_functor(),CSEBase(),rep(),0);
+ }
+ Point_ target()const{
+ return Point_(Eval_functor(),CSEBase(),rep(),1);
+ }
+
+};
+
+} //namespace Wrap
+} //namespace CGAL
+
+#endif // CGAL_WRAPPER_SEGMENT_D_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h
new file mode 100644
index 00000000..87f0c66e
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h
@@ -0,0 +1,130 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_WRAPPER_SPHERE_D_H
+#define CGAL_WRAPPER_SPHERE_D_H
+
+#include <CGAL/representation_tags.h>
+#include <CGAL/assertions.h>
+#include <boost/type_traits.hpp>
+#include <CGAL/Kernel/Return_base_tag.h>
+#include <CGAL/Dimension.h>
+#ifndef CGAL_CXX11
+#include <boost/preprocessor/repetition.hpp>
+#endif
+#include <boost/utility/result_of.hpp>
+
+namespace CGAL {
+namespace Wrap {
+
+template <class R_>
+class Sphere_d : public Get_type<typename R_::Kernel_base, Sphere_tag>::type
+{
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename R_::Kernel_base Kbase;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ typedef typename Get_functor<Kbase, Construct_ttag<Sphere_tag> >::type CSBase;
+ typedef typename Get_functor<Kbase, Center_of_sphere_tag>::type COSBase;
+ typedef typename Get_functor<Kbase, Squared_radius_tag>::type SRBase;
+
+ typedef Sphere_d Self;
+ CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Sphere_tag>::type>::value));
+
+public:
+
+ typedef Tag_true Is_wrapper;
+ typedef typename R_::Default_ambient_dimension Ambient_dimension;
+ typedef typename Increment_dimension<Ambient_dimension,-1>::type Feature_dimension;
+
+ typedef typename Get_type<Kbase, Sphere_tag>::type Rep;
+
+ const Rep& rep() const
+ {
+ return *this;
+ }
+
+ Rep& rep()
+ {
+ return *this;
+ }
+
+ typedef R_ R;
+
+#ifdef CGAL_CXX11
+ template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Sphere_d> >::value>::type> explicit Sphere_d(U&&...u)
+ : Rep(CSBase()(std::forward<U>(u)...)){}
+
+// // called from Construct_point_d
+// template<class...U> explicit Point_d(Eval_functor&&,U&&...u)
+// : Rep(Eval_functor(), std::forward<U>(u)...){}
+ template<class F,class...U> explicit Sphere_d(Eval_functor&&,F&&f,U&&...u)
+ : Rep(std::forward<F>(f)(std::forward<U>(u)...)){}
+
+#if 0
+ // the new standard may make this necessary
+ Point_d(Point_d const&)=default;
+ Point_d(Point_d &);//=default;
+ Point_d(Point_d &&)=default;
+#endif
+
+ // try not to use these
+ Sphere_d(Rep const& v) : Rep(v) {}
+ Sphere_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {}
+ Sphere_d(Rep&& v) : Rep(std::move(v)) {}
+
+#else
+
+ Sphere_d() : Rep(CSBase()()) {}
+
+ Sphere_d(Rep const& v) : Rep(v) {} // try not to use it
+
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ explicit Sphere_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(CSBase()( \
+ BOOST_PP_ENUM_PARAMS(N,t))) {} \
+ \
+ template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Sphere_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {}
+ /*
+ template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {}
+ */
+
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+
+#endif
+
+ //TODO: if COSBase returns a reference to a base point, cast it to a
+ //reference to a wrapper point. Ugly but should be safe.
+ Point_ center()const{
+ return Point_(Eval_functor(),COSBase(),rep());
+ }
+ FT_ squared_radius()const{
+ return SRBase()(rep());
+ }
+
+};
+
+} //namespace Wrap
+} //namespace CGAL
+
+#endif // CGAL_WRAPPER_SPHERE_D_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h
new file mode 100644
index 00000000..b7d1f0d0
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h
@@ -0,0 +1,266 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_WRAPPER_VECTOR_D_H
+#define CGAL_WRAPPER_VECTOR_D_H
+
+#include <CGAL/Origin.h>
+#include <CGAL/Kernel/mpl.h>
+#include <CGAL/representation_tags.h>
+#include <CGAL/assertions.h>
+#include <boost/type_traits.hpp>
+#include <CGAL/Kernel/Return_base_tag.h>
+#include <CGAL/Dimension.h>
+#ifndef CGAL_CXX11
+#include <boost/preprocessor/repetition.hpp>
+#endif
+#include <boost/utility/result_of.hpp>
+
+namespace CGAL {
+namespace Wrap {
+
+template <class R_>
+class Vector_d : public Get_type<typename R_::Kernel_base, Vector_tag>::type
+{
+ typedef typename Get_type<R_, RT_tag>::type RT_;
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename R_::Kernel_base Kbase;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ typedef typename Get_functor<Kbase, Construct_ttag<Vector_tag> >::type CVBase;
+ typedef typename Get_functor<Kbase, Compute_vector_cartesian_coordinate_tag>::type CCBase;
+ typedef typename Get_functor<Kbase, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CVI;
+ typedef typename Get_functor<Kbase, Squared_length_tag>::type SLBase;
+
+ typedef Vector_d Self;
+ CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Vector_tag>::type>::value));
+
+public:
+
+ typedef Tag_true Is_wrapper;
+ typedef typename R_::Default_ambient_dimension Ambient_dimension;
+ typedef Dimension_tag<0> Feature_dimension;
+
+ //typedef typename R_::Vector_cartesian_const_iterator Cartesian_const_iterator;
+ typedef typename Get_type<Kbase, Vector_tag>::type Rep;
+
+ const Rep& rep() const
+ {
+ return *this;
+ }
+
+ Rep& rep()
+ {
+ return *this;
+ }
+
+ typedef R_ R;
+
+#ifdef CGAL_CXX11
+ template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Vector_d> >::value>::type> explicit Vector_d(U&&...u)
+ : Rep(CVBase()(std::forward<U>(u)...)){}
+
+// // called from Construct_vector_d
+// template<class...U> explicit Vector_d(Eval_functor&&,U&&...u)
+// : Rep(Eval_functor(), std::forward<U>(u)...){}
+ template<class F,class...U> explicit Vector_d(Eval_functor&&,F&&f,U&&...u)
+ : Rep(std::forward<F>(f)(std::forward<U>(u)...)){}
+
+#if 0
+ // the new standard may make this necessary
+ Vector_d(Vector_d const&)=default;
+ Vector_d(Vector_d &);//=default;
+ Vector_d(Vector_d &&)=default;
+#endif
+
+ // try not to use these
+ Vector_d(Rep const& v) : Rep(v) {}
+ Vector_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {}
+ Vector_d(Rep&& v) : Rep(std::move(v)) {}
+
+ // this one should be implicit
+ Vector_d(Null_vector const& v)
+ : Rep(CVBase()(v)) {}
+ Vector_d(Null_vector& v)
+ : Rep(CVBase()(v)) {}
+ Vector_d(Null_vector&& v)
+ : Rep(CVBase()(std::move(v))) {}
+
+#else
+
+ Vector_d() : Rep(CVBase()()) {}
+
+ Vector_d(Rep const& v) : Rep(v) {} // try not to use it
+
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ explicit Vector_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(CVBase()( \
+ BOOST_PP_ENUM_PARAMS(N,t))) {} \
+ \
+ template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Vector_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {}
+ /*
+ template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Vector_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {}
+ */
+
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+
+ // this one should be implicit
+ Vector_d(Null_vector const& v)
+ : Rep(CVBase()(v)) {}
+
+#endif
+
+ typename boost::result_of<CCBase(Rep,int)>::type cartesian(int i)const{
+ return CCBase()(rep(),i);
+ }
+
+ typename boost::result_of<CCBase(Rep,int)>::type operator[](int i)const{
+ return CCBase()(rep(),i);
+ }
+
+ typename boost::result_of<CVI(Rep,Begin_tag)>::type cartesian_begin()const{
+ return CVI()(rep(),Begin_tag());
+ }
+
+ typename boost::result_of<CVI(Rep,End_tag)>::type cartesian_end()const{
+ return CVI()(rep(),End_tag());
+ }
+
+ Vector_d operator-() const
+ {
+ return typename Get_functor<R, Opposite_vector_tag>::type()(*this);
+ }
+
+ /*
+ Direction_d direction() const
+ {
+ return R().construct_direction_d_object()(*this);
+ }
+
+ Vector_d transform(const Aff_transformation_d &t) const
+ {
+ return t.transform(*this);
+ }
+
+ Vector_d operator/(const RT& c) const
+ {
+ return R().construct_divided_vector_d_object()(*this,c);
+ }
+
+ Vector_d operator/(const typename First_if_different<FT_,RT>::Type & c) const
+ {
+ return R().construct_divided_vector_d_object()(*this,c);
+ }
+
+ typename Qualified_result_of<typename R::Compute_x_3, Vector_3>::type
+ x() const
+ {
+ return R().compute_x_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_y_3, Vector_3>::type
+ y() const
+ {
+ return R().compute_y_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_z_3, Vector_3>::type
+ z() const
+ {
+ return R().compute_z_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_hx_3, Vector_3>::type
+ hx() const
+ {
+ return R().compute_hx_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_hy_3, Vector_3>::type
+ hy() const
+ {
+ return R().compute_hy_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_hz_3, Vector_3>::type
+ hz() const
+ {
+ return R().compute_hz_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_hw_3, Vector_3>::type
+ hw() const
+ {
+ return R().compute_hw_3_object()(*this);
+ }
+
+ typename Qualified_result_of<typename R::Compute_x_3, Vector_3>::type
+ cartesian(int i) const
+ {
+ CGAL_kernel_precondition( (i == 0) || (i == 1) || (i == 2) );
+ if (i==0) return x();
+ if (i==1) return y();
+ return z();
+ }
+
+ typename Qualified_result_of<typename R::Compute_hw_3, Vector_3>::type
+ homogeneous(int i) const
+ {
+ CGAL_kernel_precondition( (i >= 0) || (i <= 3) );
+ if (i==0) return hx();
+ if (i==1) return hy();
+ if (i==2) return hz();
+ return hw();
+ }
+
+ int dimension() const // bad idea?
+ {
+ return rep.dimension();
+ }
+*/
+ typename boost::result_of<SLBase(Rep)>::type squared_length()const{
+ return SLBase()(rep());
+ }
+};
+#if 0
+template <class R_> Vector_d<R_>::Vector_d(Vector_d &)=default;
+#endif
+
+//TODO: IO
+
+template <class R_>
+Vector_d<R_> operator+(const Vector_d<R_>& v,const Vector_d<R_>& w)
+{
+ return typename Get_functor<R_, Sum_of_vectors_tag>::type()(v,w);
+}
+
+template <class R_>
+Vector_d<R_> operator-(const Vector_d<R_>& v,const Vector_d<R_>& w)
+{
+ return typename Get_functor<R_, Difference_of_vectors_tag>::type()(v,w);
+}
+
+} //namespace Wrap
+} //namespace CGAL
+
+#endif // CGAL_WRAPPER_VECTOR_D_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h
new file mode 100644
index 00000000..877eea21
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h
@@ -0,0 +1,129 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_WRAPPER_WEIGHTED_POINT_D_H
+#define CGAL_WRAPPER_WEIGHTED_POINT_D_H
+
+#include <CGAL/representation_tags.h>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+#include <CGAL/Kernel/Return_base_tag.h>
+#include <CGAL/Dimension.h>
+#ifndef CGAL_CXX11
+#include <boost/preprocessor/repetition.hpp>
+#endif
+#include <boost/utility/result_of.hpp>
+
+namespace CGAL {
+namespace Wrap {
+
+template <class R_>
+class Weighted_point_d : public Get_type<typename R_::Kernel_base, Weighted_point_tag>::type
+{
+ typedef typename Get_type<R_, FT_tag>::type FT_;
+ typedef typename R_::Kernel_base Kbase;
+ typedef typename Get_type<R_, Point_tag>::type Point_;
+ typedef typename Get_functor<Kbase, Construct_ttag<Weighted_point_tag> >::type CWPBase;
+ typedef typename Get_functor<Kbase, Point_drop_weight_tag>::type PDWBase;
+ typedef typename Get_functor<Kbase, Point_weight_tag>::type PWBase;
+
+ typedef Weighted_point_d Self;
+ BOOST_STATIC_ASSERT((boost::is_same<Self, typename Get_type<R_, Weighted_point_tag>::type>::value));
+
+public:
+
+ typedef Tag_true Is_wrapper;
+ typedef typename R_::Default_ambient_dimension Ambient_dimension;
+ typedef Dimension_tag<0> Feature_dimension;
+
+ typedef typename Get_type<Kbase, Weighted_point_tag>::type Rep;
+
+ const Rep& rep() const
+ {
+ return *this;
+ }
+
+ Rep& rep()
+ {
+ return *this;
+ }
+
+ typedef R_ R;
+
+#ifdef CGAL_CXX11
+ template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Weighted_point_d> >::value>::type> explicit Weighted_point_d(U&&...u)
+ : Rep(CWPBase()(std::forward<U>(u)...)){}
+
+// // called from Construct_point_d
+// template<class...U> explicit Point_d(Eval_functor&&,U&&...u)
+// : Rep(Eval_functor(), std::forward<U>(u)...){}
+ template<class F,class...U> explicit Weighted_point_d(Eval_functor&&,F&&f,U&&...u)
+ : Rep(std::forward<F>(f)(std::forward<U>(u)...)){}
+
+#if 0
+ // the new standard may make this necessary
+ Point_d(Point_d const&)=default;
+ Point_d(Point_d &);//=default;
+ Point_d(Point_d &&)=default;
+#endif
+
+ // try not to use these
+ Weighted_point_d(Rep const& v) : Rep(v) {}
+ Weighted_point_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {}
+ Weighted_point_d(Rep&& v) : Rep(std::move(v)) {}
+
+#else
+
+ Weighted_point_d() : Rep(CWPBase()()) {}
+
+ Weighted_point_d(Rep const& v) : Rep(v) {} // try not to use it
+
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ explicit Weighted_point_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(CWPBase()( \
+ BOOST_PP_ENUM_PARAMS(N,t))) {} \
+ \
+ template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Weighted_point_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {}
+ /*
+ template<BOOST_PP_ENUM_PARAMS(N,class T)> \
+ Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \
+ : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {}
+ */
+
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+
+#endif
+
+ //TODO: use references?
+ Point_ point()const{
+ return Point_(Eval_functor(),PDWBase(),rep());
+ }
+ FT_ weight()const{
+ return PWBase()(rep());
+ }
+
+};
+
+} //namespace Wrap
+} //namespace CGAL
+
+#endif // CGAL_WRAPPER_SPHERE_D_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h b/include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h
new file mode 100644
index 00000000..5a132ad2
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h
@@ -0,0 +1,1355 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_KERNEL_D_FUNCTION_OBJECTS_CARTESIAN_H
+#define CGAL_KERNEL_D_FUNCTION_OBJECTS_CARTESIAN_H
+
+#include <CGAL/NewKernel_d/utils.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/Uncertain.h>
+#include <CGAL/NewKernel_d/store_kernel.h>
+#include <CGAL/is_iterator.h>
+#include <CGAL/iterator_from_indices.h>
+#include <CGAL/number_utils.h>
+#include <CGAL/Kernel/Return_base_tag.h>
+#include <CGAL/transforming_iterator.h>
+#include <CGAL/transforming_pair_iterator.h>
+#include <CGAL/NewKernel_d/functor_tags.h>
+#include <CGAL/NewKernel_d/functor_properties.h>
+#include <CGAL/predicates/sign_of_determinant.h>
+#include <functional>
+#ifdef CGAL_CXX11
+#include <initializer_list>
+#endif
+
+namespace CGAL {
+namespace CartesianDKernelFunctors {
+namespace internal {
+template<class,int> struct Dimension_at_most { enum { value = false }; };
+template<int a,int b> struct Dimension_at_most<Dimension_tag<a>,b> {
+ enum { value = (a <= b) };
+};
+}
+
+template<class R_,class D_=typename R_::Default_ambient_dimension,bool=internal::Dimension_at_most<D_,6>::value> struct Orientation_of_points : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Orientation_of_points)
+ typedef R_ R;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ typedef typename R::LA::Square_matrix Matrix;
+
+ template<class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+ Point const& p0=*f++;
+ int d=pd(p0);
+ Matrix m(d,d);
+ // FIXME: this writes the vector coordinates in lines ? check all the other uses in this file, this may be wrong for some.
+ for(int i=0;f!=e;++f,++i) {
+ Point const& p=*f;
+ for(int j=0;j<d;++j){
+ m(i,j)=c(p,j)-c(p0,j);
+ // should we cache the coordinates of p0 in case they are computed?
+ }
+ }
+ return R::LA::sign_of_determinant(CGAL_MOVE(m));
+ }
+
+#ifdef CGAL_CXX11
+ // Since the dimension is at least 2, there are at least 3 points and no ambiguity with iterators.
+ // template <class...U,class=typename std::enable_if<std::is_same<Dimension_tag<sizeof...(U)-1>,typename R::Default_ambient_dimension>::value>::type>
+ template <class...U,class=typename std::enable_if<(sizeof...(U)>=3)>::type>
+ result_type operator()(U&&...u) const {
+ return operator()({std::forward<U>(u)...});
+ }
+
+ template <class P>
+ result_type operator()(std::initializer_list<P> l) const {
+ return operator()(l.begin(),l.end());
+ }
+#else
+ //should we make it template to avoid instantiation for wrong dim?
+ //or iterate outside the class?
+#define CGAL_VAR(Z,J,I) m(I,J)=c(p##I,J)-c(x,J);
+#define CGAL_VAR2(Z,I,N) BOOST_PP_REPEAT(N,CGAL_VAR,I)
+#define CGAL_CODE(Z,N,_) \
+ result_type operator()(Point const&x, BOOST_PP_ENUM_PARAMS(N,Point const&p)) const { \
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); \
+ Matrix m(N,N); \
+ BOOST_PP_REPEAT(N,CGAL_VAR2,N) \
+ return R::LA::sign_of_determinant(CGAL_MOVE(m)); \
+ }
+
+BOOST_PP_REPEAT_FROM_TO(7, 10, CGAL_CODE, _ )
+ // No need to do it for <=6, since that uses a different code path
+#undef CGAL_CODE
+#undef CGAL_VAR2
+#undef CGAL_VAR
+#endif
+};
+
+#ifdef CGAL_CXX11
+template<class R_,int d> struct Orientation_of_points<R_,Dimension_tag<d>,true> : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Orientation_of_points)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ template<class>struct Help;
+ template<int...I>struct Help<Indices<I...> > {
+ template<class C,class P,class T> result_type operator()(C const&c,P const&x,T&&t)const{
+ return sign_of_determinant<RT>(c(std::get<I/d>(t),I%d)-c(x,I%d)...);
+ }
+ };
+ template<class P0,class...P> result_type operator()(P0 const&x,P&&...p)const{
+ static_assert(d==sizeof...(P),"Wrong number of arguments");
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ return Help<typename N_increasing_indices<d*d>::type>()(c,x,std::forward_as_tuple(std::forward<P>(p)...));
+ }
+
+
+ template<int N,class Iter,class...U> result_type help2(Dimension_tag<N>, Iter f, Iter const&e, U&&...u)const{
+ auto const&p=*f;
+ return help2(Dimension_tag<N-1>(),++f,e,std::forward<U>(u)...,p);
+ }
+ template<class Iter,class...U> result_type help2(Dimension_tag<0>, Iter CGAL_assertion_code(f), Iter const& CGAL_assertion_code(e), U&&...u)const{
+ CGAL_assertion(f==e);
+ return operator()(std::forward<U>(u)...);
+ }
+ template<class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ return help2(Dimension_tag<d+1>(),f,e);
+ }
+};
+#else
+#define CGAL_VAR(Z,J,I) c(p##I,J)-x##J
+#define CGAL_VAR2(Z,I,N) BOOST_PP_ENUM(N,CGAL_VAR,I)
+#define CGAL_VAR3(Z,N,_) Point const&p##N=*++f;
+#define CGAL_VAR4(Z,N,_) RT const&x##N=c(x,N);
+#define CGAL_CODE(Z,N,_) \
+template<class R_> struct Orientation_of_points<R_,Dimension_tag<N>,true> : private Store_kernel<R_> { \
+ CGAL_FUNCTOR_INIT_STORE(Orientation_of_points) \
+ typedef R_ R; \
+ typedef typename Get_type<R, RT_tag>::type RT; \
+ typedef typename Get_type<R, Point_tag>::type Point; \
+ typedef typename Get_type<R, Orientation_tag>::type result_type; \
+ result_type operator()(Point const&x, BOOST_PP_ENUM_PARAMS(N,Point const&p)) const { \
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); \
+ BOOST_PP_REPEAT(N,CGAL_VAR4,) \
+ return sign_of_determinant<RT>(BOOST_PP_ENUM(N,CGAL_VAR2,N)); \
+ } \
+ template<class Iter> \
+ result_type operator()(Iter f, Iter CGAL_assertion_code(e))const{ \
+ Point const&x=*f; \
+ BOOST_PP_REPEAT(N,CGAL_VAR3,) \
+ CGAL_assertion(++f==e); \
+ return operator()(x,BOOST_PP_ENUM_PARAMS(N,p)); \
+ } \
+};
+
+ BOOST_PP_REPEAT_FROM_TO(2, 7, CGAL_CODE, _ )
+#undef CGAL_CODE
+#undef CGAL_VAR4
+#undef CGAL_VAR3
+#undef CGAL_VAR2
+#undef CGAL_VAR
+
+#endif
+
+template<class R_> struct Orientation_of_points<R_,Dimension_tag<1>,true> : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Orientation_of_points)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ result_type operator()(Point const&x, Point const&y) const {
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ // No sign_of_determinant(RT) :-(
+ return CGAL::compare(c(y,0),c(x,0));
+ }
+ template<class Iter>
+ result_type operator()(Iter f, Iter CGAL_assertion_code(e))const{
+ Point const&x=*f;
+ Point const&y=*++f;
+ CGAL_assertion(++f==e);
+ return operator()(x,y);
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Orientation_of_points_tag,(CartesianDKernelFunctors::Orientation_of_points<K>),(Point_tag),(Point_dimension_tag,Compute_point_cartesian_coordinate_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Orientation_of_vectors : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Orientation_of_vectors)
+ typedef R_ R;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ typedef typename R::LA::Square_matrix Matrix;
+
+ template<class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ typename Get_functor<R, Compute_vector_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel());
+ // FIXME: Uh? Using it on a vector ?!
+ Vector const& v0=*f;
+ int d=vd(v0);
+ Matrix m(d,d);
+ for(int j=0;j<d;++j){
+ m(0,j)=c(v0,j);
+ }
+ for(int i=1;++f!=e;++i) {
+ Vector const& v=*f;
+ for(int j=0;j<d;++j){
+ m(i,j)=c(v,j);
+ }
+ }
+ return R::LA::sign_of_determinant(CGAL_MOVE(m));
+ }
+
+#ifdef CGAL_CXX11
+ template <class...U,class=typename std::enable_if<(sizeof...(U)>=3)>::type>
+ result_type operator()(U&&...u) const {
+ return operator()({std::forward<U>(u)...});
+ }
+
+ template <class V>
+ result_type operator()(std::initializer_list<V> l) const {
+ return operator()(l.begin(),l.end());
+ }
+#else
+ //TODO
+#endif
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Orientation_of_vectors_tag,(CartesianDKernelFunctors::Orientation_of_vectors<K>),(Vector_tag),(Point_dimension_tag,Compute_vector_cartesian_coordinate_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Linear_rank : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Linear_rank)
+ typedef R_ R;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ // Computing a sensible Uncertain<int> is not worth it
+ typedef int result_type;
+ typedef typename R::LA::Dynamic_matrix Matrix;
+
+ template<class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ typename Get_functor<R, Compute_vector_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel());
+ std::ptrdiff_t n=std::distance(f,e);
+ if (n==0) return 0;
+ Vector const& v0 = *f;
+ // FIXME: Uh? Using it on a vector ?!
+ int d=vd(v0);
+ Matrix m(d,n);
+ for(int j=0;j<d;++j){
+ m(j,0)=c(v0,j);
+ }
+ for(int i=1; ++f!=e; ++i){
+ Vector const& v = *f;
+ for(int j=0;j<d;++j){
+ m(j,i)=c(v,j);
+ }
+ }
+ return R::LA::rank(CGAL_MOVE(m));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Linear_rank_tag,(CartesianDKernelFunctors::Linear_rank<K>),(Vector_tag),(Point_dimension_tag,Compute_vector_cartesian_coordinate_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Linearly_independent : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Linearly_independent)
+ typedef R_ R;
+ typedef typename Get_type<R, Bool_tag>::type result_type;
+
+ template<class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel());
+ std::ptrdiff_t n=std::distance(f,e);
+ // FIXME: Uh? Using it on a vector ?!
+ int d=vd(*f);
+ if (n>d) return false;
+ typename Get_functor<R, Linear_rank_tag>::type lr(this->kernel());
+ return lr(f,e) == n;
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Linearly_independent_tag,(CartesianDKernelFunctors::Linearly_independent<K>),(Vector_tag),(Point_dimension_tag,Linear_rank_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Contained_in_linear_hull : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Contained_in_linear_hull)
+ typedef R_ R;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ // Computing a sensible Uncertain<bool> is not worth it
+ typedef bool result_type;
+ typedef typename R::LA::Dynamic_matrix Matrix;
+
+ template<class Iter,class V>
+ result_type operator()(Iter f, Iter e,V const&w)const{
+ typename Get_functor<R, Compute_vector_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel());
+ std::ptrdiff_t n=std::distance(f,e);
+ if (n==0) return false;
+ // FIXME: Uh? Using it on a vector ?!
+ int d=vd(w);
+ Matrix m(d,n+1);
+ for(int i=0; f!=e; ++f,++i){
+ Vector const& v = *f;
+ for(int j=0;j<d;++j){
+ m(j,i)=c(v,j);
+ }
+ }
+ for(int j=0;j<d;++j){
+ m(j,n)=c(w,j);
+ }
+ int r1 = R::LA::rank(m);
+ // FIXME: Don't use eigen directly, go through an interface in LA...
+ m.conservativeResize(Eigen::NoChange, n);
+ int r2 = R::LA::rank(CGAL_MOVE(m));
+ return r1 == r2;
+ // TODO: This is very very far from optimal...
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Contained_in_linear_hull_tag,(CartesianDKernelFunctors::Contained_in_linear_hull<K>),(Vector_tag),(Point_dimension_tag,Compute_vector_cartesian_coordinate_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Affine_rank : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Affine_rank)
+ typedef R_ R;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ // Computing a sensible Uncertain<int> is not worth it
+ typedef int result_type;
+ typedef typename R::LA::Dynamic_matrix Matrix;
+
+ template<class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+ int n=(int)std::distance(f,e);
+ if (--n<=0) return n;
+ Point const& p0 = *f;
+ int d=pd(p0);
+ Matrix m(d,n);
+ for(int i=0; ++f!=e; ++i){
+ Point const& p = *f;
+ for(int j=0;j<d;++j){
+ m(j,i)=c(p,j)-c(p0,j);
+ // TODO: cache p0[j] in case it is computed?
+ }
+ }
+ return R::LA::rank(CGAL_MOVE(m));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Affine_rank_tag,(CartesianDKernelFunctors::Affine_rank<K>),(Point_tag),(Point_dimension_tag,Compute_point_cartesian_coordinate_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Affinely_independent : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Affinely_independent)
+ typedef R_ R;
+ typedef typename Get_type<R, Bool_tag>::type result_type;
+
+ template<class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+ std::ptrdiff_t n=std::distance(f,e);
+ int d=pd(*f);
+ if (--n>d) return false;
+ typename Get_functor<R, Affine_rank_tag>::type ar(this->kernel());
+ return ar(f,e) == n;
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Affinely_independent_tag,(CartesianDKernelFunctors::Affinely_independent<K>),(Point_tag),(Point_dimension_tag,Affine_rank_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Contained_in_simplex : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Contained_in_simplex)
+ typedef R_ R;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ // Computing a sensible Uncertain<*> is not worth it
+ // typedef typename Get_type<R, Boolean_tag>::type result_type;
+ typedef bool result_type;
+ typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1;
+ typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2;
+ typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA;
+ typedef typename LA::Dynamic_matrix Matrix;
+ typedef typename LA::Dynamic_vector DynVec;
+ typedef typename LA::Vector Vec;
+
+ template<class Iter, class P>
+ result_type operator()(Iter f, Iter e, P const&q)const{
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+ std::ptrdiff_t n=std::distance(f,e);
+ if (n==0) return false;
+ int d=pd(q);
+ Matrix m(d+1,n);
+ DynVec a(n);
+ // FIXME: Should use the proper vector constructor (Iterator_and_last)
+ Vec b(d+1);
+ for(int j=0;j<d;++j) b[j]=c(q,j);
+ b[d]=1;
+
+ for(int i=0; f!=e; ++i,++f){
+ Point const& p = *f;
+ for(int j=0;j<d;++j){
+ m(j,i)=c(p,j);
+ }
+ m(d,i)=1;
+ }
+ // If the simplex has full dimension, there must be a solution, only the signs need to be checked.
+ if (n == d+1)
+ LA::solve(a,CGAL_MOVE(m),CGAL_MOVE(b));
+ else if (!LA::solve_and_check(a,CGAL_MOVE(m),CGAL_MOVE(b)))
+ return false;
+ for(int i=0;i<n;++i){
+ if (a[i]<0) return false;
+ }
+ return true;
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Contained_in_simplex_tag,(CartesianDKernelFunctors::Contained_in_simplex<K>),(Point_tag),(Point_dimension_tag,Compute_point_cartesian_coordinate_tag));
+
+namespace CartesianDKernelFunctors {
+ namespace internal {
+ template<class Ref_>
+ struct Matrix_col_access {
+ typedef Ref_ result_type;
+ int col;
+ Matrix_col_access(int r):col(r){}
+ template<class Mat> Ref_ operator()(Mat const& m, std::ptrdiff_t row)const{
+ return m(row,col);
+ }
+ };
+ }
+template<class R_> struct Linear_base : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Linear_base)
+ typedef R_ R;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef void result_type;
+ typedef typename R::LA::Dynamic_matrix Matrix;
+
+ template<class Iter, class Oter>
+ result_type operator()(Iter f, Iter e, Oter&o)const{
+ typename Get_functor<R, Compute_vector_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel());
+ typename Get_functor<R, Construct_ttag<Vector_tag> >::type cv(this->kernel());
+ std::ptrdiff_t n=std::distance(f,e);
+ if (n==0) return;
+ Vector const& v0 = *f;
+ // FIXME: Uh? Using it on a vector ?!
+ int d=vd(v0);
+ Matrix m(d,n);
+ for(int j=0;j<d;++j){
+ m(0,j)=c(v0,j);
+ }
+ for(int i=1; ++f!=e; ++i){
+ Vector const& v = *f;
+ for(int j=0;j<d;++j){
+ m(i,j)=c(v,j);
+ }
+ }
+ Matrix b = R::LA::basis(CGAL_MOVE(m));
+ for(int i=0; i < R::LA::columns(b); ++i){
+ //*o++ = Vector(b.col(i));
+ typedef
+#ifdef CGAL_CXX11
+ decltype(std::declval<const Matrix>()(0,0))
+#else
+ FT
+#endif
+ Ref;
+ typedef Iterator_from_indices<Matrix, FT, Ref,
+ internal::Matrix_col_access<Ref> > IFI;
+ *o++ = cv(IFI(b,0,i),IFI(b,d,i));
+ }
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Linear_base_tag,(CartesianDKernelFunctors::Linear_base<K>),(Vector_tag),(Point_dimension_tag,Compute_vector_cartesian_coordinate_tag));
+
+#if 0
+namespace CartesianDKernelFunctors {
+template<class R_,bool=boost::is_same<typename R_::Point,typename R_::Vector>::value> struct Orientation : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Orientation)
+ typedef R_ R;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ typedef typename Get_functor<R, Orientation_of_points_tag>::type OP;
+ typedef typename Get_functor<R, Orientation_of_vectors_tag>::type OV;
+
+ //FIXME!!!
+ //when Point and Vector are distinct types, the dispatch should be made
+ //in a way that doesn't instantiate a conversion from Point to Vector
+ template<class Iter>
+ result_type operator()(Iter const&f, Iter const& e)const{
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+ typename std::iterator_traits<Iter>::difference_type d=std::distance(f,e);
+ int dim=pd(*f); // BAD
+ if(d==dim) return OV(this->kernel())(f,e);
+ CGAL_assertion(d==dim+1);
+ return OP(this->kernel())(f,e);
+ }
+ //TODO: version that takes objects directly instead of iterators
+};
+
+template<class R_> struct Orientation<R_,false> : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Orientation)
+ typedef R_ R;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Orientation_tag>::type result_type;
+ typedef typename Get_functor<R, Orientation_of_points_tag>::type OP;
+ typedef typename Get_functor<R, Orientation_of_vectors_tag>::type OV;
+ typedef typename R::LA::Square_matrix Matrix;
+
+ //FIXME!!!
+ //when Point and Vector are distinct types, the dispatch should be made
+ //in a way that doesn't instantiate a conversion from Point to Vector
+ template<class Iter>
+ typename boost::enable_if<is_iterator_to<Iter,Point>,result_type>::type
+ operator()(Iter const&f, Iter const& e)const{
+ return OP(this->kernel())(f,e);
+ }
+ template<class Iter>
+ typename boost::enable_if<is_iterator_to<Iter,Vector>,result_type>::type
+ operator()(Iter const&f, Iter const& e)const{
+ return OV(this->kernel())(f,e);
+ }
+ //TODO: version that takes objects directly instead of iterators
+};
+}
+#endif
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Power_side_of_power_sphere_raw : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere_raw)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Oriented_side_tag>::type result_type;
+ typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1;
+ typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2;
+ typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA;
+ typedef typename LA::Square_matrix Matrix;
+
+ template<class IterP, class IterW, class Pt, class Wt>
+ result_type operator()(IterP f, IterP const& e, IterW fw, Pt const& p0, Wt const& w0) const {
+ typedef typename Get_functor<R, Squared_distance_to_origin_tag>::type Sqdo;
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+
+ int d=pd(p0);
+ Matrix m(d+1,d+1);
+ if(CGAL::Is_stored<Sqdo>::value) {
+ Sqdo sqdo(this->kernel());
+ FT const& h0 = sqdo(p0) - w0;
+ for(int i=0;f!=e;++f,++fw,++i) {
+ Point const& p=*f;
+ for(int j=0;j<d;++j){
+ RT const& x=c(p,j);
+ m(i,j)=x-c(p0,j);
+ }
+ m(i,d) = sqdo(p) - *fw - h0;
+ }
+ } else {
+ for(int i=0;f!=e;++f,++fw,++i) {
+ Point const& p=*f;
+ m(i,d) = w0 - *fw;
+ for(int j=0;j<d;++j){
+ RT const& x=c(p,j);
+ m(i,j)=x-c(p0,j);
+ m(i,d)+=CGAL::square(m(i,j));
+ }
+ }
+ }
+ if(d%2)
+ return -LA::sign_of_determinant(CGAL_MOVE(m));
+ else
+ return LA::sign_of_determinant(CGAL_MOVE(m));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_power_sphere_raw_tag,(CartesianDKernelFunctors::Power_side_of_power_sphere_raw<K>),(Point_tag),(Point_dimension_tag,Squared_distance_to_origin_tag,Compute_point_cartesian_coordinate_tag));
+
+// TODO: make Side_of_oriented_sphere call Power_side_of_power_sphere_raw
+namespace CartesianDKernelFunctors {
+template<class R_> struct Side_of_oriented_sphere : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Side_of_oriented_sphere)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Oriented_side_tag>::type result_type;
+ typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1;
+ typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2;
+ typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA;
+ typedef typename LA::Square_matrix Matrix;
+
+ template<class Iter>
+ result_type operator()(Iter f, Iter const& e)const{
+ Point const& p0=*f++; // *--e ?
+ return this->operator()(f,e,p0);
+ }
+
+ template<class Iter>
+ result_type operator()(Iter f, Iter const& e, Point const& p0) const {
+ typedef typename Get_functor<R, Squared_distance_to_origin_tag>::type Sqdo;
+ typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+
+ int d=pd(p0);
+ Matrix m(d+1,d+1);
+ if(CGAL::Is_stored<Sqdo>::value) {
+ Sqdo sqdo(this->kernel());
+ for(int i=0;f!=e;++f,++i) {
+ Point const& p=*f;
+ for(int j=0;j<d;++j){
+ RT const& x=c(p,j);
+ m(i,j)=x-c(p0,j);
+ }
+ m(i,d) = sqdo(p) - sqdo(p0);
+ }
+ } else {
+ for(int i=0;f!=e;++f,++i) {
+ Point const& p=*f;
+ m(i,d) = 0;
+ for(int j=0;j<d;++j){
+ RT const& x=c(p,j);
+ m(i,j)=x-c(p0,j);
+ m(i,d)+=CGAL::square(m(i,j));
+ }
+ }
+ }
+ if(d%2)
+ return -LA::sign_of_determinant(CGAL_MOVE(m));
+ else
+ return LA::sign_of_determinant(CGAL_MOVE(m));
+ }
+
+#ifdef CGAL_CXX11
+ template <class...U,class=typename std::enable_if<(sizeof...(U)>=4)>::type>
+ result_type operator()(U&&...u) const {
+ return operator()({std::forward<U>(u)...});
+ }
+
+ template <class P>
+ result_type operator()(std::initializer_list<P> l) const {
+ return operator()(l.begin(),l.end());
+ }
+#else
+ //TODO
+#endif
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Side_of_oriented_sphere_tag,(CartesianDKernelFunctors::Side_of_oriented_sphere<K>),(Point_tag),(Point_dimension_tag,Squared_distance_to_origin_tag,Compute_point_cartesian_coordinate_tag));
+
+namespace CartesianDKernelFunctors {
+template <class R_> struct Construct_circumcenter : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Construct_circumcenter)
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef Point result_type;
+ typedef typename Get_type<R_, FT_tag>::type FT;
+ template <class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ typedef typename Get_type<R_, Point_tag>::type Point;
+ typedef typename R_::LA LA;
+ typename Get_functor<R_, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
+ typename Get_functor<R_, Construct_ttag<Point_tag> >::type cp(this->kernel());
+ typename Get_functor<R_, Point_dimension_tag>::type pd(this->kernel());
+ typename Get_functor<R_, Squared_distance_to_origin_tag>::type sdo(this->kernel());
+
+ Point const& p0=*f;
+ int d = pd(p0);
+ if (d+1 == std::distance(f,e))
+ {
+ // 2*(x-y).c == x^2-y^2
+ typedef typename LA::Square_matrix Matrix;
+ typedef typename LA::Vector Vec;
+ typedef typename LA::Construct_vector CVec;
+ FT const& n0 = sdo(p0);
+ Matrix m(d,d);
+ Vec b = typename CVec::Dimension()(d);
+ // Write the point coordinates in lines.
+ int i;
+ for(i=0; ++f!=e; ++i) {
+ Point const& p=*f;
+ for(int j=0;j<d;++j) {
+ m(i,j)=2*(c(p,j)-c(p0,j));
+ b[i] = sdo(p) - n0;
+ }
+ }
+ CGAL_assertion (i == d);
+ Vec res = typename CVec::Dimension()(d);;
+ //std::cout << "Mat: " << m << "\n Vec: " << one << std::endl;
+ LA::solve(res, CGAL_MOVE(m), CGAL_MOVE(b));
+ //std::cout << "Sol: " << res << std::endl;
+ return cp(d,LA::vector_begin(res),LA::vector_end(res));
+ }
+ else
+ {
+ /*
+ * Matrix P=(p1, p2, ...) (each point as a column)
+ * Matrix Q=2*t(p2-p1,p3-p1, ...) (each vector as a line)
+ * Matrix M: QP, adding a line of 1 at the top
+ * Vector B: (1, p2^2-p1^2, p3^2-p1^2, ...)
+ * Solve ML=B, the center of the sphere is PL
+ *
+ * It would likely be faster to write P then transpose, multiply,
+ * etc instead of doing it by hand.
+ */
+ // TODO: check for degenerate cases?
+
+ typedef typename R_::Max_ambient_dimension D2;
+ typedef typename R_::LA::template Rebind_dimension<Dynamic_dimension_tag,D2>::Other LAd;
+ typedef typename LAd::Square_matrix Matrix;
+ typedef typename LAd::Vector Vec;
+ typename Get_functor<R_, Scalar_product_tag>::type sp(this->kernel());
+ int k=static_cast<int>(std::distance(f,e));
+ Matrix m(k,k);
+ Vec b(k);
+ Vec l(k);
+ int j,i=0;
+ for(Iter f2=f;f2!=e;++f2,++i){
+ b(i)=m(i,i)=sdo(*f2);
+ j=0;
+ for(Iter f3=f;f3!=e;++f3,++j){
+ m(j,i)=m(i,j)=sp(*f2,*f3);
+ }
+ }
+ for(i=1;i<k;++i){
+ b(i)-=b(0);
+ for(j=0;j<k;++j){
+ m(i,j)=2*(m(i,j)-m(0,j));
+ }
+ }
+ for(j=0;j<k;++j) m(0,j)=1;
+ b(0)=1;
+
+ LAd::solve(l,CGAL_MOVE(m),CGAL_MOVE(b));
+
+ typename LA::Vector center=typename LA::Construct_vector::Dimension()(d);
+ for(i=0;i<d;++i) center(i)=0;
+ j=0;
+ for(Iter f2=f;f2!=e;++f2,++j){
+ for(i=0;i<d;++i){
+ center(i)+=l(j)*c(*f2,i);
+ }
+ }
+
+ return cp(LA::vector_begin(center),LA::vector_end(center));
+ }
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Construct_circumcenter_tag,(CartesianDKernelFunctors::Construct_circumcenter<K>),(Point_tag),(Construct_ttag<Point_tag>,Compute_point_cartesian_coordinate_tag,Scalar_product_tag,Squared_distance_to_origin_tag,Point_dimension_tag));
+
+namespace CartesianDKernelFunctors {
+template <class R_> struct Squared_circumradius : Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Squared_circumradius)
+ typedef typename Get_type<R_, FT_tag>::type result_type;
+ template <class Iter>
+ result_type operator()(Iter f, Iter e)const{
+ typename Get_functor<R_, Construct_circumcenter_tag>::type cc(this->kernel());
+ typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel());
+ return sd(cc(f, e), *f);
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Squared_circumradius_tag,(CartesianDKernelFunctors::Squared_circumradius<K>),(Point_tag),(Construct_circumcenter_tag,Squared_distance_tag));
+
+namespace CartesianDKernelFunctors {
+// TODO: implement it directly, it should be at least as fast as Side_of_oriented_sphere.
+template<class R_> struct Side_of_bounded_sphere : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Side_of_bounded_sphere)
+ typedef R_ R;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Bounded_side_tag>::type result_type;
+
+ template<class Iter>
+ result_type operator()(Iter f, Iter const& e) const {
+ Point const& p0 = *f++; // *--e ?
+ typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel());
+ //FIXME: Doesn't work for non-full dimension.
+ CGAL_assertion (std::distance(f,e) == pd(p0)+1);
+ return operator() (f, e, p0);
+ }
+
+ template<class Iter>
+ result_type operator()(Iter const& f, Iter const& e, Point const& p0) const {
+ typename Get_functor<R, Side_of_oriented_sphere_tag>::type sos (this->kernel());
+ typename Get_functor<R, Orientation_of_points_tag>::type op (this->kernel());
+ // enum_cast is not very generic, but since this function isn't supposed to remain like this...
+ return enum_cast<Bounded_side> (sos (f, e, p0) * op (f, e));
+ }
+
+#ifdef CGAL_CXX11
+ template <class...U,class=typename std::enable_if<(sizeof...(U)>=4)>::type>
+ result_type operator()(U&&...u) const {
+ return operator()({std::forward<U>(u)...});
+ }
+
+ template <class P>
+ result_type operator()(std::initializer_list<P> l) const {
+ return operator()(l.begin(),l.end());
+ }
+#else
+ //TODO
+#endif
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Side_of_bounded_sphere_tag,(CartesianDKernelFunctors::Side_of_bounded_sphere<K>),(Point_tag),(Side_of_oriented_sphere_tag,Orientation_of_points_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Side_of_bounded_circumsphere : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Side_of_bounded_circumsphere)
+ typedef typename Get_type<R_, Bounded_side_tag>::type result_type;
+
+ template<class Iter, class P>
+ result_type operator()(Iter f, Iter const& e, P const& p0) const {
+ // TODO: Special case when the dimension is full.
+ typename Get_functor<R_, Construct_circumcenter_tag>::type cc(this->kernel());
+ typename Get_functor<R_, Compare_distance_tag>::type cd(this->kernel());
+
+ return enum_cast<Bounded_side>(cd(cc(f, e), *f, p0));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Side_of_bounded_circumsphere_tag,(CartesianDKernelFunctors::Side_of_bounded_circumsphere<K>),(Point_tag),(Squared_distance_tag,Construct_circumcenter_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Point_to_vector : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Point_to_vector)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV;
+ typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI;
+ typedef Vector result_type;
+ typedef Point argument_type;
+ result_type operator()(argument_type const&v)const{
+ CI ci(this->kernel());
+ return CV(this->kernel())(ci(v,Begin_tag()),ci(v,End_tag()));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Point_to_vector_tag,(CartesianDKernelFunctors::Point_to_vector<K>),(Point_tag,Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Vector_to_point : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Vector_to_point)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_functor<R, Construct_ttag<Point_tag> >::type CP;
+ typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI;
+ typedef Point result_type;
+ typedef Vector argument_type;
+ result_type operator()(argument_type const&v)const{
+ CI ci(this->kernel());
+ return CP(this->kernel())(ci(v,Begin_tag()),ci(v,End_tag()));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Vector_to_point_tag,(CartesianDKernelFunctors::Vector_to_point<K>),(Point_tag,Vector_tag),(Construct_ttag<Point_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Opposite_vector : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Opposite_vector)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV;
+ typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI;
+ typedef Vector result_type;
+ typedef Vector argument_type;
+ result_type operator()(Vector const&v)const{
+ CI ci(this->kernel());
+ return CV(this->kernel())(make_transforming_iterator(ci(v,Begin_tag()),std::negate<RT>()),make_transforming_iterator(ci(v,End_tag()),std::negate<RT>()));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Opposite_vector_tag,(CartesianDKernelFunctors::Opposite_vector<K>),(Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Scaled_vector : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Scaled_vector)
+ typedef R_ R;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV;
+ typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI;
+ typedef Vector result_type;
+ typedef Vector first_argument_type;
+ typedef FT second_argument_type;
+ result_type operator()(Vector const&v,FT const& s)const{
+ CI ci(this->kernel());
+ return CV(this->kernel())(make_transforming_iterator(ci(v,Begin_tag()),Scale<FT>(s)),make_transforming_iterator(ci(v,End_tag()),Scale<FT>(s)));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Scaled_vector_tag,(CartesianDKernelFunctors::Scaled_vector<K>),(Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Sum_of_vectors : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Sum_of_vectors)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV;
+ typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI;
+ typedef Vector result_type;
+ typedef Vector first_argument_type;
+ typedef Vector second_argument_type;
+ result_type operator()(Vector const&a, Vector const&b)const{
+ CI ci(this->kernel());
+ return CV(this->kernel())(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),std::plus<RT>()),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),std::plus<RT>()));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Sum_of_vectors_tag,(CartesianDKernelFunctors::Sum_of_vectors<K>),(Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Difference_of_vectors : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Difference_of_vectors)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV;
+ typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI;
+ typedef Vector result_type;
+ typedef Vector first_argument_type;
+ typedef Vector second_argument_type;
+ result_type operator()(Vector const&a, Vector const&b)const{
+ CI ci(this->kernel());
+ return CV(this->kernel())(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),std::minus<RT>()),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),std::minus<RT>()));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Difference_of_vectors_tag,(CartesianDKernelFunctors::Difference_of_vectors<K>),(Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Translated_point : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Translated_point)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_functor<R, Construct_ttag<Point_tag> >::type CP;
+ typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CVI;
+ typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CPI;
+ typedef Point result_type;
+ typedef Point first_argument_type;
+ typedef Vector second_argument_type;
+ result_type operator()(Point const&a, Vector const&b)const{
+ CVI cvi(this->kernel());
+ CPI cpi(this->kernel());
+ return CP(this->kernel())(make_transforming_pair_iterator(cpi(a,Begin_tag()),cvi(b,Begin_tag()),std::plus<RT>()),make_transforming_pair_iterator(cpi(a,End_tag()),cvi(b,End_tag()),std::plus<RT>()));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Translated_point_tag,(CartesianDKernelFunctors::Translated_point<K>),(Point_tag, Vector_tag),(Construct_ttag<Point_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Difference_of_points : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Difference_of_points)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV;
+ typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI;
+ typedef Vector result_type;
+ typedef Point first_argument_type;
+ typedef Point second_argument_type;
+ result_type operator()(Point const&a, Point const&b)const{
+ CI ci(this->kernel());
+ return CV(this->kernel())(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),std::minus<RT>()),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),std::minus<RT>()));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Difference_of_points_tag,(CartesianDKernelFunctors::Difference_of_points<K>),(Point_tag, Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Midpoint : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Midpoint)
+ typedef R_ R;
+ typedef typename Get_type<R, FT_tag>::type FT;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_functor<R, Construct_ttag<Point_tag> >::type CP;
+ typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI;
+ typedef Point result_type;
+ typedef Point first_argument_type;
+ typedef Point second_argument_type;
+ // There is a division, but it will be cast to RT afterwards anyway, so maybe we could use RT.
+ struct Average : std::binary_function<FT,RT,FT> {
+ FT operator()(FT const&a, RT const&b)const{
+ return (a+b)/2;
+ }
+ };
+ result_type operator()(Point const&a, Point const&b)const{
+ CI ci(this->kernel());
+ //Divide<FT,int> half(2);
+ //return CP(this->kernel())(make_transforming_iterator(make_transforming_pair_iterator(ci.begin(a),ci.begin(b),std::plus<FT>()),half),make_transforming_iterator(make_transforming_pair_iterator(ci.end(a),ci.end(b),std::plus<FT>()),half));
+ return CP(this->kernel())(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),Average()),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),Average()));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Midpoint_tag,(CartesianDKernelFunctors::Midpoint<K>),(Point_tag),(Construct_ttag<Point_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Squared_length : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Squared_length)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI;
+ typedef RT result_type;
+ typedef Vector argument_type;
+ result_type operator()(Vector const&a)const{
+ CI ci(this->kernel());
+ typename Algebraic_structure_traits<RT>::Square f;
+ // TODO: avoid this RT(0)+...
+ return std::accumulate(make_transforming_iterator(ci(a,Begin_tag()),f),make_transforming_iterator(ci(a,End_tag()),f),RT(0));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Squared_length_tag,(CartesianDKernelFunctors::Squared_length<K>),(Vector_tag),(Construct_ttag<Vector_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Squared_distance_to_origin : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Squared_distance_to_origin)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI;
+ typedef RT result_type;
+ typedef Point argument_type;
+ result_type operator()(Point const&a)const{
+ CI ci(this->kernel());
+ typename Algebraic_structure_traits<RT>::Square f;
+ // TODO: avoid this RT(0)+...
+ return std::accumulate(make_transforming_iterator(ci(a,Begin_tag()),f),make_transforming_iterator(ci(a,End_tag()),f),RT(0));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Squared_distance_to_origin_tag,(CartesianDKernelFunctors::Squared_distance_to_origin<K>),(Point_tag),(Construct_ttag<Point_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Squared_distance : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Squared_distance)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI;
+ typedef RT result_type;
+ typedef Point first_argument_type;
+ typedef Point second_argument_type;
+ struct Sq_diff : std::binary_function<RT,RT,RT> {
+ RT operator()(RT const&a, RT const&b)const{
+ return CGAL::square(a-b);
+ }
+ };
+ result_type operator()(Point const&a, Point const&b)const{
+ CI ci(this->kernel());
+ Sq_diff f;
+ // TODO: avoid this RT(0)+...
+ return std::accumulate(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),f),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),f),RT(0));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Squared_distance_tag,(CartesianDKernelFunctors::Squared_distance<K>),(Point_tag),(Construct_ttag<Point_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Scalar_product : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Scalar_product)
+ typedef R_ R;
+ typedef typename Get_type<R, RT_tag>::type RT;
+ typedef typename Get_type<R, Vector_tag>::type Vector;
+ typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI;
+ typedef RT result_type;
+ typedef Vector first_argument_type;
+ typedef Vector second_argument_type;
+ result_type operator()(Vector const&a, Vector const&b)const{
+ CI ci(this->kernel());
+ std::multiplies<RT> f;
+ // TODO: avoid this RT(0)+...
+ return std::accumulate(
+ make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),f),
+ make_transforming_pair_iterator(ci(a, End_tag()),ci(b, End_tag()),f),
+ RT(0));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Scalar_product_tag,(CartesianDKernelFunctors::Scalar_product<K>),(Vector_tag),(Construct_ttag<Vector_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Compare_distance : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Compare_distance)
+ typedef R_ R;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_functor<R, Squared_distance_tag>::type CSD;
+ typedef typename Get_type<R, Comparison_result_tag>::type result_type;
+ typedef Point first_argument_type;
+ typedef Point second_argument_type;
+ typedef Point third_argument_type; // why am I doing this already?
+ typedef Point fourth_argument_type;
+ result_type operator()(Point const&a, Point const&b, Point const&c)const{
+ CSD csd(this->kernel());
+ return CGAL_NTS compare(csd(a,b),csd(a,c));
+ }
+ result_type operator()(Point const&a, Point const&b, Point const&c, Point const&d)const{
+ CSD csd(this->kernel());
+ return CGAL_NTS compare(csd(a,b),csd(c,d));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Compare_distance_tag,(CartesianDKernelFunctors::Compare_distance<K>),(Point_tag),(Squared_distance_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Less_point_cartesian_coordinate : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Less_point_cartesian_coordinate)
+ typedef R_ R;
+ typedef typename Get_type<R, Bool_tag>::type result_type;
+ typedef typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type Cc;
+ // TODO: This is_exact thing should be reengineered.
+ // the goal is to have a way to tell: don't filter this
+ typedef typename CGAL::Is_exact<Cc> Is_exact;
+
+ template<class V,class W,class I>
+ result_type operator()(V const&a, W const&b, I i)const{
+ Cc c(this->kernel());
+ return c(a,i)<c(b,i);
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Less_point_cartesian_coordinate_tag,(CartesianDKernelFunctors::Less_point_cartesian_coordinate<K>),(),(Compute_point_cartesian_coordinate_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Compare_point_cartesian_coordinate : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Compare_point_cartesian_coordinate)
+ typedef R_ R;
+ typedef typename Get_type<R, Comparison_result_tag>::type result_type;
+ typedef typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type Cc;
+ // TODO: This is_exact thing should be reengineered.
+ // the goal is to have a way to tell: don't filter this
+ typedef typename CGAL::Is_exact<Cc> Is_exact;
+
+ template<class V,class W,class I>
+ result_type operator()(V const&a, W const&b, I i)const{
+ Cc c(this->kernel());
+ return CGAL_NTS compare(c(a,i),c(b,i));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Compare_point_cartesian_coordinate_tag,(CartesianDKernelFunctors::Compare_point_cartesian_coordinate<K>),(),(Compute_point_cartesian_coordinate_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Compare_lexicographically : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Compare_lexicographically)
+ typedef R_ R;
+ typedef typename Get_type<R, Comparison_result_tag>::type result_type;
+ typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI;
+ // TODO: This is_exact thing should be reengineered.
+ // the goal is to have a way to tell: don't filter this
+ typedef typename CGAL::Is_exact<CI> Is_exact;
+
+ template<class V,class W>
+ result_type operator()(V const&a, W const&b)const{
+ CI c(this->kernel());
+#ifdef CGAL_CXX11
+ auto
+#else
+ typename CI::result_type
+#endif
+ a_begin=c(a,Begin_tag()),
+ b_begin=c(b,Begin_tag()),
+ a_end=c(a,End_tag());
+ result_type res;
+ // can't we do slightly better for Uncertain<*> ?
+ // after res=...; if(is_uncertain(res))return indeterminate<result_type>();
+ do res=CGAL_NTS compare(*a_begin++,*b_begin++);
+ while(a_begin!=a_end && res==EQUAL);
+ return res;
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Compare_lexicographically_tag,(CartesianDKernelFunctors::Compare_lexicographically<K>),(),(Construct_ttag<Point_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Less_lexicographically : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Less_lexicographically)
+ typedef R_ R;
+ typedef typename Get_type<R, Bool_tag>::type result_type;
+ typedef typename Get_functor<R, Compare_lexicographically_tag>::type CL;
+ typedef typename CGAL::Is_exact<CL> Is_exact;
+
+ template <class V, class W>
+ result_type operator() (V const&a, W const&b) const {
+ CL c (this->kernel());
+ return c(a,b) < 0;
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Less_lexicographically_tag,(CartesianDKernelFunctors::Less_lexicographically<K>),(),(Compare_lexicographically_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Less_or_equal_lexicographically : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Less_or_equal_lexicographically)
+ typedef R_ R;
+ typedef typename Get_type<R, Bool_tag>::type result_type;
+ typedef typename Get_functor<R, Compare_lexicographically_tag>::type CL;
+ typedef typename CGAL::Is_exact<CL> Is_exact;
+
+ template <class V, class W>
+ result_type operator() (V const&a, W const&b) const {
+ CL c (this->kernel());
+ return c(a,b) <= 0;
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Less_or_equal_lexicographically_tag,(CartesianDKernelFunctors::Less_or_equal_lexicographically<K>),(),(Compare_lexicographically_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Equal_points : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Equal_points)
+ typedef R_ R;
+ typedef typename Get_type<R, Bool_tag>::type result_type;
+ typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI;
+ // TODO: This is_exact thing should be reengineered.
+ // the goal is to have a way to tell: don't filter this
+ typedef typename CGAL::Is_exact<CI> Is_exact;
+
+ template<class V,class W>
+ result_type operator()(V const&a, W const&b)const{
+ CI c(this->kernel());
+#ifdef CGAL_CXX11
+ auto
+#else
+ typename CI::result_type
+#endif
+ a_begin=c(a,Begin_tag()),
+ b_begin=c(b,Begin_tag()),
+ a_end=c(a,End_tag());
+ result_type res = true;
+ // Is using CGAL::possibly for Uncertain really an optimization?
+ do res = res & (*a_begin++ == *b_begin++);
+ while(a_begin!=a_end && possibly(res));
+ return res;
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Equal_points_tag,(CartesianDKernelFunctors::Equal_points<K>),(),(Construct_ttag<Point_cartesian_const_iterator_tag>));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Oriented_side : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Oriented_side)
+ typedef R_ R;
+ typedef typename Get_type<R, Oriented_side_tag>::type result_type;
+ typedef typename Get_type<R, Point_tag>::type Point;
+ typedef typename Get_type<R, Hyperplane_tag>::type Hyperplane;
+ typedef typename Get_type<R, Sphere_tag>::type Sphere;
+ typedef typename Get_functor<R, Value_at_tag>::type VA;
+ typedef typename Get_functor<R, Hyperplane_translation_tag>::type HT;
+ typedef typename Get_functor<R, Squared_distance_tag>::type SD;
+ typedef typename Get_functor<R, Squared_radius_tag>::type SR;
+ typedef typename Get_functor<R, Center_of_sphere_tag>::type CS;
+
+ result_type operator()(Hyperplane const&h, Point const&p)const{
+ HT ht(this->kernel());
+ VA va(this->kernel());
+ return CGAL::compare(va(h,p),ht(h));
+ }
+ result_type operator()(Sphere const&s, Point const&p)const{
+ SD sd(this->kernel());
+ SR sr(this->kernel());
+ CS cs(this->kernel());
+ return CGAL::compare(sd(cs(s),p),sr(s));
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Oriented_side_tag,(CartesianDKernelFunctors::Oriented_side<K>),(Point_tag,Sphere_tag,Hyperplane_tag),(Value_at_tag,Hyperplane_translation_tag,Squared_distance_tag,Squared_radius_tag,Center_of_sphere_tag));
+
+namespace CartesianDKernelFunctors {
+template<class R_> struct Has_on_positive_side : private Store_kernel<R_> {
+ CGAL_FUNCTOR_INIT_STORE(Has_on_positive_side)
+ typedef R_ R;
+ typedef typename Get_type<R, Bool_tag>::type result_type;
+ typedef typename Get_functor<R, Oriented_side_tag>::type OS;
+
+ template <class Obj, class Pt>
+ result_type operator()(Obj const&o, Pt const&p)const{
+ OS os(this->kernel());
+ return os(o,p) == ON_POSITIVE_SIDE;
+ }
+};
+}
+
+CGAL_KD_DEFAULT_FUNCTOR(Has_on_positive_side_tag,(CartesianDKernelFunctors::Has_on_positive_side<K>),(),(Oriented_side_tag));
+
+}
+#include <CGAL/NewKernel_d/Coaffine.h>
+#endif // CGAL_KERNEL_D_FUNCTION_OBJECTS_CARTESIAN_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h b/include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h
new file mode 100644
index 00000000..c25c4e2b
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_EXACTNESS_H
+#define CGAL_EXACTNESS_H
+#include <boost/mpl/has_xxx.hpp>
+#include <CGAL/tags.h>
+namespace CGAL {
+
+#define CGAL_STRAWBERRY(Is_pretty) \
+ namespace internal { \
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(Is_pretty) \
+ } \
+ template<class T,bool=internal::has_##Is_pretty<T>::value> \
+ struct Is_pretty : boost::false_type {}; \
+ template<class T> \
+ struct Is_pretty<T,true> : T::Is_pretty {}
+
+CGAL_STRAWBERRY(Is_exact);
+CGAL_STRAWBERRY(Is_fast);
+CGAL_STRAWBERRY(Is_stored);
+#undef CGAL_STRAWBERRY
+}
+#endif // CGAL_EXACTNESS_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h b/include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h
new file mode 100644
index 00000000..b8e17886
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h
@@ -0,0 +1,363 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_FUNCTOR_TAGS_H
+#define CGAL_FUNCTOR_TAGS_H
+#include <CGAL/tags.h> // for Null_tag
+#include <CGAL/NewKernel_d/utils.h>
+#ifdef CGAL_CXX11
+#include <type_traits>
+#include <utility>
+#endif
+#include <boost/type_traits.hpp>
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/empty.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/pop_front.hpp>
+namespace CGAL {
+
+ // Find a better place for this later
+
+ template <class K, class T, class=void> struct Get_type
+ : K::template Type<T> {};
+ template <class K, class F, class O=void, class=void> struct Get_functor
+ : K::template Functor<F, O> {};
+#ifdef CGAL_CXX11
+ template <class K, class T> using Type = typename Get_type<K, T>::type;
+ template <class K, class T> using Functor = typename Get_functor<K, T>::type;
+#endif
+
+ class Null_type {~Null_type();}; // no such object should be created
+
+ // To construct iterators
+ struct Begin_tag {};
+ struct End_tag {};
+
+ // Functor category
+ struct Predicate_tag {};
+ struct Construct_tag {};
+ struct Construct_iterator_tag {};
+ struct Compute_tag {};
+ struct Misc_tag {};
+
+ struct No_filter_tag {};
+
+ template<class>struct Construct_ttag {};
+ template<class>struct Convert_ttag {};
+
+ template <class K, class F, class=void, class=void> struct Get_functor_category { typedef Misc_tag type; };
+ template<class Tg, class Obj, class Base> struct Typedef_tag_type;
+ //template<class Kernel, class Tg> struct Read_tag_type {};
+
+ template<class Kernel, class Tg>
+ struct Provides_type
+ : Has_type_different_from<Get_type<Kernel, Tg>, Null_type> {};
+
+ template<class Kernel, class Tg, class O=void>
+ struct Provides_functor
+ : Has_type_different_from<Get_functor<Kernel, Tg, O>, Null_functor> {};
+
+ template<class K, class List, bool=boost::mpl::empty<List>::type::value>
+ struct Provides_functors : boost::mpl::and_ <
+ Provides_functor<K, typename boost::mpl::front<List>::type>,
+ Provides_functors<K, typename boost::mpl::pop_front<List>::type> > {};
+ template<class K, class List>
+ struct Provides_functors<K, List, true> : boost::true_type {};
+
+ template<class K, class List, bool=boost::mpl::empty<List>::type::value>
+ struct Provides_types : boost::mpl::and_ <
+ Provides_type<K, typename boost::mpl::front<List>::type>,
+ Provides_types<K, typename boost::mpl::pop_front<List>::type> > {};
+ template<class K, class List>
+ struct Provides_types<K, List, true> : boost::true_type {};
+
+ namespace internal { BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Type,template Type<Null_tag>,false) }
+ template<class Kernel, class Tg,
+ bool = internal::has_Type<Kernel>::value /* false */>
+ struct Provides_type_i : boost::false_type {};
+ template<class Kernel, class Tg>
+ struct Provides_type_i <Kernel, Tg, true>
+ : Has_type_different_from<typename Kernel::template Type<Tg>, Null_type> {};
+
+ //// This version does not like Functor<T,bool=false>
+ //namespace internal { BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(has_Functor,Functor,false) }
+ // This version lets us use non-type template parameters, but fails with older EDG-based compilers (Intel 14).
+ namespace internal { BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Functor,template Functor<Null_tag>,false) }
+
+ template<class Kernel, class Tg, class O=void,
+ bool = internal::has_Functor<Kernel>::value /* false */>
+ struct Provides_functor_i : boost::false_type {};
+ template<class Kernel, class Tg, class O>
+ struct Provides_functor_i <Kernel, Tg, O, true>
+ : Has_type_different_from<typename Kernel::template Functor<Tg, O>, Null_functor> {};
+
+ // TODO: Refine this a bit.
+ template <class K, class T, class D=void,
+ //bool=Provides_functor<K,T>::value,
+ //bool=Provides_functor_i<K,T>::value,
+ bool = internal::has_Functor<K>::value
+ >
+ struct Inherit_functor : K::template Functor<T> {};
+ template <class K, class T, class D>
+ struct Inherit_functor <K, T, D, false> {};
+
+ template <class K, class T, bool=internal::has_Type<K>::value>
+ struct Inherit_type : K::template Type<T> {};
+ template <class K, class T>
+ struct Inherit_type <K, T, false> {};
+
+ struct Number_tag {};
+ struct Discrete_tag {};
+ struct Object_tag {};
+ template <class K, class T, class=void> struct Get_type_category {
+ // The lazy kernel uses it too eagerly,
+ // so it currently needs a default.
+ typedef Null_tag type;
+ };
+
+#define CGAL_DECL_OBJ_(X,Y) \
+ template<class Obj,class Base> \
+ struct Typedef_tag_type<X##_tag, Obj, Base> : Base { typedef Obj X; }; \
+ template<class K, class D> \
+ struct Get_type_category <K, X##_tag, D> { typedef Y##_tag type; }
+#define CGAL_DECL_OBJ(X,Y) struct X##_tag {}; \
+ CGAL_DECL_OBJ_(X,Y)
+
+ //namespace has_object { BOOST_MPL_HAS_XXX_TRAIT_DEF(X) }
+ //template<class Kernel>
+ //struct Provides_tag_type<Kernel, X##_tag> : has_object::has_##X<Kernel> {};
+ //template<class Kernel>
+ //struct Read_tag_type<Kernel, X##_tag> { typedef typename Kernel::X type; }
+
+ // Not exactly objects, but the extras can't hurt.
+ CGAL_DECL_OBJ(FT, Number);
+ CGAL_DECL_OBJ(RT, Number);
+
+ CGAL_DECL_OBJ(Bool, Discrete); // Boolean_tag is already taken, and is a template :-(
+ CGAL_DECL_OBJ(Comparison_result, Discrete);
+ CGAL_DECL_OBJ(Sign, Discrete);
+ CGAL_DECL_OBJ(Orientation, Discrete); // Note: duplicate with the functor tag!
+ CGAL_DECL_OBJ(Oriented_side, Discrete);
+ CGAL_DECL_OBJ(Bounded_side, Discrete);
+ CGAL_DECL_OBJ(Angle, Discrete);
+ CGAL_DECL_OBJ(Flat_orientation, Discrete);
+
+ CGAL_DECL_OBJ(Vector, Object);
+ CGAL_DECL_OBJ(Point, Object);
+ CGAL_DECL_OBJ(Segment, Object);
+ CGAL_DECL_OBJ(Sphere, Object);
+ CGAL_DECL_OBJ(Line, Object);
+ CGAL_DECL_OBJ(Direction, Object);
+ CGAL_DECL_OBJ(Hyperplane, Object);
+ CGAL_DECL_OBJ(Ray, Object);
+ CGAL_DECL_OBJ(Iso_box, Object);
+ CGAL_DECL_OBJ(Bbox, Object);
+ CGAL_DECL_OBJ(Aff_transformation, Object);
+ CGAL_DECL_OBJ(Weighted_point, Object);
+#undef CGAL_DECL_OBJ_
+#undef CGAL_DECL_OBJ
+
+// Intel fails with those, and they are not so useful.
+// CGAL_KD_DEFAULT_TYPE(RT_tag,(typename Get_type<K, FT_tag>::type),(),());
+// CGAL_KD_DEFAULT_TYPE(FT_tag,(CGAL::Quotient<typename Get_type<K, RT_tag>::type>),(),());
+
+#define CGAL_SMURF2(A,B) CGAL_KD_DEFAULT_TYPE(A##_tag,(typename Same_uncertainty_nt<B, typename Get_type<K,RT_tag>::type>::type),(RT_tag),())
+#define CGAL_SMURF1(A) CGAL_SMURF2(A,CGAL::A)
+ CGAL_SMURF2(Bool, bool);
+ CGAL_SMURF1(Sign);
+ CGAL_SMURF1(Comparison_result);
+ CGAL_SMURF1(Orientation);
+ CGAL_SMURF1(Oriented_side);
+ CGAL_SMURF1(Bounded_side);
+ CGAL_SMURF1(Angle);
+#undef CGAL_SMURF1
+#undef CGAL_SMURF2
+
+ // TODO: replace with Get_type_category
+ template<class> struct is_NT_tag { enum { value = false }; };
+ template<> struct is_NT_tag<FT_tag> { enum { value = true }; };
+ template<> struct is_NT_tag<RT_tag> { enum { value = true }; };
+
+ template<class> struct iterator_tag_traits {
+ enum { is_iterator = false, has_nth_element = false };
+ typedef Null_tag value_tag;
+ };
+
+#define CGAL_DECL_COMPUTE(X) struct X##_tag {}; \
+ template<class A,class B,class C>struct Get_functor_category<A,X##_tag,B,C>{typedef Compute_tag type;}
+ CGAL_DECL_COMPUTE(Compute_point_cartesian_coordinate);
+ CGAL_DECL_COMPUTE(Compute_vector_cartesian_coordinate);
+ CGAL_DECL_COMPUTE(Compute_homogeneous_coordinate);
+ CGAL_DECL_COMPUTE(Squared_distance);
+ CGAL_DECL_COMPUTE(Squared_distance_to_origin);
+ CGAL_DECL_COMPUTE(Squared_length);
+ CGAL_DECL_COMPUTE(Squared_radius);
+ CGAL_DECL_COMPUTE(Squared_circumradius);
+ CGAL_DECL_COMPUTE(Scalar_product);
+ CGAL_DECL_COMPUTE(Hyperplane_translation);
+ CGAL_DECL_COMPUTE(Value_at);
+ CGAL_DECL_COMPUTE(Point_weight);
+ CGAL_DECL_COMPUTE(Power_distance);
+ CGAL_DECL_COMPUTE(Power_distance_to_point);
+#undef CGAL_DECL_COMPUTE
+
+#define CGAL_DECL_ITER_OBJ(X,Y,Z,C) struct X##_tag {}; \
+ template<>struct iterator_tag_traits<X##_tag> { \
+ enum { is_iterator = true, has_nth_element = true }; \
+ typedef Y##_tag value_tag; \
+ typedef Z##_tag nth_element; \
+ typedef C##_tag container; \
+ }; \
+ template<class Obj,class Base> \
+ struct Typedef_tag_type<X##_tag, Obj, Base> : Base { typedef Obj X; }
+
+ //namespace has_object { BOOST_MPL_HAS_XXX_TRAIT_DEF(X) }
+ //template<class Kernel>
+ //struct Provides_tag_type<Kernel, X##_tag> : has_object::has_##X<Kernel> {};
+ //template<class Kernel>
+ //struct Read_tag_type<Kernel, X##_tag> { typedef typename Kernel::X type; }
+
+ CGAL_DECL_ITER_OBJ(Vector_cartesian_const_iterator, FT, Compute_vector_cartesian_coordinate, Vector);
+ CGAL_DECL_ITER_OBJ(Point_cartesian_const_iterator, FT, Compute_point_cartesian_coordinate, Point);
+#undef CGAL_DECL_ITER_OBJ
+
+ template<class>struct map_result_tag{typedef Null_type type;};
+ template<class T>struct map_result_tag<Construct_ttag<T> >{typedef T type;};
+
+ template<class A,class T,class B,class C>struct Get_functor_category<A,Construct_ttag<T>,B,C> :
+ boost::mpl::if_c<iterator_tag_traits<T>::is_iterator,
+ Construct_iterator_tag,
+ Construct_tag> {};
+
+ // Really?
+ template<class A,class T,class B,class C>struct Get_functor_category<A,Convert_ttag<T>,B,C>{typedef Misc_tag type;};
+
+#define CGAL_DECL_CONSTRUCT(X,Y) struct X##_tag {}; \
+ template<>struct map_result_tag<X##_tag>{typedef Y##_tag type;}; \
+ template<class A,class B,class C>struct Get_functor_category<A,X##_tag,B,C>{typedef Construct_tag type;}
+ CGAL_DECL_CONSTRUCT(Midpoint,Point);
+ CGAL_DECL_CONSTRUCT(Center_of_sphere,Point);
+ CGAL_DECL_CONSTRUCT(Point_of_sphere,Point);
+ CGAL_DECL_CONSTRUCT(Segment_extremity,Point);
+ CGAL_DECL_CONSTRUCT(Sum_of_vectors,Vector);
+ CGAL_DECL_CONSTRUCT(Difference_of_vectors,Vector);
+ CGAL_DECL_CONSTRUCT(Opposite_vector,Vector);
+ CGAL_DECL_CONSTRUCT(Scaled_vector,Vector);
+ CGAL_DECL_CONSTRUCT(Orthogonal_vector,Vector);
+ CGAL_DECL_CONSTRUCT(Difference_of_points,Vector);
+ CGAL_DECL_CONSTRUCT(Translated_point,Point);
+ CGAL_DECL_CONSTRUCT(Point_to_vector,Vector);
+ CGAL_DECL_CONSTRUCT(Vector_to_point,Point);
+ CGAL_DECL_CONSTRUCT(Construct_min_vertex,Point);
+ CGAL_DECL_CONSTRUCT(Construct_max_vertex,Point);
+ CGAL_DECL_CONSTRUCT(Construct_circumcenter,Point);
+ CGAL_DECL_CONSTRUCT(Point_drop_weight,Point);
+ CGAL_DECL_CONSTRUCT(Power_center,Weighted_point);
+#undef CGAL_DECL_CONSTRUCT
+#if 0
+#define CGAL_DECL_ITER_CONSTRUCT(X,Y) struct X##_tag {}; \
+ template<>struct map_result_tag<X##_tag>{typedef Y##_tag type;}; \
+ template<>struct map_functor_type<X##_tag>{typedef Construct_iterator_tag type;}
+ CGAL_DECL_ITER_CONSTRUCT(Construct_point_cartesian_const_iterator,Point_cartesian_const_iterator);
+ CGAL_DECL_ITER_CONSTRUCT(Construct_vector_cartesian_const_iterator,Vector_cartesian_const_iterator);
+#undef CGAL_DECL_ITER_CONSTRUCT
+#endif
+
+ //FIXME: choose a convention: prefix with Predicate_ ?
+#define CGAL_DECL_PREDICATE_(X) \
+ template<class A,class B,class C>struct Get_functor_category<A,X##_tag,B,C>{typedef Predicate_tag type;}
+#define CGAL_DECL_PREDICATE(X) struct X##_tag {}; \
+ CGAL_DECL_PREDICATE_(X)
+ CGAL_DECL_PREDICATE(Less_point_cartesian_coordinate);
+ CGAL_DECL_PREDICATE(Compare_point_cartesian_coordinate);
+ CGAL_DECL_PREDICATE(Compare_distance);
+ CGAL_DECL_PREDICATE(Compare_lexicographically);
+ CGAL_DECL_PREDICATE(Less_lexicographically);
+ CGAL_DECL_PREDICATE(Less_or_equal_lexicographically);
+ CGAL_DECL_PREDICATE(Equal_points);
+ CGAL_DECL_PREDICATE(Has_on_positive_side);
+ CGAL_DECL_PREDICATE_(Orientation); // duplicate with the type
+ CGAL_DECL_PREDICATE_(Oriented_side); // duplicate with the type
+ CGAL_DECL_PREDICATE(Orientation_of_points);
+ CGAL_DECL_PREDICATE(Orientation_of_vectors);
+ CGAL_DECL_PREDICATE(Side_of_oriented_sphere);
+ CGAL_DECL_PREDICATE(Side_of_bounded_sphere);
+ CGAL_DECL_PREDICATE(Side_of_bounded_circumsphere);
+ CGAL_DECL_PREDICATE(Contained_in_affine_hull);
+ CGAL_DECL_PREDICATE(In_flat_orientation);
+ CGAL_DECL_PREDICATE(In_flat_side_of_oriented_sphere);
+ CGAL_DECL_PREDICATE(Construct_flat_orientation); // Making it a predicate is a questionable choice, it should be possible to let it be a construction for some implementations. Not sure how to do that... TODO
+ CGAL_DECL_PREDICATE(Linear_rank);
+ CGAL_DECL_PREDICATE(Affine_rank);
+ CGAL_DECL_PREDICATE(Linearly_independent);
+ CGAL_DECL_PREDICATE(Affinely_independent);
+ CGAL_DECL_PREDICATE(Contained_in_linear_hull);
+ CGAL_DECL_PREDICATE(Contained_in_simplex);
+ CGAL_DECL_PREDICATE(Power_side_of_power_sphere_raw);
+ CGAL_DECL_PREDICATE(Power_side_of_power_sphere);
+ CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere_raw);
+ CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere);
+#undef CGAL_DECL_PREDICATE
+
+#define CGAL_DECL_MISC(X) struct X##_tag {}; \
+ template<class A,class B,class C>struct Get_functor_category<A,X##_tag,B,C>{typedef Misc_tag type;}
+ //TODO: split into _begin and _end ?
+ //CGAL_DECL_MISC(Construct_point_cartesian_const_iterator);
+ //CGAL_DECL_MISC(Construct_vector_cartesian_const_iterator);
+ CGAL_DECL_MISC(Point_dimension);
+ CGAL_DECL_MISC(Vector_dimension);
+ CGAL_DECL_MISC(Linear_base); // Find a more appropriate category?
+#undef CGAL_DECL_MISC
+
+
+ // Properties for LA
+ struct Has_extra_dimension_tag {};
+ struct Has_vector_plus_minus_tag {};
+ struct Has_vector_scalar_ops_tag {};
+ struct Has_dot_product_tag {};
+ struct Has_determinant_of_vectors_tag {};
+ struct Has_determinant_of_points_tag {};
+ struct Has_determinant_of_iterator_to_vectors_tag {};
+ struct Has_determinant_of_iterator_to_points_tag {};
+ struct Has_determinant_of_vectors_omit_last_tag {};
+ struct Stores_squared_norm_tag {};
+
+ template<class> struct Preserved_by_non_linear_extra_coordinate
+ : boost::false_type {};
+ template<> struct Preserved_by_non_linear_extra_coordinate
+ <Has_extra_dimension_tag> : boost::true_type {};
+ template<> struct Preserved_by_non_linear_extra_coordinate
+ <Has_determinant_of_vectors_tag> : boost::true_type {};
+ template<> struct Preserved_by_non_linear_extra_coordinate
+ <Has_determinant_of_points_tag> : boost::true_type {};
+ template<> struct Preserved_by_non_linear_extra_coordinate
+ <Has_determinant_of_iterator_to_vectors_tag> : boost::true_type {};
+ template<> struct Preserved_by_non_linear_extra_coordinate
+ <Has_determinant_of_iterator_to_points_tag> : boost::true_type {};
+ template<> struct Preserved_by_non_linear_extra_coordinate
+ <Has_determinant_of_vectors_omit_last_tag> : boost::true_type {};
+
+ // Kernel properties
+ struct Point_stores_squared_distance_to_origin_tag {};
+
+}
+#endif // CGAL_FUNCTOR_TAGS_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/static_int.h b/include/gudhi_patches/CGAL/NewKernel_d/static_int.h
new file mode 100644
index 00000000..21858804
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/static_int.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_STATIC_INT_H
+#define CGAL_STATIC_INT_H
+#include <CGAL/constant.h>
+
+namespace CGAL {
+template <class NT> struct static_zero {
+ operator NT() const { return constant<NT,0>(); }
+};
+template <class NT> struct static_one {
+ operator NT() const { return constant<NT,1>(); }
+};
+
+template <class NT> static_zero<NT> operator-(static_zero<NT>) { return static_zero<NT>(); }
+
+template <class NT> NT operator+(NT const& x, static_zero<NT>) { return x; }
+template <class NT> NT operator+(static_zero<NT>, NT const& x) { return x; }
+template <class NT> static_zero<NT> operator+(static_zero<NT>, static_zero<NT>) { return static_zero<NT>(); }
+template <class NT> static_one<NT> operator+(static_zero<NT>, static_one<NT>) { return static_one<NT>(); }
+template <class NT> static_one<NT> operator+(static_one<NT>, static_zero<NT>) { return static_one<NT>(); }
+
+template <class NT> NT operator-(NT const& x, static_zero<NT>) { return x; }
+template <class NT> NT operator-(static_zero<NT>, NT const& x) { return -x; }
+template <class NT> static_zero<NT> operator-(static_zero<NT>, static_zero<NT>) { return static_zero<NT>(); }
+template <class NT> static_zero<NT> operator-(static_one<NT>, static_one<NT>) { return static_zero<NT>(); }
+template <class NT> static_one<NT> operator-(static_one<NT>, static_zero<NT>) { return static_one<NT>(); }
+
+template <class NT> NT operator*(NT const& x, static_one<NT>) { return x; }
+template <class NT> NT operator*(static_one<NT>, NT const& x) { return x; }
+template <class NT> static_zero<NT> operator*(NT const&, static_zero<NT>) { return static_zero<NT>(); }
+template <class NT> static_zero<NT> operator*(static_zero<NT>, NT const&) { return static_zero<NT>(); }
+template <class NT> static_zero<NT> operator*(static_zero<NT>, static_zero<NT>) { return static_zero<NT>(); }
+template <class NT> static_one<NT> operator*(static_one<NT>, static_one<NT>) { return static_one<NT>(); }
+template <class NT> static_zero<NT> operator*(static_zero<NT>, static_one<NT>) { return static_zero<NT>(); }
+template <class NT> static_zero<NT> operator*(static_one<NT>, static_zero<NT>) { return static_zero<NT>(); }
+
+template <class NT> NT operator/(NT const& x, static_one<NT>) { return x; }
+template <class NT> static_zero<NT> operator/(static_zero<NT>, NT const&) { return static_zero<NT>(); }
+template <class NT> static_zero<NT> operator/(static_zero<NT>, static_one<NT>) { return static_zero<NT>(); }
+template <class NT> static_one<NT> operator/(static_one<NT>, static_one<NT>) { return static_one<NT>(); }
+
+}
+#endif // CGAL_STATIC_INT_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h b/include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h
new file mode 100644
index 00000000..253e1282
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h
@@ -0,0 +1,104 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_STORE_KERNEL_H
+#define CGAL_STORE_KERNEL_H
+
+#include <CGAL/assertions.h>
+#include <boost/type_traits/is_empty.hpp>
+
+namespace CGAL {
+namespace internal {
+BOOST_MPL_HAS_XXX_TRAIT_DEF(Do_not_store_kernel)
+template<class T,bool=boost::is_empty<T>::value,bool=has_Do_not_store_kernel<T>::value> struct Do_not_store_kernel {
+ enum { value=false };
+ typedef Tag_false type;
+};
+template<class T> struct Do_not_store_kernel<T,true,false> {
+ enum { value=true };
+ typedef Tag_true type;
+};
+template<class T,bool b> struct Do_not_store_kernel<T,b,true> {
+ typedef typename T::Do_not_store_kernel type;
+ enum { value=type::value };
+};
+}
+
+template<class R_,bool=internal::Do_not_store_kernel<R_>::value>
+struct Store_kernel {
+ Store_kernel(){}
+ Store_kernel(R_ const&){}
+ enum { kernel_is_stored = false };
+ R_ kernel()const{return R_();}
+ typedef R_ reference_type;
+ void set_kernel(R_ const&){}
+};
+template<class R_>
+struct Store_kernel<R_,false> {
+ Store_kernel():rp(0){
+ CGAL_warning_msg(true,"I should know my kernel");
+ }
+ Store_kernel(R_ const& r):rp(&r){}
+ enum { kernel_is_stored = true };
+ R_ const& kernel()const{
+ CGAL_warning_msg(rp!=0,"I should know my kernel");
+ return *rp;
+ }
+ typedef R_ const& reference_type;
+ void set_kernel(R_ const&r){rp=&r;}
+ private:
+ R_ const* rp;
+};
+
+//For a second kernel. TODO: find something more elegant
+template<class R_,bool=internal::Do_not_store_kernel<R_>::value>
+struct Store_kernel2 {
+ Store_kernel2(){}
+ Store_kernel2(R_ const&){}
+ enum { kernel2_is_stored = false };
+ R_ kernel2()const{return R_();}
+ typedef R_ reference2_type;
+ void set_kernel2(R_ const&){}
+};
+template<class R_>
+struct Store_kernel2<R_,false> {
+ Store_kernel2(){
+ //CGAL_warning_msg(true,"I should know my kernel");
+ }
+ Store_kernel2(R_ const& r):rp(&r){}
+ enum { kernel2_is_stored = true };
+ R_ const& kernel2()const{
+ CGAL_warning_msg(rp==0,"I should know my kernel");
+ return *rp;
+ }
+ typedef R_ const& reference2_type;
+ void set_kernel2(R_ const&r){rp=&r;}
+ private:
+ R_ const* rp;
+};
+}
+#define CGAL_BASE_INIT(X,Y) \
+ X():Y(){} \
+ X(R_ const&r):Y(r){}
+#define CGAL_FUNCTOR_INIT_STORE(X) CGAL_BASE_INIT(X,Store_kernel<R_>)
+#define CGAL_FUNCTOR_INIT_IGNORE(X) \
+ X(){} \
+ X(R_ const&){}
+
+#endif // CGAL_STORE_KERNEL_H
diff --git a/include/gudhi_patches/CGAL/NewKernel_d/utils.h b/include/gudhi_patches/CGAL/NewKernel_d/utils.h
new file mode 100644
index 00000000..238a2230
--- /dev/null
+++ b/include/gudhi_patches/CGAL/NewKernel_d/utils.h
@@ -0,0 +1,306 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_MARCUTILS
+#define CGAL_MARCUTILS
+
+#include <CGAL/config.h>
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4003) // not enough actual parameters for macro 'BOOST_PP_EXPAND_I'
+ // http://lists.boost.org/boost-users/2014/11/83291.php
+#endif
+
+#ifdef CGAL_CXX11
+#include <type_traits>
+#include <utility>
+#define CGAL_FORWARDABLE(T) T&&
+#define CGAL_FORWARD(T,t) std::forward<T>(t)
+#define CGAL_MOVE(t) std::move(t)
+#define CGAL_CONSTEXPR constexpr
+#else
+#define CGAL_FORWARDABLE(T) T const&
+#define CGAL_FORWARD(T,t) t
+#define CGAL_MOVE(t) t
+#define CGAL_CONSTEXPR
+#endif
+#include <boost/utility/enable_if.hpp>
+#include <boost/preprocessor/repetition.hpp>
+#include <CGAL/Rational_traits.h>
+#include <CGAL/tuple.h>
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits.hpp>
+
+#ifdef CGAL_CXX11
+#define CGAL_BOOSTD std::
+#else
+#define CGAL_BOOSTD boost::
+#endif
+
+namespace CGAL {
+namespace internal {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(type)
+}
+
+template <class T, class No, bool=internal::has_type<T>::value /*false*/>
+struct Has_type_different_from : boost::false_type {};
+template <class T, class No>
+struct Has_type_different_from <T, No, true>
+: boost::mpl::not_<boost::is_same<typename T::type, No> > {};
+
+
+ template <class T> struct Wrap_type { typedef T type; };
+
+ // tell a function f(a,b,c) that its real argument is a(b,c)
+ struct Eval_functor {};
+
+ // forget the first argument. Useful to make something dependant
+ // (and thus usable in SFINAE), although that's not a great design.
+ template<class A,class B> struct Second_arg {
+ typedef B type;
+ };
+
+ // like std::forward, except for basic types where it does a cast, to
+ // avoid issues with narrowing conversions
+#ifdef CGAL_CXX11
+ template<class T,class U,class V> inline
+ typename std::conditional<std::is_arithmetic<T>::value&&std::is_arithmetic<typename std::remove_reference<U>::type>::value,T,U&&>::type
+ forward_safe(V&& u) { return std::forward<U>(u); }
+#else
+ template<class T,class U> inline U const& forward_safe(U const& u) {
+ return u;
+ }
+#endif
+
+#ifdef CGAL_CXX11
+ template<class...> struct Constructible_from_each;
+ template<class To,class From1,class...From> struct Constructible_from_each<To,From1,From...>{
+ enum { value=std::is_convertible<From1,To>::value&&Constructible_from_each<To,From...>::value };
+ };
+ template<class To> struct Constructible_from_each<To>{
+ enum { value=true };
+ };
+#else
+// currently only used in C++0X code
+#endif
+
+ template<class T> struct Scale {
+#ifndef CGAL_CXX11
+ template<class> struct result;
+ template<class FT> struct result<Scale(FT)> {
+ typedef FT type;
+ };
+#endif
+ T const& scale;
+ Scale(T const& t):scale(t){}
+ template<class FT>
+#ifdef CGAL_CXX11
+ auto operator()(FT&& x)const->decltype(scale*std::forward<FT>(x))
+#else
+ FT operator()(FT const& x)const
+#endif
+ {
+ return scale*CGAL_FORWARD(FT,x);
+ }
+ };
+ template<class NT,class T> struct Divide {
+#if !defined(CGAL_CXX11) || !defined(BOOST_RESULT_OF_USE_DECLTYPE)
+ // requires boost > 1.44
+ // shouldn't be needed with C++0X
+ //template<class> struct result;
+ //template<class FT> struct result<Divide(FT)> {
+ // typedef FT type;
+ //};
+ typedef NT result_type;
+#endif
+ T const& scale;
+ Divide(T const& t):scale(t){}
+ template<class FT>
+#ifdef CGAL_CXX11
+ //FIXME: gcc complains for Gmpq
+ //auto operator()(FT&& x)const->decltype(Rational_traits<NT>().make_rational(std::forward<FT>(x),scale))
+ NT operator()(FT&& x)const
+#else
+ NT operator()(FT const& x)const
+#endif
+ {
+ return Rational_traits<NT>().
+ make_rational(CGAL_FORWARD(FT,x),scale);
+ }
+ };
+
+ template <class NT> struct has_cheap_constructor : boost::is_arithmetic<NT>{};
+ template <bool p> struct has_cheap_constructor<Interval_nt<p> > {
+ enum { value=true };
+ };
+
+ // like std::multiplies but allows mixing types
+ // in C++11 in doesn't need to be a template
+ template < class Ret >
+ struct multiplies {
+ template<class A,class B>
+#ifdef CGAL_CXX11
+ auto operator()(A&&a,B&&b)const->decltype(std::forward<A>(a)*std::forward<B>(b))
+#else
+ Ret operator()(A const& a, B const& b)const
+#endif
+ {
+ return CGAL_FORWARD(A,a)*CGAL_FORWARD(B,b);
+ }
+ };
+ template < class Ret >
+ struct division {
+ template<class A,class B>
+#ifdef CGAL_CXX11
+ auto operator()(A&&a,B&&b)const->decltype(std::forward<A>(a)/std::forward<B>(b))
+#else
+ Ret operator()(A const& a, B const& b)const
+#endif
+ {
+ return CGAL_FORWARD(A,a)/CGAL_FORWARD(B,b);
+ }
+ };
+
+#ifdef CGAL_CXX11
+ using std::decay;
+#else
+ template<class T> struct decay : boost::remove_cv<typename boost::decay<T>::type> {};
+#endif
+
+ template<class T,class U> struct Type_copy_ref { typedef U type; };
+ template<class T,class U> struct Type_copy_ref<T&,U> { typedef U& type; };
+#ifdef CGAL_CXX11
+ template<class T,class U> struct Type_copy_ref<T&&,U> { typedef U&& type; };
+#endif
+ template<class T,class U> struct Type_copy_cv { typedef U type; };
+ template<class T,class U> struct Type_copy_cv<T const,U> { typedef U const type; };
+ template<class T,class U> struct Type_copy_cv<T volatile,U> { typedef U volatile type; };
+ template<class T,class U> struct Type_copy_cv<T const volatile,U> { typedef U const volatile type; };
+
+ template<class T,class U> struct Type_copy_cvref :
+ Type_copy_ref<T,typename Type_copy_cv<typename boost::remove_reference<T>::type,U>::type> {};
+
+ struct Dereference_functor {
+ template<class> struct result{};
+ template<class It> struct result<Dereference_functor(It)> {
+ typedef typename std::iterator_traits<It>::reference type;
+ };
+ template<class It> typename result<Dereference_functor(It)>::type
+ operator()(It const&i)const{
+ return *i;
+ }
+ };
+
+#ifdef CGAL_CXX11
+ template<int...> struct Indices{};
+ template<class> struct Next_increasing_indices;
+ template<int...I> struct Next_increasing_indices<Indices<I...> > {
+ typedef Indices<I...,sizeof...(I)> type;
+ };
+ template<int N> struct N_increasing_indices {
+ typedef typename Next_increasing_indices<typename N_increasing_indices<N-1>::type>::type type;
+ };
+ template<> struct N_increasing_indices<0> { typedef Indices<> type; };
+ namespace internal {
+ template<class F,class...U,int...I> inline typename std::result_of<F&&(U...)>::type
+ do_call_on_tuple_elements(F&&f, std::tuple<U...>&&t, Indices<I...>&&) {
+ return f(std::get<I>(std::move(t))...);
+ }
+ } // internal
+ template<class/*result type, ignored*/,class F,class...U>
+ inline typename std::result_of<F&&(U...)>::type
+ call_on_tuple_elements(F&&f, std::tuple<U...>&&t) {
+ return internal::do_call_on_tuple_elements(std::forward<F>(f),std::move(t),
+ typename N_increasing_indices<sizeof...(U)>::type());
+ }
+#else
+#define CGAL_VAR(Z,N,_) cpp0x::get<N>(t)
+#define CGAL_CODE(Z,N,_) template<class Res, class F BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N,class U)> \
+ inline Res call_on_tuple_elements(F const&f, \
+ cpp0x::tuple<BOOST_PP_ENUM_PARAMS(N,U)> const&t) { \
+ return f(BOOST_PP_ENUM(N,CGAL_VAR,)); \
+ }
+ template<class Res, class F>
+ inline Res call_on_tuple_elements(F const&f, cpp0x::tuple<>) {
+ return f();
+ }
+BOOST_PP_REPEAT_FROM_TO(1, 8, CGAL_CODE, _ )
+#undef CGAL_CODE
+#undef CGAL_VAR
+#endif
+
+ template<class A> struct Factory {
+ typedef A result_type;
+#ifdef CGAL_CXX11
+ template<class...U> result_type operator()(U&&...u)const{
+ return A(std::forward<U>(u)...);
+ }
+#else
+ result_type operator()()const{
+ return A();
+ }
+#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> \
+ result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \
+ return A(BOOST_PP_ENUM_PARAMS(N,u)); \
+ }
+BOOST_PP_REPEAT_FROM_TO(1, 8, CGAL_CODE, _ )
+#undef CGAL_CODE
+#endif
+ };
+}
+
+// TODO: make a Cartesian-only variant
+// WARNING: do not use the Req* parameters too much, they can cause circular instanciations and are only useful for dispatching.
+#define CGAL_STRIP_PAREN_(...) __VA_ARGS__
+#define CGAL_STRIP_PAREN(...) CGAL_STRIP_PAREN_ __VA_ARGS__
+// What to do with O? pass it down to other functors or drop it?
+#define CGAL_KD_DEFAULT_FUNCTOR(Tg,Name,ReqTyp,ReqFun) \
+ template <class K, class O> \
+ struct Get_functor<K, Tg, O, \
+ typename boost::mpl::if_c< \
+ Provides_functor_i<K, Tg, O>::value \
+ || !Provides_types<K, boost::mpl::vector<CGAL_STRIP_PAREN_ ReqTyp> >::value \
+ || !Provides_functors<K, boost::mpl::vector<CGAL_STRIP_PAREN_ ReqFun> >::value \
+ , int, void>::type> \
+ { \
+ typedef CGAL_STRIP_PAREN_ Name type; \
+ typedef K Bound_kernel; \
+ }
+
+// Not used yet, may need some changes.
+#define CGAL_KD_DEFAULT_TYPE(Tg,Name,ReqTyp,ReqFun) \
+ template <class K> \
+ struct Get_type<K, Tg, \
+ typename boost::mpl::if_c< \
+ Provides_type_i<K, Tg>::value \
+ || !Provides_types<K, boost::mpl::vector<CGAL_STRIP_PAREN_ ReqTyp> >::value \
+ || !Provides_functors<K, boost::mpl::vector<CGAL_STRIP_PAREN_ ReqFun> >::value \
+ , int, void>::type> \
+ { \
+ typedef CGAL_STRIP_PAREN_ Name type; \
+ typedef K Bound_kernel; \
+ }
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/include/gudhi_patches/CGAL/Orthogonal_incremental_neighbor_search.h b/include/gudhi_patches/CGAL/Orthogonal_incremental_neighbor_search.h
new file mode 100644
index 00000000..e29ce14f
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Orthogonal_incremental_neighbor_search.h
@@ -0,0 +1,620 @@
+// Copyright (c) 2002,2011 Utrecht University (The Netherlands).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+//
+// Author(s) : Hans Tangelder (<hanst@cs.uu.nl>)
+
+#ifndef CGAL_ORTHOGONAL_INCREMENTAL_NEIGHBOR_SEARCH
+#define CGAL_ORTHOGONAL_INCREMENTAL_NEIGHBOR_SEARCH
+
+#include <CGAL/Kd_tree.h>
+#include <cstring>
+#include <list>
+#include <queue>
+#include <memory>
+#include <CGAL/Euclidean_distance.h>
+#include <CGAL/tuple.h>
+
+namespace CGAL {
+
+ template <class SearchTraits,
+ class Distance_= typename internal::Spatial_searching_default_distance<SearchTraits>::type,
+ class Splitter_ = Sliding_midpoint<SearchTraits>,
+ class Tree_= Kd_tree<SearchTraits, Splitter_, Tag_true> >
+ class Orthogonal_incremental_neighbor_search {
+
+ public:
+ typedef Splitter_ Splitter;
+ typedef Tree_ Tree;
+ typedef Distance_ Distance;
+ typedef typename SearchTraits::Point_d Point_d;
+ typedef typename Distance::Query_item Query_item;
+ typedef typename SearchTraits::FT FT;
+ typedef typename Tree::Point_d_iterator Point_d_iterator;
+ typedef typename Tree::Node_const_handle Node_const_handle;
+
+ typedef std::pair<Point_d,FT> Point_with_transformed_distance;
+ typedef CGAL::cpp11::tuple<Node_const_handle,FT,std::vector<FT> > Node_with_distance;
+ typedef std::vector<Node_with_distance*> Node_with_distance_vector;
+ typedef std::vector<Point_with_transformed_distance*> Point_with_transformed_distance_vector;
+
+ template<class T>
+ struct Object_wrapper
+ {
+ T object;
+ Object_wrapper(const T& t):object(t){}
+ const T& operator* () const { return object; }
+ const T* operator-> () const { return &object; }
+ };
+
+ class Iterator_implementation {
+ SearchTraits traits;
+ public:
+
+ int number_of_neighbours_computed;
+ int number_of_internal_nodes_visited;
+ int number_of_leaf_nodes_visited;
+ int number_of_items_visited;
+
+ private:
+
+ typedef std::vector<FT> Distance_vector;
+
+ Distance_vector dists;
+
+ Distance Orthogonal_distance_instance;
+
+ FT multiplication_factor;
+
+ Query_item query_point;
+
+ FT distance_to_root;
+
+ bool search_nearest_neighbour;
+
+ FT rd;
+
+
+ class Priority_higher {
+ public:
+
+ bool search_nearest;
+
+ Priority_higher(bool search_the_nearest_neighbour)
+ : search_nearest(search_the_nearest_neighbour)
+ {}
+
+ //highest priority is smallest distance
+ bool
+ operator() (Node_with_distance* n1, Node_with_distance* n2) const
+ {
+ return (search_nearest) ? (CGAL::cpp11::get<1>(*n1) > CGAL::cpp11::get<1>(*n2)) : (CGAL::cpp11::get<1>(*n2) > CGAL::cpp11::get<1>(*n1));
+ }
+ };
+
+ class Distance_smaller {
+
+ public:
+
+ bool search_nearest;
+
+ Distance_smaller(bool search_the_nearest_neighbour)
+ : search_nearest(search_the_nearest_neighbour)
+ {}
+
+ //highest priority is smallest distance
+ bool operator() (Point_with_transformed_distance* p1, Point_with_transformed_distance* p2) const
+ {
+ return (search_nearest) ? (p1->second > p2->second) : (p2->second > p1->second);
+ }
+ };
+
+
+ std::priority_queue<Node_with_distance*, Node_with_distance_vector,
+ Priority_higher> PriorityQueue;
+
+ public:
+ std::priority_queue<Point_with_transformed_distance*, Point_with_transformed_distance_vector,
+ Distance_smaller> Item_PriorityQueue;
+
+
+ public:
+
+ int reference_count;
+
+
+
+ // constructor
+ Iterator_implementation(const Tree& tree,const Query_item& q, const Distance& tr,
+ FT Eps=FT(0.0), bool search_nearest=true)
+ : traits(tree.traits()),number_of_neighbours_computed(0), number_of_internal_nodes_visited(0),
+ number_of_leaf_nodes_visited(0), number_of_items_visited(0),
+ Orthogonal_distance_instance(tr), multiplication_factor(Orthogonal_distance_instance.transformed_distance(FT(1.0)+Eps)),
+ query_point(q), search_nearest_neighbour(search_nearest),
+ PriorityQueue(Priority_higher(search_nearest)), Item_PriorityQueue(Distance_smaller(search_nearest)),
+ reference_count(1)
+
+
+ {
+ if (tree.empty()) return;
+
+ typename SearchTraits::Construct_cartesian_const_iterator_d ccci=traits.construct_cartesian_const_iterator_d_object();
+ int dim = static_cast<int>(std::distance(ccci(q), ccci(q,0)));
+
+ dists.resize(dim);
+ for(int i=0 ; i<dim ; ++i){
+ dists[i] = 0;
+ }
+
+ if (search_nearest){
+ distance_to_root=
+ Orthogonal_distance_instance.min_distance_to_rectangle(q, tree.bounding_box(),dists);
+ Node_with_distance *The_Root = new Node_with_distance(tree.root(),
+ distance_to_root, dists);
+ PriorityQueue.push(The_Root);
+
+ // rd is the distance of the top of the priority queue to q
+ rd=CGAL::cpp11::get<1>(*The_Root);
+ Compute_the_next_nearest_neighbour();
+ }
+ else{
+ distance_to_root=
+ Orthogonal_distance_instance.max_distance_to_rectangle(q,
+ tree.bounding_box(), dists);
+ Node_with_distance *The_Root = new Node_with_distance(tree.root(),
+ distance_to_root, dists);
+ PriorityQueue.push(The_Root);
+
+ // rd is the distance of the top of the priority queue to q
+ rd=CGAL::cpp11::get<1>(*The_Root);
+ Compute_the_next_furthest_neighbour();
+ }
+
+
+ }
+
+ // * operator
+ const Point_with_transformed_distance&
+ operator* () const
+ {
+ return *(Item_PriorityQueue.top());
+ }
+
+ // prefix operator
+ Iterator_implementation&
+ operator++()
+ {
+ Delete_the_current_item_top();
+ if(search_nearest_neighbour)
+ Compute_the_next_nearest_neighbour();
+ else
+ Compute_the_next_furthest_neighbour();
+ return *this;
+ }
+
+ // postfix operator
+ Object_wrapper<Point_with_transformed_distance>
+ operator++(int)
+ {
+ Object_wrapper<Point_with_transformed_distance> result( *(Item_PriorityQueue.top()) );
+ ++*this;
+ return result;
+ }
+
+ // Print statistics of the general priority search process.
+ std::ostream&
+ statistics (std::ostream& s) const {
+ s << "Orthogonal priority search statistics:"
+ << std::endl;
+ s << "Number of internal nodes visited:"
+ << number_of_internal_nodes_visited << std::endl;
+ s << "Number of leaf nodes visited:"
+ << number_of_leaf_nodes_visited << std::endl;
+ s << "Number of items visited:"
+ << number_of_items_visited << std::endl;
+ s << "Number of neighbours computed:"
+ << number_of_neighbours_computed << std::endl;
+ return s;
+ }
+
+
+ //destructor
+ ~Iterator_implementation()
+ {
+ while (!PriorityQueue.empty()) {
+ Node_with_distance* The_top=PriorityQueue.top();
+ PriorityQueue.pop();
+ delete The_top;
+ }
+ while (!Item_PriorityQueue.empty()) {
+ Point_with_transformed_distance* The_top=Item_PriorityQueue.top();
+ Item_PriorityQueue.pop();
+ delete The_top;
+ }
+ }
+
+ private:
+
+ void
+ Delete_the_current_item_top()
+ {
+ Point_with_transformed_distance* The_item_top=Item_PriorityQueue.top();
+ Item_PriorityQueue.pop();
+ delete The_item_top;
+ }
+
+ void
+ Compute_the_next_nearest_neighbour()
+ {
+ // compute the next item
+ bool next_neighbour_found=false;
+ if (!(Item_PriorityQueue.empty())) {
+ next_neighbour_found=
+ (multiplication_factor*rd > Item_PriorityQueue.top()->second);
+ }
+ typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
+ typename SearchTraits::Cartesian_const_iterator_d query_point_it = construct_it(query_point);
+ // otherwise browse the tree further
+ while ((!next_neighbour_found) && (!PriorityQueue.empty())) {
+ Node_with_distance* The_node_top=PriorityQueue.top();
+ Node_const_handle N= CGAL::cpp11::get<0>(*The_node_top);
+ dists = CGAL::cpp11::get<2>(*The_node_top);
+ PriorityQueue.pop();
+ delete The_node_top;
+ FT copy_rd=rd;
+ while (!(N->is_leaf())) { // compute new distance
+ typename Tree::Internal_node_const_handle node =
+ static_cast<typename Tree::Internal_node_const_handle>(N);
+ number_of_internal_nodes_visited++;
+ int new_cut_dim=node->cutting_dimension();
+ FT new_rd,dst = dists[new_cut_dim];
+ FT val = *(query_point_it + new_cut_dim);
+ FT diff1 = val - node->upper_low_value();
+ FT diff2 = val - node->lower_high_value();
+ if (diff1 + diff2 < FT(0.0)) {
+ new_rd=
+ Orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim);
+
+ CGAL_assertion(new_rd >= copy_rd);
+ dists[new_cut_dim] = diff1;
+ Node_with_distance *Upper_Child =
+ new Node_with_distance(node->upper(), new_rd, dists);
+ PriorityQueue.push(Upper_Child);
+ dists[new_cut_dim] = dst;
+ N=node->lower();
+
+ }
+ else { // compute new distance
+ new_rd=Orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim);
+ CGAL_assertion(new_rd >= copy_rd);
+ dists[new_cut_dim] = diff2;
+ Node_with_distance *Lower_Child =
+ new Node_with_distance(node->lower(), new_rd, dists);
+ PriorityQueue.push(Lower_Child);
+ dists[new_cut_dim] = dst;
+ N=node->upper();
+ }
+ }
+ // n is a leaf
+ typename Tree::Leaf_node_const_handle node =
+ static_cast<typename Tree::Leaf_node_const_handle>(N);
+ number_of_leaf_nodes_visited++;
+ if (node->size() > 0) {
+ for (typename Tree::iterator it=node->begin(); it != node->end(); it++) {
+ number_of_items_visited++;
+ FT distance_to_query_point=
+ Orthogonal_distance_instance.transformed_distance(query_point,*it);
+ Point_with_transformed_distance *NN_Candidate=
+ new Point_with_transformed_distance(*it,distance_to_query_point);
+ Item_PriorityQueue.push(NN_Candidate);
+ }
+ // old top of PriorityQueue has been processed,
+ // hence update rd
+
+ if (!(PriorityQueue.empty())) {
+ rd = CGAL::cpp11::get<1>(*PriorityQueue.top());
+ next_neighbour_found =
+ (multiplication_factor*rd >
+ Item_PriorityQueue.top()->second);
+ }
+ else // priority queue empty => last neighbour found
+ {
+ next_neighbour_found=true;
+ }
+
+ number_of_neighbours_computed++;
+ }
+ } // next_neighbour_found or priority queue is empty
+ // in the latter case also the item priority quee is empty
+ }
+
+
+ void
+ Compute_the_next_furthest_neighbour()
+ {
+ // compute the next item
+ bool next_neighbour_found=false;
+ if (!(Item_PriorityQueue.empty())) {
+ next_neighbour_found=
+ (rd < multiplication_factor*Item_PriorityQueue.top()->second);
+ }
+ typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
+ typename SearchTraits::Cartesian_const_iterator_d query_point_it = construct_it(query_point);
+ // otherwise browse the tree further
+ while ((!next_neighbour_found) && (!PriorityQueue.empty())) {
+ Node_with_distance* The_node_top=PriorityQueue.top();
+ Node_const_handle N= CGAL::cpp11::get<0>(*The_node_top);
+ dists = CGAL::cpp11::get<2>(*The_node_top);
+ PriorityQueue.pop();
+ delete The_node_top;
+ FT copy_rd=rd;
+ while (!(N->is_leaf())) { // compute new distance
+ typename Tree::Internal_node_const_handle node =
+ static_cast<typename Tree::Internal_node_const_handle>(N);
+ number_of_internal_nodes_visited++;
+ int new_cut_dim=node->cutting_dimension();
+ FT new_rd,dst = dists[new_cut_dim];
+ FT val = *(query_point_it + new_cut_dim);
+ FT diff1 = val - node->upper_low_value();
+ FT diff2 = val - node->lower_high_value();
+ if (diff1 + diff2 < FT(0.0)) {
+ diff1 = val - node->upper_high_value();
+ new_rd=
+ Orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim);
+ Node_with_distance *Lower_Child =
+ new Node_with_distance(node->lower(), copy_rd, dists);
+ PriorityQueue.push(Lower_Child);
+ N=node->upper();
+ dists[new_cut_dim] = diff1;
+ copy_rd=new_rd;
+
+ }
+ else { // compute new distance
+ diff2 = val - node->lower_low_value();
+ new_rd=Orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim);
+ Node_with_distance *Upper_Child =
+ new Node_with_distance(node->upper(), copy_rd, dists);
+ PriorityQueue.push(Upper_Child);
+ N=node->lower();
+ dists[new_cut_dim] = diff2;
+ copy_rd=new_rd;
+ }
+ }
+ // n is a leaf
+ typename Tree::Leaf_node_const_handle node =
+ static_cast<typename Tree::Leaf_node_const_handle>(N);
+ number_of_leaf_nodes_visited++;
+ if (node->size() > 0) {
+ for (typename Tree::iterator it=node->begin(); it != node->end(); it++) {
+ number_of_items_visited++;
+ FT distance_to_query_point=
+ Orthogonal_distance_instance.transformed_distance(query_point,*it);
+ Point_with_transformed_distance *NN_Candidate=
+ new Point_with_transformed_distance(*it,distance_to_query_point);
+ Item_PriorityQueue.push(NN_Candidate);
+ }
+ // old top of PriorityQueue has been processed,
+ // hence update rd
+
+ if (!(PriorityQueue.empty())) {
+ rd = CGAL::cpp11::get<1>(*PriorityQueue.top());
+ next_neighbour_found =
+ (multiplication_factor*rd <
+ Item_PriorityQueue.top()->second);
+ }
+ else // priority queue empty => last neighbour found
+ {
+ next_neighbour_found=true;
+ }
+
+ number_of_neighbours_computed++;
+ }
+ } // next_neighbour_found or priority queue is empty
+ // in the latter case also the item priority quee is empty
+ }
+ }; // class Iterator_implementaion
+
+
+
+
+
+
+
+
+
+ public:
+ class iterator;
+ typedef iterator const_iterator;
+
+ // constructor
+ Orthogonal_incremental_neighbor_search(const Tree& tree,
+ const Query_item& q, FT Eps = FT(0.0),
+ bool search_nearest=true, const Distance& tr=Distance())
+ : m_tree(tree),m_query(q),m_dist(tr),m_Eps(Eps),m_search_nearest(search_nearest)
+ {}
+
+ iterator
+ begin() const
+ {
+ return iterator(m_tree,m_query,m_dist,m_Eps,m_search_nearest);
+ }
+
+ iterator
+ end() const
+ {
+ return iterator();
+ }
+
+ std::ostream&
+ statistics(std::ostream& s)
+ {
+ begin()->statistics(s);
+ return s;
+ }
+
+
+
+
+ class iterator {
+
+ public:
+
+ typedef std::input_iterator_tag iterator_category;
+ typedef Point_with_transformed_distance value_type;
+ typedef Point_with_transformed_distance* pointer;
+ typedef const Point_with_transformed_distance& reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef int distance_type;
+
+ //class Iterator_implementation;
+ Iterator_implementation *Ptr_implementation;
+
+
+ public:
+
+ // default constructor
+ iterator()
+ : Ptr_implementation(0)
+ {}
+
+ int
+ the_number_of_items_visited()
+ {
+ return Ptr_implementation->number_of_items_visited;
+ }
+
+ // constructor
+ iterator(const Tree& tree,const Query_item& q, const Distance& tr=Distance(), FT eps=FT(0.0),
+ bool search_nearest=true)
+ : Ptr_implementation(new Iterator_implementation(tree, q, tr, eps, search_nearest))
+ {}
+
+ // copy constructor
+ iterator(const iterator& Iter)
+ {
+ Ptr_implementation = Iter.Ptr_implementation;
+ if (Ptr_implementation != 0) Ptr_implementation->reference_count++;
+ }
+
+ iterator& operator=(const iterator& Iter)
+ {
+ if (Ptr_implementation != Iter.Ptr_implementation){
+ if (Ptr_implementation != 0 && --(Ptr_implementation->reference_count)==0) {
+ delete Ptr_implementation;
+ }
+ Ptr_implementation = Iter.Ptr_implementation;
+ if (Ptr_implementation != 0) Ptr_implementation->reference_count++;
+ }
+ return *this;
+ }
+
+
+ const Point_with_transformed_distance&
+ operator* () const
+ {
+ return *(*Ptr_implementation);
+ }
+
+ // -> operator
+ const Point_with_transformed_distance*
+ operator-> () const
+ {
+ return &*(*Ptr_implementation);
+ }
+
+ // prefix operator
+ iterator&
+ operator++()
+ {
+ ++(*Ptr_implementation);
+ return *this;
+ }
+
+ // postfix operator
+ Object_wrapper<Point_with_transformed_distance>
+ operator++(int)
+ {
+ return (*Ptr_implementation)++;
+ }
+
+
+ bool
+ operator==(const iterator& It) const
+ {
+ if (
+ ((Ptr_implementation == 0) ||
+ Ptr_implementation->Item_PriorityQueue.empty()) &&
+ ((It.Ptr_implementation == 0) ||
+ It.Ptr_implementation->Item_PriorityQueue.empty())
+ )
+ return true;
+ // else
+ return (Ptr_implementation == It.Ptr_implementation);
+ }
+
+ bool
+ operator!=(const iterator& It) const
+ {
+ return !(*this == It);
+ }
+
+ std::ostream&
+ statistics (std::ostream& s)
+ {
+ Ptr_implementation->statistics(s);
+ return s;
+ }
+
+ ~iterator()
+ {
+ if (Ptr_implementation != 0) {
+ Ptr_implementation->reference_count--;
+ if (Ptr_implementation->reference_count==0) {
+ delete Ptr_implementation;
+ Ptr_implementation = 0;
+ }
+ }
+ }
+
+
+ }; // class iterator
+
+ //data members
+ const Tree& m_tree;
+ Query_item m_query;
+ Distance m_dist;
+ FT m_Eps;
+ bool m_search_nearest;
+ }; // class
+
+ template <class Traits, class Query_item, class Distance>
+ void swap (typename Orthogonal_incremental_neighbor_search<Traits,
+ Query_item, Distance>::iterator& x,
+ typename Orthogonal_incremental_neighbor_search<Traits,
+ Query_item, Distance>::iterator& y)
+ {
+ typename Orthogonal_incremental_neighbor_search<Traits,
+ Query_item, Distance>::iterator::Iterator_implementation
+ *tmp = x.Ptr_implementation;
+ x.Ptr_implementation = y.Ptr_implementation;
+ y.Ptr_implementation = tmp;
+ }
+
+} // namespace CGAL
+
+#endif // CGAL_ORTHOGONAL_INCREMENTAL_NEIGHBOR_SEARCH_H
diff --git a/include/gudhi_patches/CGAL/Regular_triangulation.h b/include/gudhi_patches/CGAL/Regular_triangulation.h
new file mode 100644
index 00000000..111c6ac9
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Regular_triangulation.h
@@ -0,0 +1,1169 @@
+// Copyright (c) 2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Clement Jamin
+
+#ifndef CGAL_REGULAR_TRIANGULATION_H
+#define CGAL_REGULAR_TRIANGULATION_H
+
+#include <CGAL/Triangulation.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/Default.h>
+#include <CGAL/spatial_sort.h>
+#include <CGAL/Regular_triangulation_traits_adapter.h>
+
+#include <boost/property_map/function_property_map.hpp>
+
+namespace CGAL {
+
+template< typename Traits_, typename TDS_ = Default >
+class Regular_triangulation
+: public Triangulation<
+ Regular_triangulation_traits_adapter<Traits_>,
+ typename Default::Get<
+ TDS_,
+ Triangulation_data_structure<
+ typename Regular_triangulation_traits_adapter<Traits_>::Dimension,
+ Triangulation_vertex<Regular_triangulation_traits_adapter<Traits_> >,
+ Triangulation_full_cell<Regular_triangulation_traits_adapter<Traits_> >
+ >
+ >::type>
+{
+ typedef Regular_triangulation_traits_adapter<Traits_> RTTraits;
+ typedef typename RTTraits::Dimension Maximal_dimension_;
+ typedef typename Default::Get<
+ TDS_,
+ Triangulation_data_structure<
+ Maximal_dimension_,
+ Triangulation_vertex<RTTraits>,
+ Triangulation_full_cell<RTTraits>
+ > >::type TDS;
+ typedef Triangulation<RTTraits, TDS> Base;
+ typedef Regular_triangulation<Traits_, TDS_> Self;
+
+ typedef typename RTTraits::Orientation_d Orientation_d;
+ typedef typename RTTraits::Power_side_of_power_sphere_d Power_side_of_power_sphere_d;
+ typedef typename RTTraits::In_flat_power_side_of_power_sphere_d
+ In_flat_power_side_of_power_sphere_d;
+ typedef typename RTTraits::Flat_orientation_d Flat_orientation_d;
+ typedef typename RTTraits::Construct_flat_orientation_d Construct_flat_orientation_d;
+
+public: // PUBLIC NESTED TYPES
+
+ typedef RTTraits Geom_traits;
+ typedef typename Base::Triangulation_ds Triangulation_ds;
+
+ typedef typename Base::Vertex Vertex;
+ typedef typename Base::Full_cell Full_cell;
+ typedef typename Base::Facet Facet;
+ typedef typename Base::Face Face;
+
+ typedef Maximal_dimension_ Maximal_dimension;
+ typedef typename RTTraits::Bare_point_d Bare_point;
+ typedef typename RTTraits::Weighted_point_d Weighted_point;
+
+ typedef typename Base::Point_const_iterator Point_const_iterator;
+ typedef typename Base::Vertex_handle Vertex_handle;
+ typedef typename Base::Vertex_iterator Vertex_iterator;
+ typedef typename Base::Vertex_const_handle Vertex_const_handle;
+ typedef typename Base::Vertex_const_iterator Vertex_const_iterator;
+
+ typedef typename Base::Full_cell_handle Full_cell_handle;
+ typedef typename Base::Full_cell_iterator Full_cell_iterator;
+ typedef typename Base::Full_cell_const_handle Full_cell_const_handle;
+ typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator;
+ typedef typename Base::Finite_full_cell_const_iterator
+ Finite_full_cell_const_iterator;
+
+ typedef typename Base::size_type size_type;
+ typedef typename Base::difference_type difference_type;
+
+ typedef typename Base::Locate_type Locate_type;
+
+ //Tag to distinguish Delaunay from Regular triangulations
+ typedef Tag_true Weighted_tag;
+
+protected: // DATA MEMBERS
+
+
+public:
+
+ using typename Base::Rotor;
+ using Base::maximal_dimension;
+ using Base::are_incident_full_cells_valid;
+ using Base::coaffine_orientation_predicate;
+ using Base::reset_flat_orientation;
+ using Base::current_dimension;
+ using Base::geom_traits;
+ using Base::index_of_covertex;
+ //using Base::index_of_second_covertex;
+ using Base::rotate_rotor;
+ using Base::infinite_vertex;
+ using Base::insert_in_hole;
+ using Base::is_infinite;
+ using Base::locate;
+ using Base::points_begin;
+ using Base::set_neighbors;
+ using Base::new_full_cell;
+ using Base::number_of_vertices;
+ using Base::orientation;
+ using Base::tds;
+ using Base::reorient_full_cells;
+ using Base::full_cell;
+ using Base::full_cells_begin;
+ using Base::full_cells_end;
+ using Base::finite_full_cells_begin;
+ using Base::finite_full_cells_end;
+ using Base::vertices_begin;
+ using Base::vertices_end;
+
+private:
+
+ // Wrapper
+ struct Power_side_of_power_sphere_for_non_maximal_dim_d
+ {
+ boost::optional<Flat_orientation_d>* fop;
+ Construct_flat_orientation_d cfo;
+ In_flat_power_side_of_power_sphere_d ifpt;
+
+ Power_side_of_power_sphere_for_non_maximal_dim_d(
+ boost::optional<Flat_orientation_d>& x,
+ Construct_flat_orientation_d const&y,
+ In_flat_power_side_of_power_sphere_d const&z)
+ : fop(&x), cfo(y), ifpt(z) {}
+
+ template<class Iter>
+ CGAL::Orientation operator()(Iter a, Iter b, const Weighted_point & p)const
+ {
+ if(!*fop)
+ *fop=cfo(a,b);
+ return ifpt(fop->get(),a,b,p);
+ }
+ };
+
+public:
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS
+
+ Regular_triangulation(int dim, const Geom_traits &k = Geom_traits())
+ : Base(dim, k)
+ {
+ }
+
+ // With this constructor,
+ // the user can specify a Flat_orientation_d object to be used for
+ // orienting simplices of a specific dimension
+ // (= preset_flat_orientation_.first)
+ // It it used by the dark triangulations created by DT::remove
+ Regular_triangulation(
+ int dim,
+ const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation,
+ const Geom_traits &k = Geom_traits())
+ : Base(dim, preset_flat_orientation, k)
+ {
+ }
+
+ ~Regular_triangulation() {}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS
+
+ // Not Documented
+ Power_side_of_power_sphere_for_non_maximal_dim_d power_side_of_power_sphere_for_non_maximal_dim_predicate() const
+ {
+ return Power_side_of_power_sphere_for_non_maximal_dim_d (
+ flat_orientation_,
+ geom_traits().construct_flat_orientation_d_object(),
+ geom_traits().in_flat_power_side_of_power_sphere_d_object()
+ );
+ }
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
+
+ // Warning: these functions are not correct since they do not restore hidden
+ // vertices
+
+ Full_cell_handle remove(Vertex_handle);
+ Full_cell_handle remove(const Weighted_point & p, Full_cell_handle hint = Full_cell_handle())
+ {
+ Locate_type lt;
+ Face f(maximal_dimension());
+ Facet ft;
+ Full_cell_handle s = locate(p, lt, f, ft, hint);
+ if( Base::ON_VERTEX == lt )
+ {
+ return remove(s->vertex(f.index(0)));
+ }
+ return Full_cell_handle();
+ }
+
+ template< typename ForwardIterator >
+ void remove(ForwardIterator start, ForwardIterator end)
+ {
+ while( start != end )
+ remove(*start++);
+ }
+
+ // Not documented
+ void remove_decrease_dimension(Vertex_handle);
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS
+
+ template< typename ForwardIterator >
+ std::ptrdiff_t insert(ForwardIterator start, ForwardIterator end)
+ {
+ size_type n = number_of_vertices();
+ typedef std::vector<Weighted_point> WP_vec;
+ WP_vec points(start, end);
+
+ spatial_sort(points.begin(), points.end(), geom_traits());
+
+ Full_cell_handle hint;
+ for(typename WP_vec::const_iterator p = points.begin(); p != points.end(); ++p )
+ {
+ Locate_type lt;
+ Face f(maximal_dimension());
+ Facet ft;
+ Full_cell_handle c = locate (*p, lt, f, ft, hint);
+ Vertex_handle v = insert (*p, lt, f, ft, c);
+
+ hint = v == Vertex_handle() ? c : v->full_cell();
+ }
+ return number_of_vertices() - n;
+ }
+
+ Vertex_handle insert(const Weighted_point &,
+ Locate_type,
+ const Face &,
+ const Facet &,
+ Full_cell_handle);
+
+ Vertex_handle insert(const Weighted_point & p,
+ Full_cell_handle start = Full_cell_handle())
+ {
+ Locate_type lt;
+ Face f(maximal_dimension());
+ Facet ft;
+ Full_cell_handle s = locate(p, lt, f, ft, start);
+ return insert(p, lt, f, ft, s);
+ }
+
+ Vertex_handle insert(const Weighted_point & p, Vertex_handle hint)
+ {
+ CGAL_assertion( Vertex_handle() != hint );
+ return insert(p, hint->full_cell());
+ }
+
+ Vertex_handle insert_outside_affine_hull(const Weighted_point &);
+ Vertex_handle insert_in_conflicting_cell(
+ const Weighted_point &, Full_cell_handle,
+ Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle());
+
+ Vertex_handle insert_if_in_star(const Weighted_point &,
+ Vertex_handle,
+ Locate_type,
+ const Face &,
+ const Facet &,
+ Full_cell_handle);
+
+ Vertex_handle insert_if_in_star(
+ const Weighted_point & p, Vertex_handle star_center,
+ Full_cell_handle start = Full_cell_handle())
+ {
+ Locate_type lt;
+ Face f(maximal_dimension());
+ Facet ft;
+ Full_cell_handle s = locate(p, lt, f, ft, start);
+ return insert_if_in_star(p, star_center, lt, f, ft, s);
+ }
+
+ Vertex_handle insert_if_in_star(
+ const Weighted_point & p, Vertex_handle star_center,
+ Vertex_handle hint)
+ {
+ CGAL_assertion( Vertex_handle() != hint );
+ return insert_if_in_star(p, star_center, hint->full_cell());
+ }
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES
+
+ bool is_in_conflict(const Weighted_point &, Full_cell_const_handle) const;
+
+ template< class OrientationPredicate >
+ Oriented_side perturbed_power_side_of_power_sphere(const Weighted_point &,
+ Full_cell_const_handle, const OrientationPredicate &) const;
+
+ template< typename OutputIterator >
+ Facet compute_conflict_zone(const Weighted_point &, Full_cell_handle, OutputIterator) const;
+
+ template < typename OrientationPredicate, typename PowerTestPredicate >
+ class Conflict_predicate
+ {
+ const Self & rt_;
+ const Weighted_point & p_;
+ OrientationPredicate ori_;
+ PowerTestPredicate power_side_of_power_sphere_;
+ int cur_dim_;
+ public:
+ Conflict_predicate(
+ const Self & rt,
+ const Weighted_point & p,
+ const OrientationPredicate & ori,
+ const PowerTestPredicate & power_side_of_power_sphere)
+ : rt_(rt), p_(p), ori_(ori), power_side_of_power_sphere_(power_side_of_power_sphere), cur_dim_(rt.current_dimension()) {}
+
+ inline
+ bool operator()(Full_cell_const_handle s) const
+ {
+ bool ok;
+ if( ! rt_.is_infinite(s) )
+ {
+ Oriented_side power_side_of_power_sphere = power_side_of_power_sphere_(rt_.points_begin(s), rt_.points_begin(s) + cur_dim_ + 1, p_);
+ if( ON_POSITIVE_SIDE == power_side_of_power_sphere )
+ ok = true;
+ else if( ON_NEGATIVE_SIDE == power_side_of_power_sphere )
+ ok = false;
+ else
+ ok = ON_POSITIVE_SIDE == rt_.perturbed_power_side_of_power_sphere<OrientationPredicate>(p_, s, ori_);
+ }
+ else
+ {
+ typedef typename Full_cell::Vertex_handle_const_iterator VHCI;
+ typedef Substitute_point_in_vertex_iterator<VHCI> F;
+ F spivi(rt_.infinite_vertex(), &p_);
+
+ Orientation o = ori_(
+ boost::make_transform_iterator(s->vertices_begin(), spivi),
+ boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1,
+ spivi));
+
+ if( POSITIVE == o )
+ ok = true;
+ else if( o == NEGATIVE )
+ ok = false;
+ else
+ ok = (*this)(s->neighbor( s->index( rt_.infinite_vertex() ) ));
+ }
+ return ok;
+ }
+ };
+
+ template < typename ConflictPredicate >
+ class Conflict_traversal_predicate
+ {
+ const Self & rt_;
+ const ConflictPredicate & pred_;
+ public:
+ Conflict_traversal_predicate(const Self & rt, const ConflictPredicate & pred)
+ : rt_(rt), pred_(pred)
+ {}
+ inline
+ bool operator()(const Facet & f) const
+ {
+ return pred_(rt_.full_cell(f)->neighbor(rt_.index_of_covertex(f)));
+ }
+ };
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
+
+ bool is_valid(bool verbose = false, int level = 0) const;
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MISC
+
+ std::size_t number_of_hidden_vertices() const
+ {
+ return m_hidden_points.size();
+ }
+
+private:
+
+ template<typename InputIterator>
+ bool
+ does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end,
+ Vertex_handle vh) const
+ {
+ // Check all vertices
+ while(cz_begin != cz_end)
+ {
+ Full_cell_handle fch = *cz_begin;
+ for (int i = 0 ; i <= current_dimension() ; ++i)
+ {
+ if (fch->vertex(i) == vh)
+ return true;
+ }
+ ++cz_begin;
+ }
+ return false;
+ }
+
+ template<typename InputIterator, typename OutputIterator>
+ void
+ process_conflict_zone(InputIterator cz_begin, InputIterator cz_end,
+ OutputIterator vertices_out) const
+ {
+ // Get all vertices
+ while(cz_begin != cz_end)
+ {
+ Full_cell_handle fch = *cz_begin;
+ for (int i = 0 ; i <= current_dimension() ; ++i)
+ {
+ Vertex_handle vh = fch->vertex(i);
+ if (vh->full_cell() != Full_cell_handle())
+ {
+ (*vertices_out++) = vh;
+ vh->set_full_cell(Full_cell_handle());
+ }
+ }
+ ++cz_begin;
+ }
+ }
+
+
+ template<typename InputIterator>
+ void
+ process_cz_vertices_after_insertion(InputIterator vertices_begin,
+ InputIterator vertices_end)
+ {
+ // Get all vertices
+ while(vertices_begin != vertices_end)
+ {
+ Vertex_handle vh = *vertices_begin;
+ if (vh->full_cell() == Full_cell_handle())
+ {
+ m_hidden_points.push_back(vh->point());
+ tds().delete_vertex(vh);
+ }
+ ++vertices_begin;
+ }
+ }
+
+private:
+ // Some internal types to shorten notation
+ using typename Base::Coaffine_orientation_d;
+ using Base::flat_orientation_;
+ typedef Conflict_predicate<Coaffine_orientation_d, Power_side_of_power_sphere_for_non_maximal_dim_d>
+ Conflict_pred_in_subspace;
+ typedef Conflict_predicate<Orientation_d, Power_side_of_power_sphere_d>
+ Conflict_pred_in_fullspace;
+ typedef Conflict_traversal_predicate<Conflict_pred_in_subspace>
+ Conflict_traversal_pred_in_subspace;
+ typedef Conflict_traversal_predicate<Conflict_pred_in_fullspace>
+ Conflict_traversal_pred_in_fullspace;
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MEMBER VARIABLES
+ std::vector<Weighted_point> m_hidden_points;
+
+}; // class Regular_triangulation
+
+
+// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+// FUNCTIONS THAT ARE MEMBER METHODS:
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
+
+
+// Warning: this function is not correct since it does not restore hidden
+// vertices
+template< typename Traits, typename TDS >
+typename Regular_triangulation<Traits, TDS>::Full_cell_handle
+Regular_triangulation<Traits, TDS>
+::remove( Vertex_handle v )
+{
+ CGAL_precondition( ! is_infinite(v) );
+ CGAL_expensive_precondition( is_vertex(v) );
+
+ // THE CASE cur_dim == 0
+ if( 0 == current_dimension() )
+ {
+ remove_decrease_dimension(v);
+ return Full_cell_handle();
+ }
+ else if( 1 == current_dimension() )
+ { // THE CASE cur_dim == 1
+ if( 2 == number_of_vertices() )
+ {
+ remove_decrease_dimension(v);
+ return Full_cell_handle();
+ }
+ Full_cell_handle left = v->full_cell();
+ if( 0 == left->index(v) )
+ left = left->neighbor(1);
+ CGAL_assertion( 1 == left->index(v) );
+ Full_cell_handle right = left->neighbor(0);
+ tds().associate_vertex_with_full_cell(left, 1, right->vertex(1));
+ set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0));
+ tds().delete_vertex(v);
+ tds().delete_full_cell(right);
+ return left;
+ }
+
+ // THE CASE cur_dim >= 2
+ // Gather the finite vertices sharing an edge with |v|
+ typedef typename Base::template Full_cell_set<Full_cell_handle> Simplices;
+ Simplices simps;
+ std::back_insert_iterator<Simplices> out(simps);
+ tds().incident_full_cells(v, out);
+ typedef std::set<Vertex_handle> Vertex_set;
+ Vertex_set verts;
+ Vertex_handle vh;
+ for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it )
+ for( int i = 0; i <= current_dimension(); ++i )
+ {
+ vh = (*it)->vertex(i);
+ if( is_infinite(vh) )
+ continue;
+ if( vh == v )
+ continue;
+ verts.insert(vh);
+ }
+
+ // After gathering finite neighboring vertices, create their Dark Delaunay triangulation
+ typedef Triangulation_vertex<Geom_traits, Vertex_handle> Dark_vertex_base;
+ typedef Triangulation_full_cell<
+ Geom_traits,
+ internal::Triangulation::Dark_full_cell_data<TDS> > Dark_full_cell_base;
+ typedef Triangulation_data_structure<Maximal_dimension,
+ Dark_vertex_base,
+ Dark_full_cell_base
+ > Dark_tds;
+ typedef Regular_triangulation<Traits, Dark_tds> Dark_triangulation;
+ typedef typename Dark_triangulation::Face Dark_face;
+ typedef typename Dark_triangulation::Facet Dark_facet;
+ typedef typename Dark_triangulation::Vertex_handle Dark_v_handle;
+ typedef typename Dark_triangulation::Full_cell_handle Dark_s_handle;
+
+ // If flat_orientation_ is defined, we give it the Dark triangulation
+ // so that the orientation it uses for "current_dimension()"-simplices is
+ // coherent with the global triangulation
+ Dark_triangulation dark_side(
+ maximal_dimension(),
+ flat_orientation_ ?
+ std::pair<int, const Flat_orientation_d *>(current_dimension(), flat_orientation_.get_ptr())
+ : std::pair<int, const Flat_orientation_d *>(std::numeric_limits<int>::max(), NULL) );
+
+ Dark_s_handle dark_s;
+ Dark_v_handle dark_v;
+ typedef std::map<Vertex_handle, Dark_v_handle> Vertex_map;
+ Vertex_map light_to_dark;
+ typename Vertex_set::iterator vit = verts.begin();
+ while( vit != verts.end() )
+ {
+ dark_v = dark_side.insert((*vit)->point(), dark_s);
+ dark_s = dark_v->full_cell();
+ dark_v->data() = *vit;
+ light_to_dark[*vit] = dark_v;
+ ++vit;
+ }
+
+ if( dark_side.current_dimension() != current_dimension() )
+ {
+ CGAL_assertion( dark_side.current_dimension() + 1 == current_dimension() );
+ // Here, the finite neighbors of |v| span a affine subspace of
+ // dimension one less than the current dimension. Two cases are possible:
+ if( (size_type)(verts.size() + 1) == number_of_vertices() )
+ {
+ remove_decrease_dimension(v);
+ return Full_cell_handle();
+ }
+ else
+ { // |v| is strictly outside the convex hull of the rest of the points. This is an
+ // easy case: first, modify the finite full_cells, then, delete the infinite ones.
+ // We don't even need the Dark triangulation.
+ Simplices infinite_simps;
+ {
+ Simplices finite_simps;
+ for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it )
+ if( is_infinite(*it) )
+ infinite_simps.push_back(*it);
+ else
+ finite_simps.push_back(*it);
+ simps.swap(finite_simps);
+ } // now, simps only contains finite simplices
+ // First, modify the finite full_cells:
+ for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it )
+ {
+ int v_idx = (*it)->index(v);
+ tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex());
+ }
+ // Make the handles to infinite full cells searchable
+ infinite_simps.make_searchable();
+ // Then, modify the neighboring relation
+ for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it )
+ {
+ for( int i = 0 ; i <= current_dimension(); ++i )
+ {
+ if (is_infinite((*it)->vertex(i)))
+ continue;
+ (*it)->vertex(i)->set_full_cell(*it);
+ Full_cell_handle n = (*it)->neighbor(i);
+ // Was |n| a finite full cell prior to removing |v| ?
+ if( ! infinite_simps.contains(n) )
+ continue;
+ int n_idx = n->index(v);
+ set_neighbors(*it, i, n->neighbor(n_idx), n->neighbor(n_idx)->index(n));
+ }
+ }
+ Full_cell_handle ret_s;
+ // Then, we delete the infinite full_cells
+ for( typename Simplices::iterator it = infinite_simps.begin(); it != infinite_simps.end(); ++it )
+ tds().delete_full_cell(*it);
+ tds().delete_vertex(v);
+ return simps.front();
+ }
+ }
+ else // From here on, dark_side.current_dimension() == current_dimension()
+ {
+ dark_side.infinite_vertex()->data() = infinite_vertex();
+ light_to_dark[infinite_vertex()] = dark_side.infinite_vertex();
+ }
+
+ // Now, compute the conflict zone of v->point() in
+ // the dark side. This is precisely the set of full_cells
+ // that we have to glue back into the light side.
+ Dark_face dark_f(dark_side.maximal_dimension());
+ Dark_facet dark_ft;
+ typename Dark_triangulation::Locate_type lt;
+ dark_s = dark_side.locate(v->point(), lt, dark_f, dark_ft);
+ CGAL_assertion( lt != Dark_triangulation::ON_VERTEX
+ && lt != Dark_triangulation::OUTSIDE_AFFINE_HULL );
+
+ // |ret_s| is the full_cell that we return
+ Dark_s_handle dark_ret_s = dark_s;
+ Full_cell_handle ret_s;
+
+ typedef typename Base::template Full_cell_set<Dark_s_handle> Dark_full_cells;
+ Dark_full_cells conflict_zone;
+ std::back_insert_iterator<Dark_full_cells> dark_out(conflict_zone);
+
+ dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out);
+ // Make the dark simplices in the conflict zone searchable
+ conflict_zone.make_searchable();
+
+ // THE FOLLOWING SHOULD MAYBE GO IN TDS.
+ // Here is the plan:
+ // 1. Pick any Facet from boundary of the light zone
+ // 2. Find corresponding Facet on boundary of dark zone
+ // 3. stitch.
+
+ // 1. Build a facet on the boudary of the light zone:
+ Full_cell_handle light_s = *simps.begin();
+ Facet light_ft(light_s, light_s->index(v));
+
+ // 2. Find corresponding Dark_facet on boundary of the dark zone
+ Dark_full_cells dark_incident_s;
+ for( int i = 0; i <= current_dimension(); ++i )
+ {
+ if( index_of_covertex(light_ft) == i )
+ continue;
+ Dark_v_handle dark_v = light_to_dark[full_cell(light_ft)->vertex(i)];
+ dark_incident_s.clear();
+ dark_out = std::back_inserter(dark_incident_s);
+ dark_side.tds().incident_full_cells(dark_v, dark_out);
+ for(typename Dark_full_cells::iterator it = dark_incident_s.begin();
+ it != dark_incident_s.end();
+ ++it)
+ {
+ (*it)->data().count_ += 1;
+ }
+ }
+
+ for( typename Dark_full_cells::iterator it = dark_incident_s.begin(); it != dark_incident_s.end(); ++it )
+ {
+ if( current_dimension() != (*it)->data().count_ )
+ continue;
+ if( ! conflict_zone.contains(*it) )
+ continue;
+ // We found a full_cell incident to the dark facet corresponding to the light facet |light_ft|
+ int ft_idx = 0;
+ while( light_s->has_vertex( (*it)->vertex(ft_idx)->data() ) )
+ ++ft_idx;
+ dark_ft = Dark_facet(*it, ft_idx);
+ break;
+ }
+ // Pre-3. Now, we are ready to traverse both boundary and do the stiching.
+
+ // But first, we create the new full_cells in the light triangulation,
+ // with as much adjacency information as possible.
+
+ // Create new full_cells with vertices
+ for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it )
+ {
+ Full_cell_handle new_s = new_full_cell();
+ (*it)->data().light_copy_ = new_s;
+ for( int i = 0; i <= current_dimension(); ++i )
+ tds().associate_vertex_with_full_cell(new_s, i, (*it)->vertex(i)->data());
+ if( dark_ret_s == *it )
+ ret_s = new_s;
+ }
+
+ // Setup adjacencies inside the hole
+ for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it )
+ {
+ Full_cell_handle new_s = (*it)->data().light_copy_;
+ for( int i = 0; i <= current_dimension(); ++i )
+ if( conflict_zone.contains((*it)->neighbor(i)) )
+ tds().set_neighbors(new_s, i, (*it)->neighbor(i)->data().light_copy_, (*it)->mirror_index(i));
+ }
+
+ // 3. Stitch
+ simps.make_searchable();
+ typedef std::queue<std::pair<Facet, Dark_facet> > Queue;
+ Queue q;
+ q.push(std::make_pair(light_ft, dark_ft));
+ dark_s = dark_side.full_cell(dark_ft);
+ int dark_i = dark_side.index_of_covertex(dark_ft);
+ // mark dark_ft as visited:
+ // TODO try by marking with Dark_v_handle (vertex)
+ dark_s->neighbor(dark_i)->set_neighbor(dark_s->mirror_index(dark_i), Dark_s_handle());
+ while( ! q.empty() )
+ {
+ std::pair<Facet, Dark_facet> p = q.front();
+ q.pop();
+ light_ft = p.first;
+ dark_ft = p.second;
+ light_s = full_cell(light_ft);
+ int light_i = index_of_covertex(light_ft);
+ dark_s = dark_side.full_cell(dark_ft);
+ int dark_i = dark_side.index_of_covertex(dark_ft);
+ Full_cell_handle light_n = light_s->neighbor(light_i);
+ set_neighbors(dark_s->data().light_copy_, dark_i, light_n, light_s->mirror_index(light_i));
+ for( int di = 0; di <= current_dimension(); ++di )
+ {
+ if( di == dark_i )
+ continue;
+ int li = light_s->index(dark_s->vertex(di)->data());
+ Rotor light_r(light_s, li, light_i);
+ typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i);
+
+ while( simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r))) )
+ light_r = rotate_rotor(light_r);
+
+ while( conflict_zone.contains(cpp11::get<0>(dark_r)->neighbor(cpp11::get<1>(dark_r))) )
+ dark_r = dark_side.rotate_rotor(dark_r);
+
+ Dark_s_handle dark_ns = cpp11::get<0>(dark_r);
+ int dark_ni = cpp11::get<1>(dark_r);
+ Full_cell_handle light_ns = cpp11::get<0>(light_r);
+ int light_ni = cpp11::get<1>(light_r);
+ // mark dark_r as visited:
+ // TODO try by marking with Dark_v_handle (vertex)
+ Dark_s_handle outside = dark_ns->neighbor(dark_ni);
+ Dark_v_handle mirror = dark_ns->mirror_vertex(dark_ni, current_dimension());
+ int dn = outside->index(mirror);
+ if( Dark_s_handle() == outside->neighbor(dn) )
+ continue;
+ outside->set_neighbor(dn, Dark_s_handle());
+ q.push(std::make_pair(Facet(light_ns, light_ni), Dark_facet(dark_ns, dark_ni)));
+ }
+ }
+ tds().delete_full_cells(simps.begin(), simps.end());
+ tds().delete_vertex(v);
+ return ret_s;
+}
+
+template< typename Traits, typename TDS >
+void
+Regular_triangulation<Traits, TDS>
+::remove_decrease_dimension(Vertex_handle v)
+{
+ CGAL_precondition( current_dimension() >= 0 );
+ tds().remove_decrease_dimension(v, infinite_vertex());
+ // reset the predicates:
+ reset_flat_orientation();
+ if( 1 <= current_dimension() )
+ {
+ Full_cell_handle inf_v_cell = infinite_vertex()->full_cell();
+ int inf_v_index = inf_v_cell->index(infinite_vertex());
+ Full_cell_handle s = inf_v_cell->neighbor(inf_v_index);
+ Orientation o = orientation(s);
+ CGAL_assertion( ZERO != o );
+ if( NEGATIVE == o )
+ reorient_full_cells();
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS
+
+template< typename Traits, typename TDS >
+typename Regular_triangulation<Traits, TDS>::Vertex_handle
+Regular_triangulation<Traits, TDS>
+::insert(const Weighted_point & p, Locate_type lt, const Face & f, const Facet & ft, Full_cell_handle s)
+{
+ switch( lt )
+ {
+ case Base::OUTSIDE_AFFINE_HULL:
+ return insert_outside_affine_hull(p);
+ break;
+ case Base::ON_VERTEX:
+ {
+ Vertex_handle v = s->vertex(f.index(0));
+ typename RTTraits::Compute_weight_d pw =
+ geom_traits().compute_weight_d_object();
+
+ if (pw(p) == pw(v->point()))
+ return v;
+ // If dim == 0 and the new point has a bigger weight,
+ // we just replace the point, and the former point gets hidden
+ else if (current_dimension() == 0)
+ {
+ if (pw(p) > pw(v->point()))
+ {
+ m_hidden_points.push_back(v->point());
+ v->set_point(p);
+ return v;
+ }
+ // Otherwise, the new point is hidden
+ else
+ {
+ m_hidden_points.push_back(p);
+ return Vertex_handle();
+ }
+ }
+ // Otherwise, we apply the "normal" algorithm
+
+ // !NO break here!
+ }
+ default:
+ return insert_in_conflicting_cell(p, s);
+ }
+}
+
+/*
+Inserts the point `p` in the regular triangulation. Returns a handle to the
+newly created vertex at that position.
+\pre The point `p`
+must lie outside the affine hull of the regular triangulation. This implies that
+`rt`.`current_dimension()` must be smaller than `rt`.`maximal_dimension()`.
+*/
+template< typename Traits, typename TDS >
+typename Regular_triangulation<Traits, TDS>::Vertex_handle
+Regular_triangulation<Traits, TDS>
+::insert_outside_affine_hull(const Weighted_point & p)
+{
+ // we don't use Base::insert_outside_affine_hull(...) because here, we
+ // also need to reset the side_of_oriented_subsphere functor.
+ CGAL_precondition( current_dimension() < maximal_dimension() );
+ Vertex_handle v = tds().insert_increase_dimension(infinite_vertex());
+ // reset the predicates:
+ reset_flat_orientation();
+ v->set_point(p);
+ if( current_dimension() >= 1 )
+ {
+ Full_cell_handle inf_v_cell = infinite_vertex()->full_cell();
+ int inf_v_index = inf_v_cell->index(infinite_vertex());
+ Full_cell_handle s = inf_v_cell->neighbor(inf_v_index);
+ Orientation o = orientation(s);
+ CGAL_assertion( ZERO != o );
+ if( NEGATIVE == o )
+ reorient_full_cells();
+
+ // We just inserted the second finite point and the right infinite
+ // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be
+ // consistent with the rest of the cells
+ if (current_dimension() == 1)
+ {
+ // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1
+ if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0
+ && inf_v_index == 0)
+ {
+ inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension());
+ }
+ else
+ {
+ inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2);
+ inf_v_index = inf_v_cell->index(infinite_vertex());
+ // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1
+ if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0
+ && inf_v_index == 0)
+ {
+ inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension());
+ }
+ }
+ }
+ }
+ return v;
+}
+
+template< typename Traits, typename TDS >
+typename Regular_triangulation<Traits, TDS>::Vertex_handle
+Regular_triangulation<Traits, TDS>
+::insert_if_in_star(const Weighted_point & p,
+ Vertex_handle star_center,
+ Locate_type lt,
+ const Face & f,
+ const Facet & ft,
+ Full_cell_handle s)
+{
+ switch( lt )
+ {
+ case Base::OUTSIDE_AFFINE_HULL:
+ return insert_outside_affine_hull(p);
+ break;
+ case Base::ON_VERTEX:
+ {
+ Vertex_handle v = s->vertex(f.index(0));
+ typename RTTraits::Compute_weight_d pw =
+ geom_traits().compute_weight_d_object();
+ if (pw(p) == pw(v->point()))
+ return v;
+ // If dim == 0 and the new point has a bigger weight,
+ // we replace the point
+ else if (current_dimension() == 0)
+ {
+ if (pw(p) > pw(v->point()))
+ v->set_point(p);
+ else
+ return v;
+ }
+ // Otherwise, we apply the "normal" algorithm
+
+ // !NO break here!
+ }
+ default:
+ return insert_in_conflicting_cell(p, s, star_center);
+ }
+
+ return Vertex_handle();
+}
+
+/*
+[Undocumented function]
+
+Inserts the point `p` in the regular triangulation. `p` must be
+in conflict with the second parameter `c`, which is used as a
+starting point for `compute_conflict_zone`.
+The function is faster than the standard `insert` function since
+it does not need to call `locate`.
+
+If this insertion creates a vertex, this vertex is returned.
+
+If `p` coincides with an existing vertex and has a greater weight,
+then the existing weighted point becomes hidden and `p` replaces it as vertex
+of the triangulation.
+
+If `p` coincides with an already existing vertex (both point and
+weights being equal), then this vertex is returned and the triangulation
+remains unchanged.
+
+Otherwise if `p` does not appear as a vertex of the triangulation,
+then it is stored as a hidden point and this method returns the default
+constructed handle.
+
+\pre The point `p` must be in conflict with the full cell `c`.
+*/
+
+template< typename Traits, typename TDS >
+typename Regular_triangulation<Traits, TDS>::Vertex_handle
+Regular_triangulation<Traits, TDS>
+::insert_in_conflicting_cell(const Weighted_point & p,
+ Full_cell_handle s,
+ Vertex_handle only_if_this_vertex_is_in_the_cz)
+{
+ typedef std::vector<Full_cell_handle> Full_cell_h_vector;
+
+ bool in_conflict = is_in_conflict(p, s);
+
+ // If p is not in conflict with s, then p is hidden
+ // => we don't insert it
+ if (!in_conflict)
+ {
+ m_hidden_points.push_back(p);
+ return Vertex_handle();
+ }
+ else
+ {
+ Full_cell_h_vector cs; // for storing conflicting full_cells.
+ cs.reserve(64);
+ std::back_insert_iterator<Full_cell_h_vector> out(cs);
+ Facet ft = compute_conflict_zone(p, s, out);
+
+ // Check if the CZ contains "only_if_this_vertex_is_in_the_cz"
+ if (only_if_this_vertex_is_in_the_cz != Vertex_handle()
+ && !does_cell_range_contain_vertex(cs.begin(), cs.end(),
+ only_if_this_vertex_is_in_the_cz))
+ {
+ return Vertex_handle();
+ }
+
+ // Otherwise, proceed with the insertion
+ std::vector<Vertex_handle> cz_vertices;
+ cz_vertices.reserve(64);
+ process_conflict_zone(cs.begin(), cs.end(),
+ std::back_inserter(cz_vertices));
+
+ Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft);
+
+ process_cz_vertices_after_insertion(cz_vertices.begin(), cz_vertices.end());
+
+ return ret;
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES
+
+// NOT DOCUMENTED
+template< typename Traits, typename TDS >
+template< typename OrientationPred >
+Oriented_side
+Regular_triangulation<Traits, TDS>
+::perturbed_power_side_of_power_sphere(const Weighted_point & p, Full_cell_const_handle s,
+ const OrientationPred & ori) const
+{
+ CGAL_precondition_msg( ! is_infinite(s), "full cell must be finite");
+ CGAL_expensive_precondition( POSITIVE == orientation(s) );
+ typedef std::vector<const Weighted_point *> Points;
+ Points points(current_dimension() + 2);
+ int i(0);
+ for( ; i <= current_dimension(); ++i )
+ points[i] = &(s->vertex(i)->point());
+ points[i] = &p;
+ std::sort(points.begin(), points.end(),
+ internal::Triangulation::Compare_points_for_perturbation<Self>(*this));
+ typename Points::const_reverse_iterator cut_pt = points.rbegin();
+ Points test_points;
+ while( cut_pt != points.rend() )
+ {
+ if( &p == *cut_pt )
+ // because the full_cell "s" is assumed to be positively oriented
+ return ON_NEGATIVE_SIDE; // we consider |p| to lie outside the sphere
+ test_points.clear();
+ Point_const_iterator spit = points_begin(s);
+ int adjust_sign = -1;
+ for( i = 0; i < current_dimension(); ++i )
+ {
+ if( &(*spit) == *cut_pt )
+ {
+ ++spit;
+ adjust_sign = (((current_dimension() + i) % 2) == 0) ? -1 : +1;
+ }
+ test_points.push_back(&(*spit));
+ ++spit;
+ }
+ test_points.push_back(&p);
+
+ typedef typename CGAL::Iterator_project<
+ typename Points::iterator,
+ internal::Triangulation::Point_from_pointer<Self>,
+ const Weighted_point &, const Weighted_point *
+ > Point_pointer_iterator;
+
+ Orientation ori_value = ori(
+ Point_pointer_iterator(test_points.begin()),
+ Point_pointer_iterator(test_points.end()));
+
+ if( ZERO != ori_value )
+ return Oriented_side( - adjust_sign * ori_value );
+
+ ++cut_pt;
+ }
+ CGAL_assertion(false); // we should never reach here
+ return ON_NEGATIVE_SIDE;
+}
+
+template< typename Traits, typename TDS >
+bool
+Regular_triangulation<Traits, TDS>
+::is_in_conflict(const Weighted_point & p, Full_cell_const_handle s) const
+{
+ CGAL_precondition( 1 <= current_dimension() );
+ if( current_dimension() < maximal_dimension() )
+ {
+ Conflict_pred_in_subspace c(
+ *this, p,
+ coaffine_orientation_predicate(),
+ power_side_of_power_sphere_for_non_maximal_dim_predicate());
+ return c(s);
+ }
+ else
+ {
+ Orientation_d ori = geom_traits().orientation_d_object();
+ Power_side_of_power_sphere_d side = geom_traits().power_side_of_power_sphere_d_object();
+ Conflict_pred_in_fullspace c(*this, p, ori, side);
+ return c(s);
+ }
+}
+
+template< typename Traits, typename TDS >
+template< typename OutputIterator >
+typename Regular_triangulation<Traits, TDS>::Facet
+Regular_triangulation<Traits, TDS>
+::compute_conflict_zone(const Weighted_point & p, Full_cell_handle s, OutputIterator out) const
+{
+ CGAL_precondition( 1 <= current_dimension() );
+ if( current_dimension() < maximal_dimension() )
+ {
+ Conflict_pred_in_subspace c(
+ *this, p,
+ coaffine_orientation_predicate(),
+ power_side_of_power_sphere_for_non_maximal_dim_predicate());
+ Conflict_traversal_pred_in_subspace tp(*this, c);
+ return tds().gather_full_cells(s, tp, out);
+ }
+ else
+ {
+ Orientation_d ori = geom_traits().orientation_d_object();
+ Power_side_of_power_sphere_d side = geom_traits().power_side_of_power_sphere_d_object();
+ Conflict_pred_in_fullspace c(*this, p, ori, side);
+ Conflict_traversal_pred_in_fullspace tp(*this, c);
+ return tds().gather_full_cells(s, tp, out);
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
+
+template< typename Traits, typename TDS >
+bool
+Regular_triangulation<Traits, TDS>
+::is_valid(bool verbose, int level) const
+{
+ if (!Base::is_valid(verbose, level))
+ return false;
+
+ int dim = current_dimension();
+ if (dim == maximal_dimension())
+ {
+ for (Finite_full_cell_const_iterator cit = finite_full_cells_begin() ;
+ cit != finite_full_cells_end() ; ++cit )
+ {
+ Full_cell_const_handle ch = cit.base();
+ for(int i = 0; i < dim+1 ; ++i )
+ {
+ // If the i-th neighbor is not an infinite cell
+ Vertex_handle opposite_vh =
+ ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch));
+ if (!is_infinite(opposite_vh))
+ {
+ Power_side_of_power_sphere_d side =
+ geom_traits().power_side_of_power_sphere_d_object();
+ if (side(Point_const_iterator(ch->vertices_begin()),
+ Point_const_iterator(ch->vertices_end()),
+ opposite_vh->point()) == ON_POSITIVE_SIDE)
+ {
+ if (verbose)
+ CGAL_warning_msg(false, "Non-empty sphere");
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+} //namespace CGAL
+
+#endif //CGAL_REGULAR_TRIANGULATION_H
diff --git a/include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h b/include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h
new file mode 100644
index 00000000..78bb95a6
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h
@@ -0,0 +1,288 @@
+// Copyright (c) 2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Clement Jamin
+
+#ifndef CGAL_REGULAR_TRIANGULATION_TRAITS_ADAPTER_H
+#define CGAL_REGULAR_TRIANGULATION_TRAITS_ADAPTER_H
+
+#include <CGAL/basic.h>
+
+#include <boost/iterator/transform_iterator.hpp>
+
+namespace CGAL {
+
+// Wrapper class to make a model of `RegularTriangulationTraits` easily usable
+// by the `Regular_triangulation` class. By using this class:
+// - Point_d (used by `Triangulation` and the TDS) becomes a weighted point
+// - Predicates and functors such as Less_coordinate_d or Orientation_d
+// can be called using weighted points instead of bare points (this is
+// needed because `Weighted_point_d` is not convertible to `Point_d`)
+// This way, `Triangulation` works perfectly well with weighted points.
+
+template <class K>
+class Regular_triangulation_traits_adapter
+ : public K
+{
+public:
+ typedef K Base;
+
+ // Required by TriangulationTraits
+ typedef typename K::Dimension Dimension;
+ typedef typename K::FT FT;
+ typedef typename K::Flat_orientation_d Flat_orientation_d;
+ typedef typename K::Weighted_point_d Point_d;
+
+ // Required by RegularTriangulationTraits
+ typedef typename K::Point_d Bare_point_d;
+ typedef typename K::Weighted_point_d Weighted_point_d;
+ typedef typename K::Construct_point_d Construct_point_d;
+ typedef typename K::Compute_weight_d Compute_weight_d;
+ typedef typename K::Power_side_of_power_sphere_d Power_side_of_power_sphere_d;
+ typedef typename K::In_flat_power_side_of_power_sphere_d
+ In_flat_power_side_of_power_sphere_d;
+
+ //===========================================================================
+ // Custom types
+ //===========================================================================
+
+ // Required by SpatialSortingTraits_d
+ class Less_coordinate_d
+ {
+ const K &m_kernel;
+
+ public:
+ typedef bool result_type;
+
+ Less_coordinate_d(const K &kernel)
+ : m_kernel(kernel) {}
+
+ result_type operator()(
+ Weighted_point_d const& p, Weighted_point_d const& q, int i) const
+ {
+ Construct_point_d cp = m_kernel.construct_point_d_object();
+ return m_kernel.less_coordinate_d_object() (cp(p), cp(q), i);
+ }
+ };
+
+ //===========================================================================
+
+ // Required by TriangulationTraits
+ class Orientation_d
+ {
+ const K &m_kernel;
+
+ public:
+ typedef Orientation result_type;
+
+ Orientation_d(const K &kernel)
+ : m_kernel(kernel) {}
+
+ template <typename ForwardIterator>
+ result_type operator()(ForwardIterator start, ForwardIterator end) const
+ {
+ Construct_point_d cp = m_kernel.construct_point_d_object();
+ return m_kernel.orientation_d_object() (
+ boost::make_transform_iterator(start, cp),
+ boost::make_transform_iterator(end, cp)
+ );
+ }
+ };
+
+ //===========================================================================
+
+ // Required by TriangulationTraits
+ class Construct_flat_orientation_d
+ {
+ const K &m_kernel;
+
+ public:
+ typedef Flat_orientation_d result_type;
+
+ Construct_flat_orientation_d(const K &kernel)
+ : m_kernel(kernel) {}
+
+ template <typename ForwardIterator>
+ result_type operator()(ForwardIterator start, ForwardIterator end) const
+ {
+ Construct_point_d cp = m_kernel.construct_point_d_object();
+ return m_kernel.construct_flat_orientation_d_object() (
+ boost::make_transform_iterator(start, cp),
+ boost::make_transform_iterator(end, cp)
+ );
+ }
+ };
+
+
+ //===========================================================================
+
+ // Required by TriangulationTraits
+ class In_flat_orientation_d
+ {
+ const K &m_kernel;
+
+ public:
+ typedef Orientation result_type;
+
+ In_flat_orientation_d(const K &kernel)
+ : m_kernel(kernel) {}
+
+ template <typename ForwardIterator>
+ result_type operator()(Flat_orientation_d orient,
+ ForwardIterator start, ForwardIterator end) const
+ {
+ Construct_point_d cp = m_kernel.construct_point_d_object();
+ return m_kernel.in_flat_orientation_d_object() (
+ orient,
+ boost::make_transform_iterator(start, cp),
+ boost::make_transform_iterator(end, cp)
+ );
+ }
+ };
+
+ //===========================================================================
+
+ // Required by TriangulationTraits
+ class Contained_in_affine_hull_d
+ {
+ const K &m_kernel;
+
+ public:
+ typedef bool result_type;
+
+ Contained_in_affine_hull_d(const K &kernel)
+ : m_kernel(kernel) {}
+
+ template <typename ForwardIterator>
+ result_type operator()(ForwardIterator start, ForwardIterator end,
+ const Weighted_point_d & p) const
+ {
+ Construct_point_d cp = m_kernel.construct_point_d_object();
+ return m_kernel.contained_in_affine_hull_d_object() (
+ boost::make_transform_iterator(start, cp),
+ boost::make_transform_iterator(end, cp),
+ cp(p)
+ );
+ }
+ };
+
+ //===========================================================================
+
+ // Required by TriangulationTraits
+ class Compare_lexicographically_d
+ {
+ const K &m_kernel;
+
+ public:
+ typedef Comparison_result result_type;
+
+ Compare_lexicographically_d(const K &kernel)
+ : m_kernel(kernel) {}
+
+ result_type operator()(
+ const Weighted_point_d & p, const Weighted_point_d & q) const
+ {
+ Construct_point_d cp = m_kernel.construct_point_d_object();
+ return m_kernel.compare_lexicographically_d_object()(cp(p), cp(q));
+ }
+ };
+
+ //===========================================================================
+
+ // Only for Triangulation_off_ostream.h (undocumented)
+ class Compute_coordinate_d
+ {
+ const K &m_kernel;
+
+ public:
+ typedef FT result_type;
+
+ Compute_coordinate_d(const K &kernel)
+ : m_kernel(kernel) {}
+
+ result_type operator()(
+ const Weighted_point_d & p, const int i) const
+ {
+ Construct_point_d cp = m_kernel.construct_point_d_object();
+ return m_kernel.compute_coordinate_d_object()(cp(p), i);
+ }
+ };
+
+ //===========================================================================
+
+ // To satisfy SpatialSortingTraits_d
+ // and also for Triangulation_off_ostream.h (undocumented)
+ class Point_dimension_d
+ {
+ const K &m_kernel;
+
+ public:
+ typedef int result_type;
+
+ Point_dimension_d(const K &kernel)
+ : m_kernel(kernel) {}
+
+ result_type operator()(
+ const Weighted_point_d & p) const
+ {
+ Construct_point_d cp = m_kernel.construct_point_d_object();
+ return m_kernel.point_dimension_d_object()(cp(p));
+ }
+ };
+
+ //===========================================================================
+ // Object creation
+ //===========================================================================
+
+ Less_coordinate_d less_coordinate_d_object() const
+ {
+ return Less_coordinate_d(*this);
+ }
+ Contained_in_affine_hull_d contained_in_affine_hull_d_object() const
+ {
+ return Contained_in_affine_hull_d(*this);
+ }
+ Orientation_d orientation_d_object() const
+ {
+ return Orientation_d(*this);
+ }
+ Construct_flat_orientation_d construct_flat_orientation_d_object() const
+ {
+ return Construct_flat_orientation_d(*this);
+ }
+ In_flat_orientation_d in_flat_orientation_d_object() const
+ {
+ return In_flat_orientation_d(*this);
+ }
+ Compare_lexicographically_d compare_lexicographically_d_object() const
+ {
+ return Compare_lexicographically_d(*this);
+ }
+ Compute_coordinate_d compute_coordinate_d_object() const
+ {
+ return Compute_coordinate_d(*this);
+ }
+ Point_dimension_d point_dimension_d_object() const
+ {
+ return Point_dimension_d(*this);
+ }
+};
+
+
+} //namespace CGAL
+
+#endif // CGAL_REGULAR_TRIANGULATION_TRAITS_ADAPTER_H
diff --git a/include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h b/include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h
new file mode 100644
index 00000000..9a6030e5
--- /dev/null
+++ b/include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_TDS_FULL_CELL_DEFAULT_STORAGE_POLICY_H
+#define CGAL_TDS_FULL_CELL_DEFAULT_STORAGE_POLICY_H
+
+#include <CGAL/Dimension.h>
+#include <CGAL/Compact_container.h>
+#include <CGAL/internal/Static_or_dynamic_array.h>
+
+#include <boost/cstdint.hpp>
+
+namespace CGAL {
+
+// POLICY TAG
+
+struct TDS_full_cell_default_storage_policy {}; // stores no additional data. Uses XOR trick.
+
+template< typename V, typename S, typename D, typename StoragePolicy >
+struct TFC_data; // TFC = Triangulation Full Cell
+
+template< typename Vertex_handle, typename Full_cell_handle, typename Dimen >
+struct TFC_data< Vertex_handle, Full_cell_handle, Dimen, TDS_full_cell_default_storage_policy >
+{
+ typedef typename internal::Dimen_plus_one<Dimen>::type Dimen_plus;
+ typedef typename internal::S_or_D_array< Vertex_handle, Dimen_plus, true > Vertex_handle_array;
+ typedef typename internal::S_or_D_array< Full_cell_handle, Dimen_plus > Full_cell_handle_array;
+
+ Vertex_handle_array vertices_;
+ Full_cell_handle_array neighbors_;
+
+ TFC_data(const int dmax)
+ : vertices_(dmax+1), neighbors_(dmax+1)
+ {}
+ void* for_compact_container() const { return vertices_.for_compact_container(); }
+ void* & for_compact_container() { return vertices_.for_compact_container(); }
+ int dimension() const { return ( vertices_.size() - 1 ); }
+ void set_mirror_index(const int, const int) {}
+#ifdef BOOST_NO_INT64_T
+ typedef std::ptrdiff_t Xor_type;
+#else
+ typedef boost::int_least64_t Xor_type;
+#endif
+ Xor_type xor_of_vertices(const int cur_dim) const
+ {
+ Xor_type result(0);
+ for( int i = 0; i <= cur_dim; ++i )
+ result ^= reinterpret_cast<Xor_type>(&(*vertices_[i]));
+ return result;
+ }
+ // ASSUMES |*this| is indeed a neighbor of neighbor(i):
+ // NOT correct when the hole (in insert_in_hole) is doubly covered.
+ int mirror_index(const int i) const
+ {
+ int index = 0;
+ Full_cell_handle n = neighbors_[i];
+ Full_cell_handle o = n->neighbor(index);
+ while( &(o->combinatorics_) != this )
+ o = n->neighbor(++index);
+ return index;
+ }
+ Vertex_handle mirror_vertex(const int i, const int cur_dim) const
+ {
+ Xor_type opp_vertex = xor_of_vertices(cur_dim)
+ ^ neighbors_[i]->xor_of_vertices(cur_dim)
+ ^ reinterpret_cast<Xor_type>(&(*vertices_[i]));
+ Vertex_handle mirror;
+ typedef typename Vertex_handle::pointer pointer;
+ // mirror.set_pointer(reinterpret_cast<pointer>(opp_vertex));
+ mirror = Compact_container<typename Vertex_handle::value_type>
+ ::s_iterator_to(*(reinterpret_cast<pointer>(opp_vertex)));
+ return mirror;
+ }
+ void swap_vertices(const int d1, const int d2)
+ {
+ std::swap(vertices_[d1], vertices_[d2]);
+ std::swap(neighbors_[d1], neighbors_[d2]);
+ }
+};
+
+} //namespace CGAL
+
+#endif // CGAL_TDS_FULL_CELL_DEFAULT_STORAGE_POLICY_H
diff --git a/include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h b/include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h
new file mode 100644
index 00000000..095dfe68
--- /dev/null
+++ b/include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_TDS_FULL_CELL_MIRROR_STORAGE_POLICY_H
+#define CGAL_TDS_FULL_CELL_MIRROR_STORAGE_POLICY_H
+
+#include <CGAL/TDS_full_cell_default_storage_policy.h>
+
+namespace CGAL {
+
+// POLICY TAGS
+
+struct TDS_full_cell_mirror_storage_policy {}; // Stores the mirror index of all vertices.
+
+template< typename Vertex_handle, typename Full_cell_handle, typename Maximal_dimension >
+struct TFC_data< Vertex_handle, Full_cell_handle, Maximal_dimension, TDS_full_cell_mirror_storage_policy >
+: public TFC_data< Vertex_handle, Full_cell_handle, Maximal_dimension, TDS_full_cell_default_storage_policy >
+{
+ typedef TFC_data< Vertex_handle, Full_cell_handle, Maximal_dimension, TDS_full_cell_default_storage_policy > Base;
+ typedef typename Base::Vertex_handle_array Vertex_handle_array;
+ typedef typename Base::Full_cell_handle_array Full_cell_handle_array;
+ typedef typename internal::S_or_D_array< int, typename Base::Dimen_plus > Int_array;
+
+private:
+ Int_array mirror_vertices_;
+
+public:
+ TFC_data(const int dmax)
+ : Base(dmax), mirror_vertices_(dmax+1)
+ {}
+
+ void set_mirror_index(const int i, const int index)
+ {
+ mirror_vertices_[i] = index;
+ }
+ int mirror_index(const int i) const
+ {
+ return mirror_vertices_[i];
+ }
+ Vertex_handle mirror_vertex(const int i, const int) const
+ {
+ return Base::neighbors_[i]->vertex(mirror_index(i));
+ }
+ void swap_vertices(const int d1, const int d2)
+ {
+ Base::swap_vertices(d1, d2);
+ std::swap(mirror_vertices_[d1], mirror_vertices_[d2]);
+ Base::neighbors_[d1]->set_mirror_index(mirror_vertices_[d1], d1);
+ Base::neighbors_[d2]->set_mirror_index(mirror_vertices_[d2], d2);
+ }
+};
+
+} //namespace CGAL
+
+#endif // CGAL_TDS_FULL_CELL_MIRROR_STORAGE_POLICY_H
diff --git a/include/gudhi_patches/CGAL/Triangulation.h b/include/gudhi_patches/CGAL/Triangulation.h
new file mode 100644
index 00000000..906df92e
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Triangulation.h
@@ -0,0 +1,1424 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_TRIANGULATION_H
+#define CGAL_TRIANGULATION_H
+
+#include <CGAL/internal/Triangulation/utilities.h>
+#include <CGAL/Triangulation_data_structure.h>
+#include <CGAL/Triangulation_full_cell.h>
+#include <CGAL/Triangulation_vertex.h>
+#include <CGAL/Iterator_project.h>
+#include <CGAL/spatial_sort.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/iterator.h>
+#include <CGAL/Default.h>
+#include <CGAL/Random.h>
+
+#include <boost/iterator/filter_iterator.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+
+namespace CGAL {
+
+// Iterator which iterates over vertex_handle's, but returns a point when
+// dereferenced. If the current
+// vertex_handle vh == vh_where_point_should_be_substituted, it returns
+// "subtitute_point", otherwise, it returns vh->point()
+template<class VertexHandleConstIter>
+class Substitute_point_in_vertex_iterator
+{
+ typedef typename std::iterator_traits<VertexHandleConstIter>::value_type Vertex_handle;
+ typedef typename Vertex_handle::value_type Vertex;
+ typedef typename Vertex::Point Point;
+
+public:
+ typedef Point const& result_type; // For result_of
+
+ Substitute_point_in_vertex_iterator(
+ Vertex_handle vh_where_point_should_be_substituted,
+ Point const *subtitute_point)
+ : vh_where_point_should_be_substituted_(vh_where_point_should_be_substituted)
+ , subtitute_point_(subtitute_point)
+ {}
+
+ result_type operator()(Vertex_handle vh) const
+ {
+ if (vh == vh_where_point_should_be_substituted_)
+ return *subtitute_point_;
+ else
+ return vh->point();
+ }
+
+private:
+ Vertex_handle vh_where_point_should_be_substituted_;
+ Point const *subtitute_point_;
+
+};
+
+
+template < class TriangulationTraits, class TDS_ = Default >
+class Triangulation
+{
+ typedef typename TriangulationTraits::Dimension Maximal_dimension_;
+ typedef typename Default::Get<TDS_, Triangulation_data_structure
+ < Maximal_dimension_,
+ Triangulation_vertex<TriangulationTraits>,
+ Triangulation_full_cell<TriangulationTraits> >
+ >::type TDS;
+ typedef Triangulation<TriangulationTraits, TDS_> Self;
+
+protected:
+ typedef typename TriangulationTraits::Flat_orientation_d Flat_orientation_d;
+ typedef typename TriangulationTraits::Construct_flat_orientation_d Construct_flat_orientation_d;
+ typedef typename TriangulationTraits::In_flat_orientation_d In_flat_orientation_d;
+
+ // Wrapper
+ struct Coaffine_orientation_d
+ {
+ boost::optional<Flat_orientation_d>* fop;
+ Construct_flat_orientation_d cfo;
+ In_flat_orientation_d ifo;
+
+ Coaffine_orientation_d(
+ boost::optional<Flat_orientation_d>& x,
+ Construct_flat_orientation_d const&y,
+ In_flat_orientation_d const&z)
+ : fop(&x), cfo(y), ifo(z) {}
+
+ template<class Iter>
+ CGAL::Orientation operator()(Iter a, Iter b) const
+ {
+ if (*fop)
+ return ifo(fop->get(),a,b);
+ *fop = cfo(a,b);
+ CGAL_assertion(ifo(fop->get(),a,b) == CGAL::POSITIVE);
+ return CGAL::POSITIVE;
+ }
+ };
+
+ void reset_flat_orientation()
+ {
+ if (current_dimension() == preset_flat_orientation_.first)
+ {
+ CGAL_assertion(preset_flat_orientation_.second != NULL);
+ flat_orientation_ = *preset_flat_orientation_.second;
+ }
+ else
+ flat_orientation_ = boost::none;
+ }
+
+ typedef typename TriangulationTraits::Orientation_d
+ Orientation_d;
+
+public:
+
+ typedef TriangulationTraits Geom_traits;
+ typedef TDS Triangulation_ds;
+
+ typedef typename TDS::Vertex Vertex;
+ typedef typename TDS::Full_cell Full_cell;
+ typedef typename TDS::Facet Facet;
+ typedef typename TDS::Face Face;
+
+ typedef Maximal_dimension_ Maximal_dimension;
+ typedef typename Geom_traits::Point_d Point;
+
+ typedef typename TDS::Vertex_handle Vertex_handle;
+ typedef typename TDS::Vertex_iterator Vertex_iterator;
+ typedef typename TDS::Vertex_const_handle Vertex_const_handle;
+ typedef typename TDS::Vertex_const_iterator Vertex_const_iterator;
+
+ typedef typename TDS::Full_cell_handle Full_cell_handle;
+ typedef typename TDS::Full_cell_iterator Full_cell_iterator;
+ typedef typename TDS::Full_cell_const_handle Full_cell_const_handle;
+ typedef typename TDS::Full_cell_const_iterator Full_cell_const_iterator;
+
+ typedef typename TDS::Facet_iterator Facet_iterator;
+
+ typedef typename TDS::size_type size_type;
+ typedef typename TDS::difference_type difference_type;
+
+ /// The type of location a new point is found lying on
+ enum Locate_type
+ {
+ ON_VERTEX = 0 // simplex of dimension 0
+ , IN_FACE = 1 // simplex of dimension in [ 1, |current_dimension()| - 2 ]
+ , IN_FACET = 2 // simplex of dimension |current_dimension()| - 1
+ , IN_FULL_CELL = 3 /// simplex of dimension |current_dimension()|
+ , OUTSIDE_CONVEX_HULL = 4
+ , OUTSIDE_AFFINE_HULL = 5
+ };
+
+ // Finite elements iterators
+
+ class Finiteness_predicate;
+
+ typedef boost::filter_iterator<Finiteness_predicate, Vertex_iterator>
+ Finite_vertex_iterator;
+ typedef boost::filter_iterator<Finiteness_predicate, Vertex_const_iterator>
+ Finite_vertex_const_iterator;
+ typedef boost::filter_iterator<Finiteness_predicate, Full_cell_iterator>
+ Finite_full_cell_iterator;
+ typedef boost::filter_iterator<Finiteness_predicate, Full_cell_const_iterator>
+ Finite_full_cell_const_iterator;
+ typedef boost::filter_iterator<Finiteness_predicate, Facet_iterator>
+ Finite_facet_iterator;
+
+protected: // DATA MEMBERS
+
+ Triangulation_ds tds_;
+ const Geom_traits kernel_;
+ Vertex_handle infinity_;
+ mutable std::vector<Oriented_side> orientations_;
+ mutable boost::optional<Flat_orientation_d> flat_orientation_;
+ // The user can specify a Flat_orientation_d object to be used for
+ // orienting simplices of a specific dimension
+ // (= preset_flat_orientation_.first)
+ // preset_flat_orientation_.first = numeric_limits<int>::max() otherwise)
+ std::pair<int, const Flat_orientation_d *> preset_flat_orientation_;
+ // for stochastic walk in the locate() function:
+ mutable Random rng_;
+#ifdef CGAL_TRIANGULATION_STATISTICS
+ mutable unsigned long walk_size_;
+#endif
+
+protected: // HELPER FUNCTIONS
+
+ typedef CGAL::Iterator_project<
+ typename Full_cell::Vertex_handle_const_iterator,
+ internal::Triangulation::Point_from_vertex_handle<Vertex_handle, Point>
+ > Point_const_iterator;
+
+ Point_const_iterator points_begin(Full_cell_const_handle c) const
+ { return Point_const_iterator(c->vertices_begin()); }
+ Point_const_iterator points_end(Full_cell_const_handle c) const
+ { return Point_const_iterator(c->vertices_end()); }
+ Point_const_iterator points_begin(Full_cell_handle c) const
+ { return Point_const_iterator(c->vertices_begin()); }
+ Point_const_iterator points_end(Full_cell_handle c) const
+ { return Point_const_iterator(c->vertices_end()); }
+
+public:
+
+ // FACETS OPERATIONS
+
+ Full_cell_handle full_cell(const Facet & f) const
+ {
+ return tds().full_cell(f);
+ }
+
+ int index_of_covertex(const Facet & f) const
+ {
+ return tds().index_of_covertex(f);
+ }
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UTILITIES
+
+ // A co-dimension 2 sub-simplex. called a Rotor because we can rotate
+ // the two "covertices" around the sub-simplex. Useful for traversing the
+ // boundary of a hole. NOT DOCUMENTED
+ typedef cpp11::tuple<Full_cell_handle, int, int> Rotor;
+
+ // Commented out because it was causing "internal compiler error" in MSVC
+ /*Full_cell_handle full_cell(const Rotor & r) const // NOT DOCUMENTED
+ {
+ return cpp11::get<0>(r);
+ }
+ int index_of_covertex(const Rotor & r) const // NOT DOCUMENTED
+ {
+ return cpp11::get<1>(r);
+ }
+ int index_of_second_covertex(const Rotor & r) const // NOT DOCUMENTED
+ {
+ return cpp11::get<2>(r);
+ }*/
+ Rotor rotate_rotor(Rotor & r) // NOT DOCUMENTED...
+ {
+ int opposite = cpp11::get<0>(r)->mirror_index(cpp11::get<1>(r));
+ Full_cell_handle s = cpp11::get<0>(r)->neighbor(cpp11::get<1>(r));
+ int new_second = s->index(cpp11::get<0>(r)->vertex(cpp11::get<2>(r)));
+ return Rotor(s, new_second, opposite);
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS
+
+ Triangulation(int dim, const Geom_traits &k = Geom_traits())
+ : tds_(dim)
+ , kernel_(k)
+ , infinity_()
+ , preset_flat_orientation_((std::numeric_limits<int>::max)(),
+ (Flat_orientation_d*) NULL)
+ , rng_((long)0)
+#ifdef CGAL_TRIANGULATION_STATISTICS
+ ,walk_size_(0)
+#endif
+ {
+ clear();
+ }
+
+ // With this constructor,
+ // the user can specify a Flat_orientation_d object to be used for
+ // orienting simplices of a specific dimension
+ // (= preset_flat_orientation_.first)
+ // It it used for by dark triangulations created by DT::remove
+ Triangulation(
+ int dim,
+ const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation,
+ const Geom_traits k = Geom_traits())
+ : tds_(dim)
+ , kernel_(k)
+ , infinity_()
+ , preset_flat_orientation_(preset_flat_orientation)
+ , rng_((long)0)
+#ifdef CGAL_TRIANGULATION_STATISTICS
+ ,walk_size_(0)
+#endif
+ {
+ clear();
+ }
+
+ Triangulation(const Triangulation & t2)
+ : tds_(t2.tds_)
+ , kernel_(t2.kernel_)
+ , infinity_()
+ , preset_flat_orientation_((std::numeric_limits<int>::max)(),
+ (Flat_orientation_d*) NULL)
+ , rng_(t2.rng_)
+#ifdef CGAL_TRIANGULATION_STATISTICS
+ ,walk_size_(t2.walk_size_)
+#endif
+ {
+ // We find the vertex at infinity by scanning the vertices of both
+ // triangulations. This works because Compact_container garantees that
+ // the vertices in the copy (*this) are stored in the same order as in
+ // the original triangulation (t2)
+ infinity_ = vertices_begin();
+ Vertex_const_iterator inf2 = t2.vertices_begin();
+ while( inf2 != t2.infinite_vertex() )
+ {
+ ++infinity_;
+ ++inf2;
+ }
+ // A full_cell has at most 1 + maximal_dimension() facets:
+ orientations_.resize(1 + maximal_dimension());
+ // Our coaffine orientation predicates HAS state member variables
+ reset_flat_orientation();
+ }
+
+ ~Triangulation() {}
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS FUNCTIONS
+
+ /* These three function are no longer needed since we do not use them anymore
+ in the Delaunay_triangulation::remove. *But*, they may reappear in the future
+ if we manage to passe the information that flags/TDS_data is available or not
+ for marking simplices in Delaunay_triangulation::remove. This would be useful
+ to make it a little faster, instead of binary searching if a simplex is marked
+ or not...
+ // NOT DOCUMENTED --
+ bool get_visited(Full_cell_handle s) const
+ {
+ return tds().get_visited(s);
+ }
+ // NOT DOCUMENTED --
+ bool get_visited(Full_cell_const_handle s) const
+ {
+ return tds().get_visited(s);
+ }
+
+ // NOT DOCUMENTED --
+ void set_visited(Full_cell_handle s, bool b) const
+ {
+ tds().set_visited(s, b);
+ } */
+
+ Coaffine_orientation_d coaffine_orientation_predicate() const
+ {
+ return Coaffine_orientation_d (
+ flat_orientation_,
+ geom_traits().construct_flat_orientation_d_object(),
+ geom_traits().in_flat_orientation_d_object()
+ );
+ }
+
+ const Triangulation_ds & tds() const
+ {
+ return tds_;
+ }
+
+ Triangulation_ds & tds()
+ {
+ return tds_;
+ }
+
+ const Geom_traits & geom_traits() const
+ {
+ return kernel_;
+ }
+
+ int maximal_dimension() const { return tds().maximal_dimension(); }
+ int current_dimension() const { return tds().current_dimension(); }
+
+ bool empty() const
+ {
+ return current_dimension() == -1;
+ }
+
+ size_type number_of_vertices() const
+ {
+ return tds().number_of_vertices() - 1;
+ }
+
+ size_type number_of_full_cells() const
+ {
+ return tds().number_of_full_cells();
+ }
+
+ Vertex_handle infinite_vertex() const
+ {
+ return infinity_;
+ }
+
+ Full_cell_handle infinite_full_cell() const
+ {
+ CGAL_assertion(infinite_vertex()->full_cell()->has_vertex(infinite_vertex()));
+ return infinite_vertex()->full_cell();
+ }
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - NON CONSTANT-TIME ACCESS FUNCTIONS
+
+ size_type number_of_finite_full_cells() const
+ {
+ Full_cell_const_iterator s = full_cells_begin();
+ size_type result = number_of_full_cells();
+ for( ; s != full_cells_end(); ++s )
+ {
+ if( is_infinite(s) )
+ --result;
+ }
+ return result;
+ }
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TRAVERSAL
+
+ Vertex_iterator vertices_begin() { return tds().vertices_begin(); }
+ Vertex_iterator vertices_end() { return tds().vertices_end(); }
+
+ Vertex_const_iterator vertices_begin() const { return tds().vertices_begin(); }
+ Vertex_const_iterator vertices_end() const { return tds().vertices_end(); }
+
+ Finite_vertex_iterator finite_vertices_begin()
+ { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); }
+ Finite_vertex_iterator finite_vertices_end()
+ { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); }
+ Finite_vertex_const_iterator finite_vertices_begin() const
+ { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); }
+ Finite_vertex_const_iterator finite_vertices_end() const
+ { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); }
+
+ Full_cell_iterator full_cells_begin() { return tds().full_cells_begin(); }
+ Full_cell_iterator full_cells_end() { return tds().full_cells_end(); }
+
+ Full_cell_const_iterator full_cells_begin() const { return tds().full_cells_begin(); }
+ Full_cell_const_iterator full_cells_end() const { return tds().full_cells_end(); }
+
+ Finite_full_cell_iterator finite_full_cells_begin()
+ { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); }
+ Finite_full_cell_iterator finite_full_cells_end()
+ { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); }
+ Finite_full_cell_const_iterator finite_full_cells_begin() const
+ { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); }
+ Finite_full_cell_const_iterator finite_full_cells_end() const
+ { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); }
+
+ Facet_iterator facets_begin() { return tds().facets_begin(); }
+ Facet_iterator facets_end() { return tds().facets_end(); }
+ Facet_iterator finite_facets_begin()
+ { return Finite_facet_iterator(Finiteness_predicate(*this), facets_begin(), facets_end()); }
+ Facet_iterator finite_facets_end()
+ { return Finite_facet_iterator(Finiteness_predicate(*this), facets_end(), facets_end()); }
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SOME PREDICATE FUNCTORS
+
+ class Finiteness_predicate
+ {
+ const Self & t_;
+ public:
+ Finiteness_predicate(const Self & t) : t_(t) {}
+ template < class T >
+ bool operator()(const T & t) const
+ {
+ return ! t_.is_infinite(t);
+ }
+ };
+
+ class Point_equality_predicate
+ {
+ const Point & o_;
+ public:
+ Point_equality_predicate(const Point & o) : o_(o) {}
+ bool operator()(const Point & o) const { return (o == o_ );}
+ };
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SIMPLE QUERIES
+/*
+ bool is_vertex(const Point & p, Vertex_handle & v, Full_cell_handle hint = Full_cell_handle()) const
+ {
+ Locate_type lt;
+ Face f(maximal_dimension());
+ Facet ft;
+ Full_cell_handle s = locate(p, lt, f, ft, hint);
+ if( ON_VERTEX == lt )
+ {
+ v = s->vertex(f.index(0));
+ return true;
+ }
+ return false;
+ }
+
+ bool is_vertex(Vertex_const_handle v) const
+ {
+ return tds().is_vertex(v);
+ }
+
+ bool is_full_cell(Full_cell_const_handle s) const
+ {
+ return tds().is_full_cell(s);
+ }
+*/
+
+ bool is_infinite(Vertex_const_handle v) const
+ {
+ CGAL_precondition(Vertex_const_handle() != v);
+ return (infinite_vertex() == v);
+ }
+
+ bool is_infinite(const Vertex & v) const /* internal use, not documented */
+ {
+ return (&(*infinite_vertex()) == &v);
+ }
+
+ bool is_infinite(Full_cell_const_handle s) const
+ {
+ CGAL_precondition(Full_cell_const_handle() != s);
+ return is_infinite(*s);
+ }
+ bool is_infinite(const Full_cell & s) const /* internal use, not documented */
+ {
+ for(int i = 0; i <= current_dimension(); ++i)
+ if( is_infinite(s.vertex(i)) )
+ return true;
+ return false;
+ }
+ bool is_infinite(const Facet & ft) const
+ {
+ Full_cell_const_handle s = full_cell(ft);
+ CGAL_precondition(s != Full_cell_const_handle());
+ if( is_infinite(s) )
+ return (s->vertex(index_of_covertex(ft)) != infinite_vertex());
+ return false;
+ }
+
+ bool is_infinite(const Face & f) const
+ {
+ Full_cell_const_handle s = f.full_cell();
+ CGAL_precondition(s != Full_cell_const_handle());
+ if( is_infinite(s) )
+ {
+ Vertex_handle v;
+ for( int i(0); i<= f.face_dimension(); ++i)
+ if ( is_infinite( f.vertex(i) )) return true;
+ }
+ return false;
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ELEMENT GATHERING
+
+
+ template< typename OutputIterator >
+ OutputIterator incident_full_cells(const Face & f, OutputIterator out) const
+ {
+ return tds().incident_full_cells(f, out);
+ }
+ template< typename OutputIterator >
+ OutputIterator incident_full_cells(Vertex_const_handle v, OutputIterator out) const
+ {
+ return tds().incident_full_cells(v, out);
+ }
+ template< typename OutputIterator >
+ OutputIterator star(const Face & f, OutputIterator out) const
+ {
+ return tds().star(f, out);
+ }
+
+ template< typename OutputIterator >
+ OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) const
+ {
+ return tds().incident_faces(v, d, out);
+ }
+ /*
+ template< typename OutputIterator, class Comparator >
+ OutputIterator incident_upper_faces( Vertex_const_handle v, int d,
+ OutputIterator out, Comparator cmp = Comparator())
+ {
+ return tds().incident_upper_faces(v, d, out, cmp);
+ }
+ template< typename OutputIterator >
+ OutputIterator incident_upper_faces( Vertex_const_handle v, int d,
+ OutputIterator out)
+ { // FIXME: uncomment this function, since it uses a comparator specific to
+ // *geometric* triangulation (taking infinite vertex into account)
+ internal::Triangulation::Compare_vertices_for_upper_face<Self> cmp(*this);
+ return tds().incident_upper_faces(v, d, out, cmp);
+ }
+ */
+ Orientation orientation(Full_cell_const_handle s, bool in_is_valid = false) const
+ {
+ if( ! in_is_valid )
+ CGAL_assertion( ! is_infinite(s) );
+ if( 0 == current_dimension() )
+ return POSITIVE;
+ if( current_dimension() == maximal_dimension() )
+ {
+ Orientation_d ori = geom_traits().orientation_d_object();
+ return ori(points_begin(s), points_begin(s) + 1 + current_dimension());
+ }
+ else
+ {
+ return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension());
+ }
+ }
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UPDATE OPERATIONS
+
+ void clear()
+ {
+ tds_.clear();
+ infinity_ = tds().insert_increase_dimension();
+ // A full_cell has at most 1 + maximal_dimension() facets:
+ orientations_.resize(1 + maximal_dimension());
+ // Our coaffine orientation predicates HAS state member variables
+ reset_flat_orientation();
+#ifdef CGAL_TRIANGULATION_STATISTICS
+ walk_size_ = 0;
+#endif
+ }
+
+ void set_current_dimension(int d)
+ {
+ tds().set_current_dimension(d);
+ }
+
+ Full_cell_handle new_full_cell()
+ {
+ return tds().new_full_cell();
+ }
+
+ Vertex_handle new_vertex()
+ {
+ return tds().new_vertex();
+ }
+
+ Vertex_handle new_vertex(const Point & p)
+ {
+ return tds().new_vertex(p);
+ }
+
+ void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j)
+ {
+ tds().set_neighbors(s, i, s1, j);
+ }
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
+
+ bool is_valid(bool = false, int = 0) const;
+ bool are_incident_full_cells_valid(Vertex_const_handle, bool = false, int = 0) const;
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - POINT LOCATION
+
+protected:
+ template< typename OrientationPredicate >
+ Full_cell_handle do_locate(const Point &, Locate_type &, Face &, Facet &,
+ Full_cell_handle start,
+ const OrientationPredicate & o) const;
+public:
+ Full_cell_handle locate(const Point &, Locate_type &, Face &, Facet &,
+ Full_cell_handle start = Full_cell_handle()) const;
+ Full_cell_handle locate(const Point &, Locate_type &, Face &, Facet &,
+ Vertex_handle) const;
+ Full_cell_handle locate(const Point & p, Full_cell_handle s = Full_cell_handle()) const;
+ Full_cell_handle locate(const Point & p, Vertex_handle v) const;
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
+
+ Vertex_handle contract_face(const Point &, const Face &);
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - POINT INSERTION
+
+ template< typename ForwardIterator >
+ size_type insert(ForwardIterator start, ForwardIterator end)
+ {
+ size_type n = number_of_vertices();
+ std::vector<Point> points(start, end);
+ spatial_sort(points.begin(), points.end(), geom_traits());
+ Full_cell_handle hint = Full_cell_handle();
+ typename std::vector<Point>::const_iterator s = points.begin();
+ while( s != points.end() )
+ {
+ hint = insert(*s++, hint)->full_cell();
+ }
+ return number_of_vertices() - n;
+ }
+ Vertex_handle insert(const Point &, Locate_type, const Face &, const Facet &, Full_cell_handle);
+ Vertex_handle insert(const Point &, Full_cell_handle start = Full_cell_handle());
+ Vertex_handle insert(const Point &, Vertex_handle);
+ template< typename ForwardIterator >
+ Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft)
+ {
+ Emptyset_iterator out;
+ return insert_in_hole(p, start, end, ft, out);
+ }
+ template< typename ForwardIterator, typename OutputIterator >
+ Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft,
+ OutputIterator out)
+ {
+ Vertex_handle v = tds().insert_in_hole(start, end, ft, out);
+ v->set_point(p);
+ return v;
+ }
+ Vertex_handle insert_in_face(const Point &, const Face &);
+ Vertex_handle insert_in_facet(const Point &, const Facet &);
+ Vertex_handle insert_in_full_cell(const Point &, Full_cell_handle);
+ Vertex_handle insert_outside_convex_hull_1(const Point &, Full_cell_handle);
+ Vertex_handle insert_outside_convex_hull(const Point &, Full_cell_handle);
+ Vertex_handle insert_outside_affine_hull(const Point &);
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - FACET-TRAVERSAL PREDICATES
+
+ template< typename OrientationPredicate >
+ class Outside_convex_hull_traversal_predicate
+ {
+ Triangulation & t_;
+ const Point & p_;
+ OrientationPredicate const& ori_;
+ int cur_dim_;
+ public:
+ Outside_convex_hull_traversal_predicate(Triangulation & t, const Point & p,
+ OrientationPredicate const& ori)
+ : t_(t), p_(p), ori_(ori), cur_dim_(t.current_dimension()) {}
+ // FUTURE change parameter to const reference
+ bool operator()(Facet f) const
+ {
+ Full_cell_handle s = t_.full_cell(f);
+ const int i = t_.index_of_covertex(f);
+ Full_cell_handle n = s->neighbor(i);
+ if( ! t_.is_infinite(n) )
+ return false;
+ int inf_v_index = n->index(t_.infinite_vertex());
+ n->vertex(inf_v_index)->set_point(p_);
+ bool ok = (POSITIVE == ori_(t_.points_begin(n), t_.points_begin(n) + cur_dim_ + 1));
+ return ok;
+ }
+ };
+
+ // make sure all full_cells have positive orientation
+ void reorient_full_cells();
+
+protected:
+ // This is used in the |remove(v)| member function to manage sets of Full_cell_handles
+ template< typename FCH >
+ struct Full_cell_set : public std::vector<FCH>
+ {
+ typedef std::vector<FCH> Base_set;
+ using Base_set::begin;
+ using Base_set::end;
+ void make_searchable()
+ { // sort the full cell handles
+ std::sort(begin(), end());
+ }
+ bool contains(const FCH & fch) const
+ {
+ return std::binary_search(begin(), end(), fch);
+ }
+ bool contains_1st_and_not_2nd(const FCH & fst, const FCH & snd) const
+ {
+ return ( ! contains(snd) ) && ( contains(fst) );
+ }
+ };
+
+ void display_all_full_cells__debugging() const
+ {
+ std::cerr << "ALL FULL CELLS:" << std::endl;
+ for (Full_cell_const_iterator cit = full_cells_begin() ;
+ cit != full_cells_end() ; ++cit )
+ {
+ std::cerr << std::hex << &*cit << ": ";
+ for (int jj = 0 ; jj <= current_dimension() ; ++jj)
+ std::cerr << (is_infinite(cit->vertex(jj)) ? 0xFFFFFFFF : (unsigned int)&*cit->vertex(jj)) << " - ";
+ std::cerr << std::dec << std::endl;
+ }
+ std::cerr << std::endl;
+ }
+
+
+}; // Triangulation<...>
+
+// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+
+// CLASS MEMBER FUNCTIONS
+
+template < class TT, class TDS >
+void
+Triangulation<TT, TDS>
+::reorient_full_cells()
+{
+ if( current_dimension() < 1 )
+ return;
+
+ Full_cell_iterator sit = full_cells_begin();
+ Full_cell_iterator send = full_cells_end();
+ for ( ; sit != send ; ++sit)
+ {
+ if( ! (is_infinite(sit) && (1 == current_dimension())) )
+ {
+ sit->swap_vertices(current_dimension() - 1, current_dimension());
+ }
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// - - - - - - - - - - - - - - - - - - - - - - - - THE REMOVAL METHODS
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::contract_face(const Point & p, const Face & f)
+{
+ CGAL_precondition( ! is_infinite(f) );
+ Vertex_handle v = tds().contract_face(f);
+ v->set_point(p);
+ CGAL_expensive_postcondition_msg(are_incident_full_cells_valid(v), "new point is not where it should be");
+ return v;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// - - - - - - - - - - - - - - - - - - - - - - - - THE INSERTION METHODS
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::insert(const Point & p, Locate_type lt, const Face & f, const Facet & ft, Full_cell_handle s)
+{
+ switch( lt )
+ {
+ case IN_FULL_CELL:
+ return insert_in_full_cell(p, s);
+ break;
+ case OUTSIDE_CONVEX_HULL:
+ return insert_outside_convex_hull(p, s);
+ break;
+ case OUTSIDE_AFFINE_HULL:
+ return insert_outside_affine_hull(p);
+ break;
+ case IN_FACET:
+ {
+ return insert_in_facet(p, ft);
+ break;
+ }
+ case IN_FACE:
+ return insert_in_face(p, f);
+ break;
+ case ON_VERTEX:
+ s->vertex(f.index(0))->set_point(p);
+ return s->vertex(f.index(0));
+ break;
+ }
+ CGAL_assertion(false);
+ return Vertex_handle();
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::insert(const Point & p, Full_cell_handle start)
+{
+ Locate_type lt;
+ Face f(maximal_dimension());
+ Facet ft;
+ Full_cell_handle s = locate(p, lt, f, ft, start);
+ return insert(p, lt, f, ft, s);
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::insert(const Point & p, Vertex_handle v)
+{
+ if( Vertex_handle() == v )
+ v = infinite_vertex();
+ return insert(p, v->full_cell());
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::insert_in_face(const Point & p, const Face & f)
+{
+ CGAL_precondition( ! is_infinite(f) );
+ Vertex_handle v = tds().insert_in_face(f);
+ v->set_point(p);
+ return v;
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::insert_in_facet(const Point & p, const Facet & ft)
+{
+ CGAL_precondition( ! is_infinite(ft) );
+ Vertex_handle v = tds().insert_in_facet(ft);
+ v->set_point(p);
+ return v;
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::insert_in_full_cell(const Point & p, Full_cell_handle s)
+{
+ CGAL_precondition( ! is_infinite(s) );
+ Vertex_handle v = tds().insert_in_full_cell(s);
+ v->set_point(p);
+ return v;
+}
+
+// NOT DOCUMENTED...
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::insert_outside_convex_hull_1(const Point & p, Full_cell_handle s)
+{
+ // This is a special case for dimension 1, because in that case, the right
+ // infinite full_cell is not correctly oriented... (sice its first vertex is the
+ // infinite one...
+ CGAL_precondition( is_infinite(s) );
+ CGAL_precondition( 1 == current_dimension() );
+ Vertex_handle v = tds().insert_in_full_cell(s);
+ v->set_point(p);
+ return v;
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::insert_outside_convex_hull(const Point & p, Full_cell_handle s)
+{
+ if( 1 == current_dimension() )
+ {
+ return insert_outside_convex_hull_1(p, s);
+ }
+ CGAL_precondition( is_infinite(s) );
+ CGAL_assertion( current_dimension() >= 2 );
+ std::vector<Full_cell_handle> simps;
+ simps.reserve(64);
+ std::back_insert_iterator<std::vector<Full_cell_handle> > out(simps);
+ if( current_dimension() < maximal_dimension() )
+ {
+ Coaffine_orientation_d ori = coaffine_orientation_predicate();
+ Outside_convex_hull_traversal_predicate<Coaffine_orientation_d>
+ ochtp(*this, p, ori);
+ tds().gather_full_cells(s, ochtp, out);
+ }
+ else
+ {
+ Orientation_d ori = geom_traits().orientation_d_object();
+ Outside_convex_hull_traversal_predicate<Orientation_d>
+ ochtp(*this, p, ori);
+ tds().gather_full_cells(s, ochtp, out);
+ }
+ int inf_v_index = s->index(infinite_vertex());
+ Vertex_handle v = insert_in_hole(
+ p, simps.begin(), simps.end(), Facet(s, inf_v_index));
+ return v;
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Vertex_handle
+Triangulation<TT, TDS>
+::insert_outside_affine_hull(const Point & p)
+{
+ CGAL_precondition( current_dimension() < maximal_dimension() );
+ Vertex_handle v = tds().insert_increase_dimension(infinite_vertex());
+ // reset the orientation predicate:
+ reset_flat_orientation();
+ v->set_point(p);
+ if( current_dimension() >= 1 )
+ {
+ Full_cell_handle inf_v_cell = infinite_vertex()->full_cell();
+ int inf_v_index = inf_v_cell->index(infinite_vertex());
+ Full_cell_handle s = inf_v_cell->neighbor(inf_v_index);
+ Orientation o = orientation(s);
+ CGAL_assertion( COPLANAR != o );
+ if( NEGATIVE == o )
+ reorient_full_cells();
+
+
+ // We just inserted the second finite point and the right infinite
+ // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be
+ // consistent with the rest of the cells
+ if (current_dimension() == 1)
+ {
+ // Is "inf_v_cell" the right infinite cell?
+ // Then inf_v_index should be 1
+ if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0
+ && inf_v_index == 0)
+ {
+ inf_v_cell->swap_vertices(
+ current_dimension() - 1, current_dimension());
+ }
+ // Otherwise, let's find the right infinite cell
+ else
+ {
+ inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2);
+ inf_v_index = inf_v_cell->index(infinite_vertex());
+ // Is "inf_v_cell" the right infinite cell?
+ // Then inf_v_index should be 1
+ if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0
+ && inf_v_index == 0)
+ {
+ inf_v_cell->swap_vertices(
+ current_dimension() - 1, current_dimension());
+ }
+ }
+ }
+ }
+ return v;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// - - - - - - - - - - - - - - - - - - - - THE MAIN LOCATE(...) FUNCTION
+
+template < class TT, class TDS >
+template< typename OrientationPredicate >
+typename Triangulation<TT, TDS>::Full_cell_handle
+Triangulation<TT, TDS>
+::do_locate(const Point & p, // query point
+ Locate_type & loc_type,// type of result (full_cell, face, vertex)
+ Face & face,// the face containing the query in its interior (when appropriate)
+ Facet & facet,// the facet containing the query in its interior (when appropriate)
+ Full_cell_handle start, // starting full_cell for the walk
+ OrientationPredicate const& orientation_pred
+ ) const
+{
+ const int cur_dim = current_dimension();
+
+ if( cur_dim == -1 )
+ {
+ loc_type = OUTSIDE_AFFINE_HULL;
+ return Full_cell_handle();
+ }
+ else if( cur_dim == 0 )
+ {
+ Vertex_handle vit = infinite_full_cell()->neighbor(0)->vertex(0);
+ if( EQUAL != geom_traits().compare_lexicographically_d_object()(p, vit->point()) )
+ {
+ loc_type = OUTSIDE_AFFINE_HULL;
+ return Full_cell_handle();
+ }
+ else
+ {
+ loc_type = ON_VERTEX;
+ face.set_full_cell(vit->full_cell());
+ face.set_index(0, 0);
+ return vit->full_cell();
+ }
+ }
+
+ Full_cell_handle s;
+
+ // if we don't know where to start, we start from any bounded full_cell
+ if( Full_cell_handle() == start )
+ {
+ // THE HACK THAT NOBODY SHOULD DO... BUT DIFFICULT TO WORK AROUND
+ // THIS... TODO: WORK AROUND IT
+ Full_cell_handle inf_c = const_cast<Self*>(this)->infinite_full_cell();
+ int inf_v_index = inf_c->index(infinite_vertex());
+ s = inf_c->neighbor(inf_v_index);
+ }
+ else
+ {
+ s = start;
+ if( is_infinite(s) )
+ {
+ int inf_v_index = s->index(infinite_vertex());
+ s = s->neighbor(inf_v_index);
+ }
+ }
+
+ // Check if query |p| is outside the affine hull
+ if( cur_dim < maximal_dimension() )
+ {
+ if( ! geom_traits().contained_in_affine_hull_d_object()(
+ points_begin(s),
+ points_begin(s) + current_dimension() + 1,
+ p) )
+ {
+ loc_type = OUTSIDE_AFFINE_HULL;
+ return Full_cell_handle();
+ }
+ }
+
+ // we remember the |previous|ly visited full_cell to avoid the evaluation
+ // of one |orientation| predicate
+ Full_cell_handle previous = Full_cell_handle();
+ bool full_cell_not_found = true;
+ while(full_cell_not_found) // we walk until we locate the query point |p|
+ {
+ #ifdef CGAL_TRIANGULATION_STATISTICS
+ ++walk_size_;
+ #endif
+ // For the remembering stochastic walk, we need to start trying
+ // with a random index:
+ int j, i = rng_.get_int(0, cur_dim);
+ // we check |p| against all the full_cell's hyperplanes in turn
+
+ for(j = 0; j <= cur_dim; ++j, i = (i + 1) % (cur_dim + 1) )
+ {
+ Full_cell_handle next = s->neighbor(i);
+ if( previous == next )
+ { // no need to compute the orientation, we already know it
+ orientations_[i] = POSITIVE;
+ continue; // go to next full_cell's facet
+ }
+
+ Substitute_point_in_vertex_iterator<
+ typename Full_cell::Vertex_handle_const_iterator>
+ spivi(s->vertex(i), &p);
+
+ orientations_[i] = orientation_pred(
+ boost::make_transform_iterator(s->vertices_begin(), spivi),
+ boost::make_transform_iterator(s->vertices_begin() + cur_dim + 1,
+ spivi));
+
+ if( orientations_[i] != NEGATIVE )
+ {
+ // from this facet's point of view, we are inside the
+ // full_cell or on its boundary, so we continue to next facet
+ continue;
+ }
+
+ // At this point, we know that we have to jump to the |next|
+ // full_cell because orientation_[i] == NEGATIVE
+ previous = s;
+ s = next;
+ if( is_infinite(next) )
+ { // we have arrived OUTSIDE the convex hull of the triangulation,
+ // so we stop the search
+ full_cell_not_found = false;
+ loc_type = OUTSIDE_CONVEX_HULL;
+ face.set_full_cell(s);
+ }
+ break;
+ } // end of the 'for' loop
+ if( ( cur_dim + 1 ) == j ) // we found the full_cell containing |p|
+ full_cell_not_found = false;
+ }
+ // Here, we know in which full_cell |p| is in.
+ // We now check more precisely where |p| landed:
+ // vertex, facet, face or full_cell.
+ if( ! is_infinite(s) )
+ {
+ face.set_full_cell(s);
+ int num(0);
+ int verts(0);
+ for(int i = 0; i < cur_dim; ++i)
+ {
+ if( orientations_[i] == COPLANAR )
+ {
+ ++num;
+ facet = Facet(s, i);
+ }
+ else
+ face.set_index(verts++, i);
+ }
+ //-- We could put the if{}else{} below in the loop above, but then we would
+ // need to test if (verts < cur_dim) many times... we do it only once
+ // here:
+ if( orientations_[cur_dim] == COPLANAR )
+ {
+ ++num;
+ facet = Facet(s, cur_dim);
+ }
+ else if( verts < cur_dim )
+ face.set_index(verts, cur_dim);
+ //-- end of remark above //
+ if( 0 == num )
+ {
+ loc_type = IN_FULL_CELL;
+ face.clear();
+ }
+ else if( cur_dim == num )
+ loc_type = ON_VERTEX;
+ else if( 1 == num )
+ loc_type = IN_FACET;
+ else
+ loc_type = IN_FACE;
+ }
+ return s;
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Full_cell_handle
+Triangulation<TT, TDS>
+::locate( const Point & p, // query point
+ Locate_type & loc_type,// type of result (full_cell, face, vertex)
+ Face & face,// the face containing the query in its interior (when appropriate)
+ Facet & facet,// the facet containing the query in its interior (when appropriate)
+ Full_cell_handle start// starting full_cell for the walk
+ ) const
+{
+ if( current_dimension() == maximal_dimension() )
+ {
+ Orientation_d ori = geom_traits().orientation_d_object();
+ return do_locate(p, loc_type, face, facet, start, ori);
+ }
+ else
+ return do_locate(p, loc_type, face, facet, start, coaffine_orientation_predicate());
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// - - - - - - - - - - - - - - - - - - - - the locate(...) variants
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Full_cell_handle
+Triangulation<TT, TDS>
+::locate( const Point & p,
+ Locate_type & loc_type,
+ Face & face,
+ Facet & facet,
+ Vertex_handle start) const
+{
+ if( Vertex_handle() == start )
+ start = infinite_vertex();
+ return locate(p, loc_type, face, facet, start->full_cell());
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Full_cell_handle
+Triangulation<TT, TDS>
+::locate(const Point & p, Full_cell_handle s) const
+{
+ Locate_type lt;
+ Face face(maximal_dimension());
+ Facet facet;
+ return locate(p, lt, face, facet, s);
+}
+
+template < class TT, class TDS >
+typename Triangulation<TT, TDS>::Full_cell_handle
+Triangulation<TT, TDS>
+::locate(const Point & p, Vertex_handle v) const
+{
+ if( Vertex_handle() != v )
+ v = infinite_vertex();
+ return this->locate(p, v->full_cell());
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
+
+template < class TT, class TDS >
+bool
+Triangulation<TT, TDS>
+::is_valid(bool verbose, int level) const
+{
+ if( ! tds().is_valid(verbose, level) )
+ return false;
+
+ Full_cell_const_iterator c;
+ if( current_dimension() < 0 )
+ return true;
+ Orientation o;
+ for( c = full_cells_begin(); c != full_cells_end(); ++c )
+ {
+ if( is_infinite(c) )
+ {
+ if( current_dimension() > 1 )
+ {
+ int i = c->index( infinite_vertex() );
+ Full_cell_handle n = c->neighbor(i);
+ infinite_vertex()->set_point(n->vertex(c->mirror_index(i))->point());
+ o = - orientation(c, true);
+ }
+ else
+ o = POSITIVE;
+ }
+ else
+ o = orientation(c, true);
+ if( NEGATIVE == o )
+ {
+ if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented");
+ return false;
+ }
+ if( COPLANAR == o )
+ {
+ if( verbose ) CGAL_warning_msg(false, "full_cell is flat");
+ return false;
+ }
+ }
+ return true;
+}
+
+template < class TT, class TDS >
+bool Triangulation<TT, TDS>::are_incident_full_cells_valid(Vertex_const_handle v, bool verbose, int) const
+{
+ if( current_dimension() <= 0 )
+ return true;
+ typedef std::vector<Full_cell_const_handle> Simps;
+ Simps simps;
+ simps.reserve(64);
+ std::back_insert_iterator<Simps> out(simps);
+ incident_full_cells(v, out);
+ typename Simps::const_iterator sit = simps.begin();
+ for( ; sit != simps.end(); ++sit )
+ {
+ if( is_infinite(*sit) )
+ continue;
+ Orientation o = orientation(*sit);
+ if( NEGATIVE == o )
+ {
+ if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented");
+ return false;
+ }
+ if( COPLANAR == o )
+ {
+ if( verbose ) CGAL_warning_msg(false, "full_cell is flat");
+ return false;
+ }
+ }
+ return true;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS:
+
+template < class TT, class TDS >
+std::istream &
+operator>>(std::istream & is, Triangulation<TT, TDS> & tr)
+ // reads :
+ // - the dimensions (maximal and current)
+ // - the number of finite vertices
+ // - the non combinatorial information on vertices (point, etc)
+ // - the number of full_cells
+ // - the full_cells by the indices of their vertices in the preceding list
+ // of vertices, plus the non combinatorial information on each full_cell
+ // - the neighbors of each full_cell by their index in the preceding list
+{
+ typedef Triangulation<TT, TDS> T;
+ typedef typename T::Vertex_handle Vertex_handle;
+
+ // read current dimension and number of vertices
+ size_t n;
+ int cd;
+ if( is_ascii(is) )
+ is >> cd >> n;
+ else
+ {
+ read(is, cd);
+ read(is, n, io_Read_write());
+ }
+
+ CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation has too high dimension");
+
+ tr.clear();
+ tr.set_current_dimension(cd);
+
+ if( n == 0 )
+ return is;
+
+ std::vector<Vertex_handle> vertices;
+ vertices.resize(n+1);
+ vertices[0] = tr.infinite_vertex();
+ is >> (*vertices[0]);
+
+ // read the vertices:
+ size_t i(1);
+ while( i <= n )
+ {
+ vertices[i] = tr.new_vertex();
+ is >> (*vertices[i]); // read a vertex
+ ++i;
+ }
+
+ // now, read the combinatorial information
+ return tr.tds().read_full_cells(is, vertices);
+}
+
+template < class TT, class TDS >
+std::ostream &
+operator<<(std::ostream & os, const Triangulation<TT, TDS> & tr)
+ // writes :
+ // - the dimensions (maximal and current)
+ // - the number of finite vertices
+ // - the non combinatorial information on vertices (point, etc)
+ // - the number of full_cells
+ // - the full_cells by the indices of their vertices in the preceding list
+ // of vertices, plus the non combinatorial information on each full_cell
+ // - the neighbors of each full_cell by their index in the preceding list
+{
+ typedef Triangulation<TT, TDS> T;
+ typedef typename T::Vertex_const_handle Vertex_handle;
+ typedef typename T::Vertex_const_iterator Vertex_iterator;
+
+ // outputs dimensions and number of vertices
+ size_t n = tr.number_of_vertices();
+ if( is_ascii(os) )
+ os << tr.current_dimension() << std::endl << n << std::endl;
+ else
+ {
+ write(os, tr.current_dimension());
+ write(os, n, io_Read_write());
+ }
+
+ if( n == 0 )
+ return os;
+
+ size_t i(0);
+ // write the vertices
+ std::map<Vertex_handle, int> index_of_vertex;
+
+ // infinite vertex has index 0 (among all the vertices)
+ index_of_vertex[tr.infinite_vertex()] = i++;
+ os << *tr.infinite_vertex();
+ for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it )
+ {
+ if( tr.is_infinite(it) )
+ continue;
+ os << *it; // write the vertex
+ index_of_vertex[it] = i++;
+ }
+ CGAL_assertion( i == n+1 );
+
+ // output the combinatorial information
+ return tr.tds().write_full_cells(os, index_of_vertex);
+}
+
+} //namespace CGAL
+
+#endif // CGAL_TRIANGULATION_H
diff --git a/include/gudhi_patches/CGAL/Triangulation_data_structure.h b/include/gudhi_patches/CGAL/Triangulation_data_structure.h
new file mode 100644
index 00000000..2493c712
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Triangulation_data_structure.h
@@ -0,0 +1,1603 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_TRIANGULATION_DATA_STRUCTURE_H
+#define CGAL_TRIANGULATION_DATA_STRUCTURE_H
+
+#include <CGAL/basic.h>
+#include <CGAL/Default.h>
+#include <CGAL/iterator.h>
+#include <CGAL/Compact_container.h>
+#include <CGAL/Triangulation_face.h>
+#include <CGAL/Triangulation_ds_vertex.h>
+#include <CGAL/Triangulation_ds_full_cell.h>
+#include <CGAL/internal/Combination_enumerator.h>
+#include <CGAL/internal/Triangulation/utilities.h>
+#include <CGAL/internal/Triangulation/Triangulation_ds_iterators.h>
+
+#include <algorithm>
+#include <vector>
+#include <queue>
+#include <set>
+
+namespace CGAL {
+
+template< class Dimen,
+ class Vb = Default,
+ class Fcb = Default >
+class Triangulation_data_structure
+{
+ typedef Triangulation_data_structure<Dimen, Vb, Fcb> Self;
+ typedef typename Default::Get<Vb, Triangulation_ds_vertex<> >::type V_base;
+ typedef typename Default::Get<Fcb, Triangulation_ds_full_cell<> >::type FC_base;
+
+public:
+ typedef typename V_base::template Rebind_TDS<Self>::Other Vertex; /* Concept */
+ typedef typename FC_base::template Rebind_TDS<Self>::Other Full_cell; /* Concept */
+
+ // Tools to change the Vertex and Cell types of the TDS.
+ template < typename Vb2 >
+ struct Rebind_vertex {
+ typedef Triangulation_data_structure<Dimen, Vb2, Fcb> Other;
+ };
+
+ template < typename Fcb2 >
+ struct Rebind_full_cell {
+ typedef Triangulation_data_structure<Dimen, Vb, Fcb2> Other;
+ };
+
+
+
+ // we want to store an object of this class in every Full_cell:
+ class Full_cell_data
+ {
+ unsigned char bits_;
+ public:
+ Full_cell_data() : bits_(0) {}
+ Full_cell_data(const Full_cell_data & fcd) : bits_(fcd.bits_) {}
+
+ void clear() { bits_ = 0; }
+ void mark_visited() { bits_ = 1; }
+ void clear_visited() { bits_ = 0; }
+
+ bool is_clear() const { return bits_ == 0; }
+ bool is_visited() const { return bits_ == 1; }
+ // WARNING: if we use more bits and several bits can be set at once,
+ // then make sure to use bitwise operation above, instead of direct
+ // affectation.
+ };
+
+protected:
+ typedef Compact_container<Vertex> Vertex_container;
+ typedef Compact_container<Full_cell> Full_cell_container;
+
+public:
+ typedef Dimen Maximal_dimension;
+
+ typedef typename Vertex_container::size_type size_type; /* Concept */
+ typedef typename Vertex_container::difference_type difference_type; /* Concept */
+
+ typedef typename Vertex_container::iterator Vertex_handle; /* Concept */
+ typedef typename Vertex_container::iterator Vertex_iterator; /* Concept */
+ typedef typename Vertex_container::const_iterator Vertex_const_handle;
+ typedef typename Vertex_container::const_iterator Vertex_const_iterator;
+
+ typedef typename Full_cell_container::iterator Full_cell_handle; /* Concept */
+ typedef typename Full_cell_container::iterator Full_cell_iterator; /* Concept */
+ typedef typename Full_cell_container::const_iterator Full_cell_const_handle;
+ typedef typename Full_cell_container::const_iterator Full_cell_const_iterator;
+
+ typedef internal::Triangulation::
+ Triangulation_ds_facet_iterator<Self> Facet_iterator; /* Concept */
+
+ /* The 2 types defined below, |Facet| and |Rotor| are used when traversing
+ the boundary `B' of the union of a set of full cells. |Rotor| makes it
+ easy to rotate around itself, in the search of neighbors in `B' (see
+ |rotate_rotor| and |insert_in_tagged_hole|) */
+
+ // A co-dimension 1 sub-simplex.
+ class Facet /* Concept */
+ {
+ Full_cell_handle full_cell_;
+ int index_of_covertex_;
+ public:
+ Facet() : full_cell_(), index_of_covertex_(0) {}
+ Facet(Full_cell_handle f, int i) : full_cell_(f), index_of_covertex_(i) {}
+ Full_cell_handle full_cell() const { return full_cell_; }
+ int index_of_covertex() const { return index_of_covertex_; }
+ };
+
+ // A co-dimension 2 sub-simplex. called a Rotor because we can rotate
+ // the two "covertices" around the sub-simplex. Useful for traversing the
+ // boundary of a hole. NOT DOCUMENTED
+ class Rotor : public Facet
+ {
+ int index_of_second_covertex_;
+ public:
+ Rotor() : Facet(), index_of_second_covertex_(0) {}
+ Rotor(Full_cell_handle f, int first, int second) : Facet(f, first), index_of_second_covertex_(second) {}
+ int index_of_second_covertex() const { return index_of_second_covertex_; }
+ };
+
+ typedef Triangulation_face<Self> Face; /* Concept */
+
+protected: // DATA MEMBERS
+
+ int dmax_, dcur_; // dimension of the current triangulation
+ Vertex_container vertices_; // list of all vertices
+ Full_cell_container full_cells_; // list of all full cells
+
+private:
+
+ void clean_dynamic_memory()
+ {
+ vertices_.clear();
+ full_cells_.clear();
+ }
+
+ template < class Dim_tag >
+ struct get_maximal_dimension
+ {
+ static int value(int D) { return D; }
+ };
+ // specialization
+ template < int D >
+ struct get_maximal_dimension<Dimension_tag<D> >
+ {
+ static int value(int) { return D; }
+ };
+
+public:
+ Triangulation_data_structure( int dim=0) /* Concept */
+ : dmax_(get_maximal_dimension<Dimen>::value(dim)), dcur_(-2),
+ vertices_(), full_cells_()
+ {
+ CGAL_assertion_msg(dmax_ > 0, "maximal dimension must be positive.");
+ }
+
+ ~Triangulation_data_structure()
+ {
+ clean_dynamic_memory();
+ }
+
+ Triangulation_data_structure(const Triangulation_data_structure & tds)
+ : dmax_(tds.dmax_), dcur_(tds.dcur_),
+ vertices_(tds.vertices_), full_cells_(tds.full_cells_)
+ {
+ typedef std::map<Vertex_const_handle, Vertex_handle> V_map;
+ typedef std::map<Full_cell_const_handle, Full_cell_handle> C_map;
+ V_map vmap;
+ C_map cmap;
+ Vertex_const_iterator vfrom = tds.vertices_begin();
+ Vertex_iterator vto = vertices_begin();
+ Full_cell_const_iterator cfrom = tds.full_cells_begin();
+ Full_cell_iterator cto = full_cells_begin();
+ while( vfrom != tds.vertices_end() )
+ vmap[vfrom++] = vto++;
+ while( cfrom != tds.full_cells_end() )
+ cmap[cfrom++] = cto++;
+ cto = full_cells_begin();
+ while( cto != full_cells_end() )
+ {
+ for( int i = 0; i <= (std::max)(0, current_dimension()); ++i )
+ {
+ associate_vertex_with_full_cell(cto, i, vmap[cto->vertex(i)]);
+ cto->set_neighbor(i, cmap[cto->neighbor(i)]);
+ }
+ ++cto;
+ }
+ }
+
+ // QUERIES
+
+protected:
+
+ bool check_range(int i) const
+ {
+ if( current_dimension() < 0 )
+ {
+ return (0 == i);
+ }
+ return ( (0 <= i) && (i <= current_dimension()) );
+ }
+
+public:
+
+ /* returns the current dimension of the full cells in the triangulation. */
+ int maximal_dimension() const { return dmax_; } /* Concept */
+ int current_dimension() const { return dcur_; } /* Concept */
+
+ size_type number_of_vertices() const /* Concept */
+ {
+ return this->vertices_.size();
+ }
+ size_type number_of_full_cells() const /* Concept */
+ {
+ return this->full_cells_.size();
+ }
+
+ bool empty() const /* Concept */
+ {
+ return current_dimension() == -2;
+ }
+
+ Vertex_container & vertices() { return vertices_; }
+ const Vertex_container & vertices() const { return vertices_; }
+ Full_cell_container & full_cells() { return full_cells_; }
+ const Full_cell_container & full_cells() const { return full_cells_; }
+
+ Vertex_handle vertex(Full_cell_handle s, int i) const /* Concept */
+ {
+ CGAL_precondition(s != Full_cell_handle() && check_range(i));
+ return s->vertex(i);
+ }
+
+ Vertex_const_handle vertex(Full_cell_const_handle s, int i) const /* Concept */
+ {
+ CGAL_precondition(s != Full_cell_handle() && check_range(i));
+ return s->vertex(i);
+ }
+
+ bool is_vertex(Vertex_const_handle v) const /* Concept */
+ {
+ if( Vertex_const_handle() == v )
+ return false;
+ Vertex_const_iterator vit = vertices_begin();
+ while( vit != vertices_end() && ( v != vit ) )
+ ++vit;
+ return v == vit;
+ }
+
+ bool is_full_cell(Full_cell_const_handle s) const /* Concept */
+ {
+ if( Full_cell_const_handle() == s )
+ return false;
+ Full_cell_const_iterator sit = full_cells_begin();
+ while( sit != full_cells_end() && ( s != sit ) )
+ ++sit;
+ return s == sit;
+ }
+
+ Full_cell_handle full_cell(Vertex_handle v) const /* Concept */
+ {
+ CGAL_precondition(v != Vertex_handle());
+ return v->full_cell();
+ }
+
+ Full_cell_const_handle full_cell(Vertex_const_handle v) const /* Concept */
+ {
+ CGAL_precondition(Vertex_const_handle() != v);
+ return v->full_cell();
+ }
+
+ Full_cell_handle neighbor(Full_cell_handle s, int i) const /* Concept */
+ {
+ CGAL_precondition(Full_cell_handle() != s && check_range(i));
+ return s->neighbor(i);
+ }
+
+ Full_cell_const_handle neighbor(Full_cell_const_handle s, int i) const/* Concept */
+ {
+ CGAL_precondition(Full_cell_const_handle() != s && check_range(i));
+ return s->neighbor(i);
+ }
+
+ int mirror_index(Full_cell_handle s, int i) const /* Concept */
+ {
+ CGAL_precondition(Full_cell_handle() != s && check_range(i));
+ return s->mirror_index(i);
+ }
+
+ int mirror_index(Full_cell_const_handle s, int i) const
+ {
+ CGAL_precondition(Full_cell_const_handle() != s && check_range(i)); /* Concept */
+ return s->mirror_index(i);
+ }
+
+ int mirror_vertex(Full_cell_handle s, int i) const /* Concept */
+ {
+ CGAL_precondition(Full_cell_handle() != s && check_range(i));
+ return s->mirror_vertex(i);
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FACETS OPERATIONS
+
+ // works for Face_ = Facet and Face_ = Rotor.
+ // NOT DOCUMENTED for the Rotor case...
+ template< typename Face_ >
+ Full_cell_handle full_cell(const Face_ & f) const /* Concept */
+ {
+ return f.full_cell();
+ }
+
+ // works for Face_ = Facet and Face_ = Rotor.
+ // NOT DOCUMENTED for the Rotor case...
+ template< class Face_ >
+ int index_of_covertex(const Face_ & f) const /* Concept */
+ {
+ return f.index_of_covertex();
+ }
+
+ // NOT DOCUMENTED
+ // A Rotor has two covertices
+ int index_of_second_covertex(const Rotor & f) const
+ {
+ return f.index_of_second_covertex();
+ }
+
+ // works for Face_ = Facet and Face_ = Rotor.
+ // NOT DOCUMENTED...
+ template< class Face_ >
+ bool is_boundary_facet(const Face_ & f) const
+ {
+ if( get_visited(neighbor(full_cell(f), index_of_covertex(f))) )
+ return false;
+ if( ! get_visited(full_cell(f)) )
+ return false;
+ return true;
+ }
+
+ // NOT DOCUMENTED...
+ Rotor rotate_rotor(Rotor & f)
+ {
+ int opposite = mirror_index(full_cell(f), index_of_covertex(f));
+ Full_cell_handle s = neighbor(full_cell(f), index_of_covertex(f));
+ int new_second = s->index(vertex(full_cell(f), index_of_second_covertex(f)));
+ return Rotor(s, new_second, opposite);
+ }
+
+ // NICE UPDATE OPERATIONS
+
+protected:
+ void do_insert_increase_dimension(Vertex_handle, Vertex_handle);
+public:
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
+
+ Vertex_handle collapse_face(const Face &); /* Concept */
+ void remove_decrease_dimension(Vertex_handle, Vertex_handle); /* Concept */
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS
+
+ Vertex_handle insert_in_full_cell(Full_cell_handle); /* Concept */
+ Vertex_handle insert_in_face(const Face &); /* Concept */
+ Vertex_handle insert_in_facet(const Facet &); /* Concept */
+ template< typename Forward_iterator >
+ Vertex_handle insert_in_hole(Forward_iterator, Forward_iterator, Facet); /* Concept */
+ template< typename Forward_iterator, typename OutputIterator >
+ Vertex_handle insert_in_hole(Forward_iterator, Forward_iterator, Facet, OutputIterator); /* Concept */
+
+ template< typename OutputIterator >
+ Full_cell_handle insert_in_tagged_hole(Vertex_handle, Facet, OutputIterator);
+
+ Vertex_handle insert_increase_dimension(Vertex_handle=Vertex_handle()); /* Concept */
+
+private:
+
+ // Used by insert_in_tagged_hole
+ struct IITH_task
+ {
+ IITH_task(
+ Facet boundary_facet_,
+ int index_of_inside_cell_in_outside_cell_,
+ Full_cell_handle future_neighbor_ = Full_cell_handle(),
+ int new_cell_index_in_future_neighbor_ = -1,
+ int index_of_future_neighbor_in_new_cell_ = -1)
+ : boundary_facet(boundary_facet_),
+ index_of_inside_cell_in_outside_cell(index_of_inside_cell_in_outside_cell_),
+ future_neighbor(future_neighbor_),
+ new_cell_index_in_future_neighbor(new_cell_index_in_future_neighbor_),
+ index_of_future_neighbor_in_new_cell(index_of_future_neighbor_in_new_cell_)
+ {}
+
+ // "new_cell" is the cell about to be created
+ Facet boundary_facet;
+ int index_of_inside_cell_in_outside_cell;
+ Full_cell_handle future_neighbor;
+ int new_cell_index_in_future_neighbor;
+ int index_of_future_neighbor_in_new_cell;
+ };
+
+ // NOT DOCUMENTED
+ void clear_visited_marks(Full_cell_handle) const;
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DANGEROUS UPDATE OPERATIONS
+
+private:
+
+ // NOT DOCUMENTED
+ template< typename FCH > // FCH = Full_cell_[const_]handle
+ bool get_visited(FCH c) const
+ {
+ return c->tds_data().is_visited();
+ }
+
+ // NOT DOCUMENTED
+ template< typename FCH > // FCH = Full_cell_[const_]handle
+ void set_visited(FCH c, bool m) const
+ {
+ if( m )
+ c->tds_data().mark_visited();
+ else
+ c->tds_data().clear_visited();
+ }
+
+public:
+
+ void clear() /* Concept */
+ {
+ clean_dynamic_memory();
+ dcur_ = -2;
+ }
+
+ void set_current_dimension(int d) /* Concept */
+ {
+ CGAL_precondition(-2<=d && d<=maximal_dimension());
+ dcur_ = d;
+ }
+
+ Full_cell_handle new_full_cell(Full_cell_handle s)
+ {
+ return full_cells_.emplace(*s);
+ }
+
+ Full_cell_handle new_full_cell() /* Concept */
+ {
+ return full_cells_.emplace(dmax_);
+ }
+
+ void delete_full_cell(Full_cell_handle s) /* Concept */
+ {
+ CGAL_precondition(Full_cell_handle() != s);
+ // CGAL_expensive_precondition(is_full_cell(s));
+ full_cells_.erase(s);
+ }
+
+ template< typename Forward_iterator >
+ void delete_full_cells(Forward_iterator start, Forward_iterator end) /* Concept */
+ {
+ Forward_iterator s = start;
+ while( s != end )
+ full_cells_.erase(*s++);
+ }
+
+ template< class T >
+ Vertex_handle new_vertex( const T & t )
+ {
+ return vertices_.emplace(t);
+ }
+
+ Vertex_handle new_vertex() /* Concept */
+ {
+ return vertices_.emplace();
+ }
+
+ void delete_vertex(Vertex_handle v) /* Concept */
+ {
+ CGAL_precondition( Vertex_handle() != v );
+ vertices_.erase(v);
+ }
+
+ void associate_vertex_with_full_cell(Full_cell_handle s, int i, Vertex_handle v) /* Concept */
+ {
+ CGAL_precondition(check_range(i));
+ CGAL_precondition(s != Full_cell_handle());
+ CGAL_precondition(v != Vertex_handle());
+ s->set_vertex(i, v);
+ v->set_full_cell(s);
+ }
+
+ void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j) /* Concept */
+ {
+ CGAL_precondition(check_range(i));
+ CGAL_precondition(check_range(j));
+ CGAL_precondition(s != Full_cell_handle());
+ CGAL_precondition(s1 != Full_cell_handle());
+ s->set_neighbor(i, s1);
+ s1->set_neighbor(j, s);
+ s->set_mirror_index(i, j);
+ s1->set_mirror_index(j, i);
+ }
+
+ // SANITY CHECKS
+
+ bool is_valid(bool = true, int = 0) const; /* Concept */
+
+ // NOT DOCUMENTED
+ template< class OutStream> void write_graph(OutStream &);
+
+ Vertex_iterator vertices_begin() { return vertices_.begin(); } /* Concept */
+ Vertex_iterator vertices_end() { return vertices_.end(); } /* Concept */
+ Full_cell_iterator full_cells_begin() { return full_cells_.begin(); } /* Concept */
+ Full_cell_iterator full_cells_end() { return full_cells_.end(); } /* Concept */
+
+ Vertex_const_iterator vertices_begin() const { return vertices_.begin(); } /* Concept */
+ Vertex_const_iterator vertices_end() const { return vertices_.end(); } /* Concept */
+ Full_cell_const_iterator full_cells_begin() const { return full_cells_.begin(); } /* Concept */
+ Full_cell_const_iterator full_cells_end() const { return full_cells_.end(); } /* Concept */
+
+ Facet_iterator facets_begin() /* Concept */
+ {
+ if( current_dimension() <= 0 )
+ return facets_end();
+ return Facet_iterator(*this);
+ }
+ Facet_iterator facets_end() /* Concept */
+ {
+ return Facet_iterator(*this, 0);
+ }
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - FULL CELL GATHERING
+
+ // a traversal predicate for gathering full_cells incident to a given face
+ // ``incident'' means that the given face is a subface of the full_cell
+ class Incident_full_cell_traversal_predicate
+ {
+ const Face & f_;
+ int dim_;
+ const Triangulation_data_structure & tds_;
+ public:
+ Incident_full_cell_traversal_predicate(const Triangulation_data_structure & tds,
+ const Face & f)
+ : f_(f), tds_(tds)
+ {
+ dim_ = f.face_dimension();
+ }
+ bool operator()(const Facet & facet) const
+ {
+ Vertex_handle v = tds_.full_cell(facet)->vertex(tds_.index_of_covertex(facet));
+ for( int i = 0; i <= dim_; ++i )
+ {
+ if( v == f_.vertex(i) )
+ return false;
+ }
+ return true;
+ }
+ };
+
+ // a traversal predicate for gathering full_cells having a given face as subface
+ class Star_traversal_predicate
+ {
+ const Face & f_;
+ int dim_;
+ const Triangulation_data_structure & tds_;
+ public:
+ Star_traversal_predicate(const Triangulation_data_structure & tds,
+ const Face & f)
+ : f_(f), tds_(tds)
+ {
+ dim_ = f.face_dimension();
+ }
+ bool operator()(const Facet & facet) const
+ {
+ Full_cell_handle s = tds_.full_cell(facet)->neighbor(tds_.index_of_covertex(facet));
+ for( int j = 0; j <= tds_.current_dimension(); ++j )
+ {
+ for( int i = 0; i <= dim_; ++i )
+ if( s->vertex(j) == f_.vertex(i) )
+ return true;
+ }
+ return false;
+ }
+ };
+
+ template< typename TraversalPredicate, typename OutputIterator >
+ Facet gather_full_cells(Full_cell_handle, TraversalPredicate &, OutputIterator &) const; /* Concept */
+ template< typename OutputIterator >
+ OutputIterator incident_full_cells(const Face &, OutputIterator) const; /* Concept */
+ template< typename OutputIterator >
+ OutputIterator incident_full_cells(Vertex_const_handle, OutputIterator) const; /* Concept */
+ template< typename OutputIterator >
+ OutputIterator star(const Face &, OutputIterator) const; /* Concept */
+#ifndef CGAL_CFG_NO_CPP0X_DEFAULT_TEMPLATE_ARGUMENTS_FOR_FUNCTION_TEMPLATES
+ template< typename OutputIterator, typename Comparator = std::less<Vertex_const_handle> >
+ OutputIterator incident_upper_faces(Vertex_const_handle v, int dim, OutputIterator out, Comparator cmp = Comparator())
+ {
+ return incident_faces(v, dim, out, cmp, true);
+ }
+ template< typename OutputIterator, typename Comparator = std::less<Vertex_const_handle> >
+ OutputIterator incident_faces(Vertex_const_handle, int, OutputIterator, Comparator = Comparator(), bool = false) const;
+#else
+ template< typename OutputIterator, typename Comparator >
+ OutputIterator incident_upper_faces(Vertex_const_handle v, int dim, OutputIterator out, Comparator cmp = Comparator())
+ {
+ return incident_faces(v, dim, out, cmp, true);
+ }
+ template< typename OutputIterator >
+ OutputIterator incident_upper_faces(Vertex_const_handle v, int dim, OutputIterator out)
+ {
+ return incident_faces(v, dim, out, std::less<Vertex_const_handle>(), true);
+ }
+ template< typename OutputIterator, typename Comparator >
+ OutputIterator incident_faces(Vertex_const_handle, int, OutputIterator, Comparator = Comparator(), bool = false) const;
+ template< typename OutputIterator >
+ OutputIterator incident_faces(Vertex_const_handle, int, OutputIterator,
+ std::less<Vertex_const_handle> = std::less<Vertex_const_handle>(), bool = false) const;
+#endif
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INPUT / OUTPUT
+
+ std::istream & read_full_cells(std::istream &, const std::vector<Vertex_handle> &);
+ std::ostream & write_full_cells(std::ostream &, std::map<Vertex_const_handle, int> &) const;
+
+}; // end of ``declaration/definition'' of Triangulation_data_structure<...>
+
+// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+
+// FUNCTIONS THAT ARE MEMBER FUNCTIONS:
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// - - - - - - - - - - - - - - - - - - - - - - - - THE GATHERING METHODS
+
+template< class Dim, class Vb, class Fcb >
+template< typename OutputIterator >
+OutputIterator
+Triangulation_data_structure<Dim, Vb, Fcb>
+::incident_full_cells(const Face & f, OutputIterator out) const /* Concept */
+{
+ // CGAL_expensive_precondition_msg(is_full_cell(f.full_cell()), "the facet does not belong to the Triangulation");
+ Incident_full_cell_traversal_predicate tp(*this, f);
+ gather_full_cells(f.full_cell(), tp, out);
+ return out;
+}
+
+template< class Dim, class Vb, class Fcb >
+template< typename OutputIterator >
+OutputIterator
+Triangulation_data_structure<Dim, Vb, Fcb>
+::incident_full_cells(Vertex_const_handle v, OutputIterator out) const /* Concept */
+{
+// CGAL_expensive_precondition(is_vertex(v));
+ CGAL_precondition(Vertex_handle() != v);
+ Face f(v->full_cell());
+ f.set_index(0, v->full_cell()->index(v));
+ return incident_full_cells(f, out);
+}
+
+template< class Dim, class Vb, class Fcb >
+template< typename OutputIterator >
+OutputIterator
+Triangulation_data_structure<Dim, Vb, Fcb>
+::star(const Face & f, OutputIterator out) const /* Concept */
+{
+ // CGAL_precondition_msg(is_full_cell(f.full_cell()), "the facet does not belong to the Triangulation");
+ Star_traversal_predicate tp(*this, f);
+ gather_full_cells(f.full_cell(), tp, out);
+ return out;
+}
+
+template< class Dim, class Vb, class Fcb >
+template< typename TraversalPredicate, typename OutputIterator >
+typename Triangulation_data_structure<Dim, Vb, Fcb>::Facet
+Triangulation_data_structure<Dim, Vb, Fcb>
+::gather_full_cells(Full_cell_handle start,
+ TraversalPredicate & tp,
+ OutputIterator & out) const /* Concept */
+{
+ std::queue<Full_cell_handle> queue;
+ set_visited(start, true);
+ queue.push(start);
+ const int cur_dim = current_dimension();
+ Facet ft;
+ while( ! queue.empty() )
+ {
+ Full_cell_handle s = queue.front();
+ queue.pop();
+ *out = s;
+ ++out;
+ for( int i = 0; i <= cur_dim; ++i )
+ {
+ Full_cell_handle n = s->neighbor(i);
+ if( ! get_visited(n) )
+ {
+ set_visited(n, true);
+ if( tp(Facet(s, i)) )
+ queue.push(n);
+ else
+ ft = Facet(s, i);
+ }
+ }
+ }
+ clear_visited_marks(start);
+ return ft;
+}
+
+#ifdef CGAL_CFG_NO_CPP0X_DEFAULT_TEMPLATE_ARGUMENTS_FOR_FUNCTION_TEMPLATES
+template< class Dim, class Vb, class Fcb >
+template< typename OutputIterator >
+OutputIterator
+Triangulation_data_structure<Dim, Vb, Fcb>
+::incident_faces(Vertex_const_handle v, int dim, OutputIterator out,
+ std::less<Vertex_const_handle> cmp, bool upper_faces) const
+{
+ return incident_faces<OutputIterator, std::less<Vertex_const_handle> >(v, dim, out, cmp, upper_faces);
+}
+#endif
+
+template< class Dim, class Vb, class Fcb >
+template< typename OutputIterator, typename Comparator >
+OutputIterator
+Triangulation_data_structure<Dim, Vb, Fcb>
+::incident_faces(Vertex_const_handle v, int dim, OutputIterator out, Comparator cmp, bool upper_faces) const
+{
+ CGAL_precondition( 0 < dim );
+ if( dim >= current_dimension() )
+ return out;
+ typedef std::vector<Full_cell_handle> Simplices;
+ Simplices simps;
+ simps.reserve(64);
+ // gather incident full_cells
+ std::back_insert_iterator<Simplices> sout(simps);
+ incident_full_cells(v, sout);
+ // for storing the handles to the vertices of a full_cell
+ typedef std::vector<Vertex_const_handle> Vertices;
+ typedef std::vector<int> Indices;
+ Vertices vertices(1 + current_dimension());
+ Indices sorted_idx(1 + current_dimension());
+ // setup Face comparator and Face_set
+ typedef internal::Triangulation::Compare_faces_with_common_first_vertex<Self>
+ Upper_face_comparator;
+ Upper_face_comparator ufc(dim);
+ typedef std::set<Face, Upper_face_comparator> Face_set;
+ Face_set face_set(ufc);
+ for( typename Simplices::const_iterator s = simps.begin(); s != simps.end(); ++s )
+ {
+ int v_idx(0); // the index of |v| in the sorted full_cell
+ // get the vertices of the full_cell and sort them
+ for( int i = 0; i <= current_dimension(); ++i )
+ vertices[i] = (*s)->vertex(i);
+ if( upper_faces )
+ {
+ std::sort(vertices.begin(), vertices.end(), cmp);
+ while( vertices[v_idx] != v )
+ ++v_idx;
+ }
+ else
+ {
+ while( vertices[v_idx] != v )
+ ++v_idx;
+ if( 0 != v_idx )
+ std::swap(vertices[0], vertices[v_idx]);
+ v_idx = 0;
+ typename Vertices::iterator vbegin(vertices.begin());
+ ++vbegin;
+ std::sort(vbegin, vertices.end(), cmp);
+ }
+ if( v_idx + dim > current_dimension() )
+ continue; // |v| is too far to the right
+ // stores the index of the vertices of s in the same order
+ // as in |vertices|:
+ for( int i = 0; i <= current_dimension(); ++i )
+ sorted_idx[i] = (*s)->index(vertices[i]);
+ // init state for enumerating all candidate faces:
+ internal::Combination_enumerator f_idx(dim, v_idx + 1, current_dimension());
+ Face f(*s);
+ f.set_index(0, sorted_idx[v_idx]);
+ while( ! f_idx.end() )
+ {
+ for( int i = 0; i < dim; ++i )
+ f.set_index(1 + i, sorted_idx[f_idx[i]]);
+ face_set.insert(f); // checks if face has already been found
+
+ // compute next sorted face (lexicographic enumeration)
+ ++f_idx;
+ }
+ }
+ typename Face_set::iterator fit = face_set.begin();
+ while( fit != face_set.end() )
+ *out++ = *fit++;
+ return out;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// - - - - - - - - - - - - - - - - - - - - - - - - THE REMOVAL METHODS
+
+template <class Dim, class Vb, class Fcb>
+typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle
+Triangulation_data_structure<Dim, Vb, Fcb>
+::collapse_face(const Face & f) /* Concept */
+{
+ const int fd = f.face_dimension();
+ CGAL_precondition( (1 <= fd ) && (fd < current_dimension()));
+ std::vector<Full_cell_handle> simps;
+ // save the Face's vertices:
+ Full_cell s;
+ for( int i = 0; i <= fd; ++i )
+ s.set_vertex(i, f.vertex(i));
+ // compute the star of f
+ simps.reserve(64);
+ std::back_insert_iterator<std::vector<Full_cell_handle> > out(simps);
+ star(f, out);
+ Vertex_handle v = insert_in_hole(simps.begin(), simps.end(), Facet(f.full_cell(), f.index(0)));
+ for( int i = 0; i <= fd; ++i )
+ delete_vertex(s.vertex(i));
+ return v;
+}
+
+template <class Dim, class Vb, class Fcb>
+void
+Triangulation_data_structure<Dim, Vb, Fcb>
+::remove_decrease_dimension(Vertex_handle v, Vertex_handle star) /* Concept */
+{
+ CGAL_assertion( current_dimension() >= -1 );
+ if( -1 == current_dimension() )
+ {
+ clear();
+ return;
+ }
+ else if( 0 == current_dimension() )
+ {
+ delete_full_cell(v->full_cell());
+ delete_vertex(v);
+ star->full_cell()->set_neighbor(0, Full_cell_handle());
+ set_current_dimension(-1);
+ return;
+ }
+ else if( 1 == current_dimension() )
+ {
+ Full_cell_handle s = v->full_cell();
+ int star_index;
+ if( s->has_vertex(star, star_index) )
+ s = s->neighbor(star_index);
+ // Here, |star| is not a vertex of |s|, so it's the only finite
+ // full_cell
+ Full_cell_handle inf1 = s->neighbor(0);
+ Full_cell_handle inf2 = s->neighbor(1);
+ Vertex_handle v2 = s->vertex(1 - s->index(v));
+ delete_vertex(v);
+ delete_full_cell(s);
+ inf1->set_vertex(1, Vertex_handle());
+ inf1->set_vertex(1, Vertex_handle());
+ inf2->set_neighbor(1, Full_cell_handle());
+ inf2->set_neighbor(1, Full_cell_handle());
+ associate_vertex_with_full_cell(inf1, 0, star);
+ associate_vertex_with_full_cell(inf2, 0, v2);
+ set_neighbors(inf1, 0, inf2, 0);
+ set_current_dimension(0);
+ return;
+ }
+ typedef std::vector<Full_cell_handle> Simplices;
+ Simplices simps;
+ incident_full_cells(v, std::back_inserter(simps));
+ for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it )
+ {
+ int v_idx = (*it)->index(v);
+ if( ! (*it)->has_vertex(star) )
+ {
+ delete_full_cell((*it)->neighbor(v_idx));
+ for( int i = 0; i <= current_dimension(); ++i )
+ (*it)->vertex(i)->set_full_cell(*it);
+ }
+ else
+ star->set_full_cell(*it);
+ if( v_idx != current_dimension() )
+ {
+ (*it)->swap_vertices(v_idx, current_dimension());
+ (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1);
+ }
+ (*it)->set_vertex(current_dimension(), Vertex_handle());
+ (*it)->set_neighbor(current_dimension(), Full_cell_handle());
+ }
+ set_current_dimension(current_dimension()-1);
+ delete_vertex(v);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// - - - - - - - - - - - - - - - - - - - - - - - - THE INSERTION METHODS
+
+template <class Dim, class Vb, class Fcb>
+typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle
+Triangulation_data_structure<Dim, Vb, Fcb>
+::insert_in_full_cell(Full_cell_handle s) /* Concept */
+{
+ CGAL_precondition(0 < current_dimension());
+ CGAL_precondition(Full_cell_handle() != s);
+ // CGAL_expensive_precondition(is_full_cell(s));
+
+ const int cur_dim = current_dimension();
+ Vertex_handle v = new_vertex();
+ // the full_cell 'fc' is just used to store the handle to all the new full_cells.
+ Full_cell fc(maximal_dimension());
+ for( int i = 1; i <= cur_dim; ++i )
+ {
+ Full_cell_handle new_s = new_full_cell(s);
+ fc.set_neighbor(i, new_s);
+ associate_vertex_with_full_cell(new_s, i, v);
+ s->vertex(i-1)->set_full_cell(new_s);
+ set_neighbors(new_s, i, neighbor(s, i), mirror_index(s, i));
+ }
+ fc.set_neighbor(0, s);
+ associate_vertex_with_full_cell(s, 0, v);
+ for( int i = 0; i <= cur_dim; ++i )
+ for( int j = 0; j <= cur_dim; ++j )
+ {
+ if( j == i ) continue;
+ set_neighbors(fc.neighbor(i), j, fc.neighbor(j), i);
+ }
+ return v;
+}
+
+template <class Dim, class Vb, class Fcb >
+typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle
+Triangulation_data_structure<Dim, Vb, Fcb>
+::insert_in_face(const Face & f) /* Concept */
+{
+ std::vector<Full_cell_handle> simps;
+ simps.reserve(64);
+ std::back_insert_iterator<std::vector<Full_cell_handle> > out(simps);
+ incident_full_cells(f, out);
+ return insert_in_hole(simps.begin(), simps.end(), Facet(f.full_cell(), f.index(0)));
+}
+template <class Dim, class Vb, class Fcb >
+typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle
+Triangulation_data_structure<Dim, Vb, Fcb>
+::insert_in_facet(const Facet & ft) /* Concept */
+{
+ Full_cell_handle s[2];
+ s[0] = full_cell(ft);
+ int i = index_of_covertex(ft);
+ s[1] = s[0]->neighbor(i);
+ i = ( i + 1 ) % current_dimension();
+ return insert_in_hole(s, s+2, Facet(s[0], i));
+}
+
+template <class Dim, class Vb, class Fcb >
+template < typename OutputIterator >
+typename Triangulation_data_structure<Dim, Vb, Fcb>::Full_cell_handle
+Triangulation_data_structure<Dim, Vb, Fcb>
+::insert_in_tagged_hole(Vertex_handle v, Facet f,
+ OutputIterator new_full_cells)
+{
+ CGAL_assertion_msg(is_boundary_facet(f), "starting facet should be on the hole boundary");
+
+ const int cur_dim = current_dimension();
+ Full_cell_handle new_s;
+
+ std::queue<IITH_task> task_queue;
+ task_queue.push(
+ IITH_task(f, mirror_index(full_cell(f), index_of_covertex(f))) );
+
+ while (!task_queue.empty())
+ {
+ IITH_task task = task_queue.front();
+ task_queue.pop();
+
+ Full_cell_handle old_s = full_cell(task.boundary_facet);
+ const int facet_index = index_of_covertex(task.boundary_facet);
+
+ Full_cell_handle outside_neighbor = neighbor(old_s, facet_index);
+ // Here, "new_s" might actually be a new cell, but it might also be "old_s"
+ // if it has not been treated already in the meantime
+ new_s = neighbor(outside_neighbor, task.index_of_inside_cell_in_outside_cell);
+ // If the cell has not been treated yet
+ if (old_s == new_s)
+ {
+ new_s = new_full_cell();
+
+ int i(0);
+ for ( ; i < facet_index ; ++i)
+ associate_vertex_with_full_cell(new_s, i, old_s->vertex(i));
+ ++i; // skip facet_index
+ for ( ; i <= cur_dim ; ++i)
+ associate_vertex_with_full_cell(new_s, i, old_s->vertex(i));
+ associate_vertex_with_full_cell(new_s, facet_index, v);
+ set_neighbors(new_s,
+ facet_index,
+ outside_neighbor,
+ mirror_index(old_s, facet_index));
+
+ // add the new full_cell to the list of new full_cells
+ *new_full_cells++ = new_s;
+
+ // check all of |Facet f|'s neighbors
+ for (i = 0 ; i <= cur_dim ; ++i)
+ {
+ if (facet_index == i)
+ continue;
+ // we define a |Rotor| because it makes it easy to rotate around
+ // in a self contained fashion. The corresponding potential
+ // boundary facet is Facet(full_cell(rot), index_of_covertex(rot))
+ Rotor rot(old_s, i, facet_index);
+ // |rot| on line above, stands for Candidate Facet
+ while (!is_boundary_facet(rot))
+ rot = rotate_rotor(rot);
+
+ // we did find the |i|-th neighbor of Facet(old_s, facet_index)...
+ // has it already been extruded to center point |v| ?
+ Full_cell_handle inside = full_cell(rot);
+ Full_cell_handle outside = neighbor(inside, index_of_covertex(rot));
+ // "m" is the vertex of outside which is not on the boundary
+ Vertex_handle m = inside->mirror_vertex(index_of_covertex(rot), current_dimension()); // CJTODO: use mirror_index?
+ // "index" is the index of m in "outside"
+ int index = outside->index(m);
+ // new_neighbor is the inside cell which is registered as the neighbor
+ // of the outside cell => it's either a newly created inside cell or an
+ // old inside cell which we are about to delete
+ Full_cell_handle new_neighbor = outside->neighbor(index);
+
+ // Is new_neighbor still the old neighbor?
+ if (new_neighbor == inside)
+ {
+ task_queue.push(IITH_task(
+ Facet(inside, index_of_covertex(rot)), // boundary facet
+ index, // index_of_inside_cell_in_outside_cell
+ new_s, // future_neighbor
+ i, // new_cell_index_in_future_neighbor
+ index_of_second_covertex(rot) // index_of_future_neighbor_in_new_cell
+ ));
+ }
+ }
+ }
+
+ // If there is some neighbor stories to fix
+ if (task.future_neighbor != Full_cell_handle())
+ {
+ // now the new neighboring full_cell exists, we link both
+ set_neighbors(new_s,
+ task.index_of_future_neighbor_in_new_cell,
+ task.future_neighbor,
+ task.new_cell_index_in_future_neighbor);
+ }
+ }
+
+ return new_s;
+}
+
+template< class Dim, class Vb, class Fcb >
+template< typename Forward_iterator, typename OutputIterator >
+typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle
+Triangulation_data_structure<Dim, Vb, Fcb>
+::insert_in_hole(Forward_iterator start, Forward_iterator end, Facet f,
+ OutputIterator out) /* Concept */
+{
+ CGAL_expensive_precondition(
+ ( std::distance(start, end) == 1 )
+ || ( current_dimension() > 1 ) );
+ Forward_iterator sit = start;
+ while( end != sit )
+ set_visited(*sit++, true);
+ Vertex_handle v = new_vertex();
+ insert_in_tagged_hole(v, f, out);
+ delete_full_cells(start, end);
+ return v;
+}
+
+template< class Dim, class Vb, class Fcb >
+template< typename Forward_iterator >
+typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle
+Triangulation_data_structure<Dim, Vb, Fcb>
+::insert_in_hole(Forward_iterator start, Forward_iterator end, Facet f) /* Concept */
+{
+ Emptyset_iterator out;
+ return insert_in_hole(start, end, f, out);
+}
+
+template <class Dim, class Vb, class Fcb>
+void
+Triangulation_data_structure<Dim, Vb, Fcb>
+::clear_visited_marks(Full_cell_handle start) const // NOT DOCUMENTED
+{
+ CGAL_precondition(start != Full_cell_handle());
+
+ std::queue<Full_cell_handle> queue;
+ set_visited(start, false);
+ queue.push(start);
+ const int cur_dim = current_dimension();
+ while( ! queue.empty() )
+ {
+ Full_cell_handle s = queue.front();
+ queue.pop();
+ for( int i = 0; i <= cur_dim; ++i )
+ {
+ if( get_visited(s->neighbor(i)) )
+ {
+ set_visited(s->neighbor(i), false);
+ queue.push(s->neighbor(i));
+ }
+ }
+ }
+}
+
+template <class Dim, class Vb, class Fcb>
+void Triangulation_data_structure<Dim, Vb, Fcb>
+::do_insert_increase_dimension(Vertex_handle x, Vertex_handle star)
+{
+ Full_cell_handle start = full_cells_begin();
+ Full_cell_handle swap_me;
+ const int cur_dim = current_dimension();
+ for( Full_cell_iterator S = full_cells_begin(); S != full_cells_end(); ++S )
+ {
+ if( Vertex_handle() != S->vertex(cur_dim) )
+ continue;
+ set_visited(S, true);
+ // extends full_cell |S| to include the new vertex as the
+ // current_dimension()-th vertex
+ associate_vertex_with_full_cell(S, cur_dim, x);
+ if( ! S->has_vertex(star) )
+ { // S is bounded, we create its unbounded "twin" full_cell
+ Full_cell_handle S_new = new_full_cell();
+ set_neighbors(S, cur_dim, S_new, 0);
+ associate_vertex_with_full_cell(S_new, 0, star);
+ // here, we could be clever so as to get consistent orientation
+ for( int k = 1; k <= cur_dim; ++k )
+ associate_vertex_with_full_cell(S_new, k, vertex(S, k - 1));
+ }
+ }
+ // now we setup the neighbors
+ set_visited(start, false);
+ std::queue<Full_cell_handle> queue;
+ queue.push(start);
+ while( ! queue.empty() )
+ {
+ Full_cell_handle S = queue.front();
+ queue.pop();
+ // here, the first visit above ensured that all neighbors exist now.
+ // Now we need to connect them with adjacency relation
+ int star_index;
+ if( S->has_vertex(star, star_index) )
+ {
+ set_neighbors( S, cur_dim, neighbor(neighbor(S, star_index), cur_dim),
+ // this is tricky :-) :
+ mirror_index(S, star_index) + 1);
+ }
+ else
+ {
+ Full_cell_handle S_new = neighbor(S, cur_dim);
+ for( int k = 0 ; k < cur_dim ; ++k )
+ {
+ Full_cell_handle S_opp = neighbor(S, k);
+ if( ! S_opp->has_vertex(star) )
+ set_neighbors(S_new, k + 1, neighbor(S_opp, cur_dim), mirror_index(S, k) + 1);
+ // neighbor of S_new opposite to v is S_new'
+ // the vertex opposite to v remains the same but ...
+ // remember the shifting of the vertices one step to the right
+ }
+ }
+ for( int k = 0 ; k < cur_dim ; ++k )
+ if( get_visited(neighbor(S, k)) )
+ {
+ set_visited(neighbor(S, k), false);
+ queue.push(neighbor(S, k));
+ }
+ }
+ if( ( ( cur_dim % 2 ) == 0 ) && ( cur_dim > 1 ) )
+ {
+ for( Full_cell_iterator S = full_cells_begin(); S != full_cells_end(); ++S )
+ {
+ if( x != S->vertex(cur_dim) )
+ S->swap_vertices(cur_dim - 1, cur_dim);
+ }
+ }
+ if( Full_cell_handle() != swap_me )
+ swap_me->swap_vertices(1, 2);
+}
+
+template <class Dim, class Vb, class Fcb>
+typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle
+Triangulation_data_structure<Dim, Vb, Fcb>
+::insert_increase_dimension(Vertex_handle star) /* Concept */
+{
+ const int prev_cur_dim = current_dimension();
+ CGAL_precondition(prev_cur_dim < maximal_dimension());
+ if( -2 != current_dimension() )
+ {
+ CGAL_precondition( Vertex_handle() != star );
+ CGAL_expensive_precondition(is_vertex(star));
+ }
+
+ set_current_dimension(prev_cur_dim + 1);
+ Vertex_handle v = new_vertex();
+ switch( prev_cur_dim )
+ {
+ case -2:
+ { // insertion of the first vertex
+ // ( geometrically : infinite vertex )
+ Full_cell_handle s = new_full_cell();
+ associate_vertex_with_full_cell(s, 0, v);
+ break;
+ }
+ case -1:
+ { // insertion of the second vertex
+ // ( geometrically : first finite vertex )
+ //we create a triangulation of the 0-sphere, with
+ // vertices |star| and |v|
+ Full_cell_handle infinite_full_cell = star->full_cell();
+ Full_cell_handle finite_full_cell = new_full_cell();
+ associate_vertex_with_full_cell(finite_full_cell, 0, v);
+ set_neighbors(infinite_full_cell, 0, finite_full_cell, 0);
+ break;
+ }
+ default:
+ do_insert_increase_dimension(v, star);
+ break;
+ }
+ return v;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY CHECKS
+
+template <class Dimen, class Vb, class Fcb>
+bool Triangulation_data_structure<Dimen, Vb, Fcb>
+::is_valid(bool verbose, int /* level */) const /* Concept */
+{
+ Full_cell_const_handle s, t;
+ Vertex_const_handle v;
+ int i, j, k;
+
+ if( current_dimension() == -2 )
+ {
+ if( ! vertices_.empty() || ! full_cells_.empty() )
+ {
+ if( verbose ) CGAL_warning_msg(false, "current dimension is -2 but there are vertices or full_cells");
+ return false;
+ }
+ }
+
+ if( current_dimension() == -1 )
+ {
+ if ( (number_of_vertices() != 1) || (number_of_full_cells() != 1) )
+ {
+ if( verbose ) CGAL_warning_msg(false, "current dimension is -1 but there isn't one vertex and one full_cell");
+ return false;
+ }
+ }
+
+ for( v = vertices_begin(); v != vertices_end(); ++v )
+ {
+ if( ! v->is_valid(verbose) )
+ return false;
+ }
+
+ // FUTURE: for each vertex v, gather incident full_cells. then, check that
+ // any full_cell containing v is among those gathered full_cells...
+
+ if( current_dimension() < 0 )
+ return true;
+
+ for( s = full_cells_begin(); s != full_cells_end(); ++s )
+ {
+ if( ! s->is_valid(verbose) )
+ return false;
+ // check that the full cell has no duplicate vertices
+ for( i = 0; i <= current_dimension(); ++i )
+ for( j = i + 1; j <= current_dimension(); ++j )
+ if( vertex(s,i) == vertex(s,j) )
+ {
+ CGAL_warning_msg(false, "a full_cell has two equal vertices");
+ return false;
+ }
+ }
+
+ for( s = full_cells_begin(); s != full_cells_end(); ++s )
+ {
+ for( i = 0; i <= current_dimension(); ++i )
+ if( (t = neighbor(s,i)) != Full_cell_const_handle() )
+ {
+ int l = mirror_index(s,i);
+ if( s != neighbor(t,l) || i != mirror_index(t,l) )
+ {
+ if( verbose ) CGAL_warning_msg(false, "neighbor relation is not symmetric");
+ return false;
+ }
+ for( j = 0; j <= current_dimension(); ++j )
+ if( j != i )
+ {
+ // j must also occur as a vertex of t
+ for( k = 0; k <= current_dimension() && ( vertex(s,j) != vertex(t,k) || k == l); ++k )
+ ;
+ if( k > current_dimension() )
+ {
+ if( verbose ) CGAL_warning_msg(false, "too few shared vertices between neighbors full_cells.");
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if( verbose ) CGAL_warning_msg(false, "full_cell has a NULL neighbor");
+ return false;
+ }
+ }
+ return true;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// - - - - - - - - - - - - - - - - - - - - - - - - INPUT / OUTPUT
+
+// NOT DOCUMENTED
+template <class Dim, class Vb, class Fcb>
+template <class OutStream>
+void Triangulation_data_structure<Dim, Vb, Fcb>
+::write_graph(OutStream & os)
+{
+ std::vector<std::set<int> > edges;
+ os << number_of_vertices() + 1; // add the vertex at infinity
+ int count(1);
+ for( Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit )
+ vit->idx_ = count++;
+ edges.resize(number_of_vertices()+1);
+ for( Full_cell_iterator sit = full_cells_begin(); sit != full_cells_end(); ++sit )
+ {
+ int v1 = 0;
+ while( v1 < current_dimension() )
+ {
+ int v2 = v1 + 1;
+ while( v2 <= current_dimension() )
+ {
+ int i1, i2;
+ if( Vertex_handle() != sit-> vertex(v1) )
+ i1 = sit->vertex(v1)->idx_;
+ else
+ i1 = 0;
+ if( Vertex_handle() != sit-> vertex(v2) )
+ i2 = sit->vertex(v2)->idx_;
+ else
+ i2 = 0;
+ edges[i1].insert(i2);
+ edges[i2].insert(i1);
+ ++v2;
+ }
+ ++v1;
+ }
+ }
+ for( std::size_t i = 0; i < edges.size(); ++i )
+ {
+ os << std::endl << edges[i].size();
+ for( std::set<int>::const_iterator nit = edges[i].begin();
+ nit != edges[i].end(); ++nit )
+ {
+ os << ' ' << (*nit);
+ }
+ }
+}
+
+// NOT DOCUMENTED...
+template<class Dimen, class Vb, class Fcb>
+std::istream &
+Triangulation_data_structure<Dimen, Vb, Fcb>
+::read_full_cells(std::istream & is, const std::vector<Vertex_handle> & vertices)
+{
+ std::size_t m; // number of full_cells
+ int index;
+ const int cd = current_dimension();
+ if( is_ascii(is) )
+ is >> m;
+ else
+ read(is, m, io_Read_write());
+
+ std::vector<Full_cell_handle> full_cells;
+ full_cells.reserve(m);
+ // read the vertices of each full_cell
+ std::size_t i = 0;
+ while( i < m )
+ {
+ Full_cell_handle s = new_full_cell();
+ full_cells.push_back(s);
+ for( int j = 0; j <= cd; ++j )
+ {
+ if( is_ascii(is) )
+ is >> index;
+ else
+ read(is, index);
+ s->set_vertex(j, vertices[index]);
+ }
+ // read other non-combinatorial information for the full_cells
+ is >> (*s);
+ ++i;
+ }
+
+ // read the neighbors of each full_cell
+ i = 0;
+ if( is_ascii(is) )
+ while( i < m )
+ {
+ for( int j = 0; j <= cd; ++j )
+ {
+ is >> index;
+ full_cells[i]->set_neighbor(j, full_cells[index]);
+ }
+ ++i;
+ }
+ else
+ while( i < m )
+ {
+ for( int j = 0; j <= cd; ++j )
+ {
+ read(is, index);
+ full_cells[i]->set_neighbor(j, full_cells[index]);
+ }
+ ++i;
+ }
+
+ // compute the mirror indices
+ for( i = 0; i < m; ++i )
+ {
+ Full_cell_handle s = full_cells[i];
+ for( int j = 0; j <= cd; ++j )
+ {
+ if( -1 != s->mirror_index(j) )
+ continue;
+ Full_cell_handle n = s->neighbor(j);
+ int k = 0;
+ Full_cell_handle nn = n->neighbor(k);
+ while( s != nn )
+ nn = n->neighbor(++k);
+ s->set_mirror_index(j,k);
+ n->set_mirror_index(k,j);
+ }
+ }
+ return is;
+}
+
+// NOT DOCUMENTED...
+template<class Dimen, class Vb, class Fcb>
+std::ostream &
+Triangulation_data_structure<Dimen, Vb, Fcb>
+::write_full_cells(std::ostream & os, std::map<Vertex_const_handle, int> & index_of_vertex) const
+{
+ std::map<Full_cell_const_handle, int> index_of_full_cell;
+
+ std::size_t m = number_of_full_cells();
+
+ if( is_ascii(os) )
+ os << std::endl << m;
+ else
+ write(os, m, io_Read_write());
+
+ const int cur_dim = current_dimension();
+ // write the vertex indices of each full_cell
+ int i = 0;
+ for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it )
+ {
+ index_of_full_cell[it] = i++;
+ if( is_ascii(os) )
+ os << std::endl;
+ for( int j = 0; j <= cur_dim; ++j )
+ {
+ if( is_ascii(os) )
+ os << ' ' << index_of_vertex[it->vertex(j)];
+ else
+ write(os, index_of_vertex[it->vertex(j)]);
+ }
+ // write other non-combinatorial information for the full_cells
+ os << (*it);
+ }
+
+ CGAL_assertion( (std::size_t) i == m );
+
+ // write the neighbors of each full_cell
+ if( is_ascii(os) )
+ for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it )
+ {
+ os << std::endl;
+ for( int j = 0; j <= cur_dim; ++j )
+ os << ' ' << index_of_full_cell[it->neighbor(j)];
+ }
+ else
+ for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it )
+ {
+ for( int j = 0; j <= cur_dim; ++j )
+ write(os, index_of_full_cell[it->neighbor(j)]);
+ }
+
+ return os;
+}
+
+// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+
+// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS:
+
+template<class Dimen, class Vb, class Fcb>
+std::istream &
+operator>>(std::istream & is, Triangulation_data_structure<Dimen, Vb, Fcb> & tr)
+ // reads :
+ // - the dimensions (maximal and current)
+ // - the number of finite vertices
+ // - the non combinatorial information on vertices (point, etc)
+ // - the number of full_cells
+ // - the full_cells by the indices of their vertices in the preceding list
+ // of vertices, plus the non combinatorial information on each full_cell
+ // - the neighbors of each full_cell by their index in the preceding list
+{
+ typedef Triangulation_data_structure<Dimen, Vb, Fcb> TDS;
+ typedef typename TDS::Vertex_handle Vertex_handle;
+
+ // read current dimension and number of vertices
+ std::size_t n;
+ int cd;
+ if( is_ascii(is) )
+ is >> cd >> n;
+ else
+ {
+ read(is, cd);
+ read(is, n, io_Read_write());
+ }
+
+ CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation_data_structure has too high dimension");
+
+ tr.clear();
+ tr.set_current_dimension(cd);
+
+ if( n == 0 )
+ return is;
+
+ std::vector<Vertex_handle> vertices;
+ vertices.resize(n);
+
+ // read the vertices:
+ std::size_t i(0);
+ while( i < n )
+ {
+ vertices[i] = tr.new_vertex();
+ is >> (*vertices[i]); // read a vertex
+ ++i;
+ }
+
+ // now, read the combinatorial information
+ return tr.read_full_cells(is, vertices);
+}
+
+template<class Dimen, class Vb, class Fcb>
+std::ostream &
+operator<<(std::ostream & os, const Triangulation_data_structure<Dimen, Vb, Fcb> & tr)
+ // writes :
+ // - the dimensions (maximal and current)
+ // - the number of finite vertices
+ // - the non combinatorial information on vertices (point, etc)
+ // - the number of full cells
+ // - the full cells by the indices of their vertices in the preceding list
+ // of vertices, plus the non combinatorial information on each full_cell
+ // - the neighbors of each full_cell by their index in the preceding list
+{
+ typedef Triangulation_data_structure<Dimen, Vb, Fcb> TDS;
+ typedef typename TDS::Vertex_const_handle Vertex_handle;
+ typedef typename TDS::Vertex_const_iterator Vertex_iterator;
+
+ // outputs dimension and number of vertices
+ std::size_t n = tr.number_of_vertices();
+ if( is_ascii(os) )
+ os << tr.current_dimension() << std::endl << n;
+ else
+ {
+ write(os, tr.current_dimension());
+ write(os, n, io_Read_write());
+ }
+
+ if( n == 0 )
+ return os;
+
+ // write the vertices
+ std::map<Vertex_handle, int> index_of_vertex;
+ int i = 0;
+ for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it, ++i )
+ {
+ os << *it; // write the vertex
+ if (is_ascii(os))
+ os << std::endl;
+ index_of_vertex[it] = i;
+ }
+ CGAL_assertion( (std::size_t) i == n );
+
+ // output the combinatorial information
+ return tr.write_full_cells(os, index_of_vertex);
+}
+
+} //namespace CGAL
+
+#endif // CGAL_TRIANGULATION_DATA_STRUCTURE_H
diff --git a/include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h b/include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h
new file mode 100644
index 00000000..541a6a85
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h
@@ -0,0 +1,311 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_TRIANGULATION_DS_FULL_CELL_H
+#define CGAL_TRIANGULATION_DS_FULL_CELL_H
+
+#include <CGAL/TDS_full_cell_default_storage_policy.h>
+#include <CGAL/TDS_full_cell_mirror_storage_policy.h>
+#include <CGAL/internal/Triangulation/Dummy_TDS.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/Default.h>
+#include <CGAL/array.h>
+
+namespace CGAL {
+
+template< class TDS = void, typename FullCellStoragePolicy = Default >
+class Triangulation_ds_full_cell
+{
+ typedef typename Default::Get<FullCellStoragePolicy, TDS_full_cell_default_storage_policy>::type
+ Storage_policy;
+ typedef Triangulation_ds_full_cell<TDS> Self;
+ typedef typename TDS::Maximal_dimension Maximal_dimension;
+
+public:
+ typedef TDS Triangulation_data_structure;
+ typedef typename TDS::Face Face;
+ typedef typename TDS::Vertex_handle Vertex_handle; /* Concept */
+ typedef typename TDS::Vertex_const_handle Vertex_const_handle;
+ typedef typename TDS::Full_cell_handle Full_cell_handle; /* Concept */
+ typedef typename TDS::Full_cell_const_handle Full_cell_const_handle;
+ typedef typename TDS::Full_cell_data TDS_data; /* data that the TDS wants to be stored here */
+ template< typename TDS2 >
+ struct Rebind_TDS /* Concept */
+ {
+ typedef Triangulation_ds_full_cell<TDS2, FullCellStoragePolicy> Other;
+ };
+
+private: // STORAGE
+ typedef TFC_data< Vertex_handle, Full_cell_handle,
+ Maximal_dimension, Storage_policy > Combinatorics;
+ friend struct TFC_data< Vertex_handle, Full_cell_handle,
+ Maximal_dimension, Storage_policy >;
+ // array of vertices
+ typedef typename Combinatorics::Vertex_handle_array Vertex_handle_array;
+ // neighbor simplices
+ typedef typename Combinatorics::Full_cell_handle_array Full_cell_handle_array;
+
+ // NOT DOCUMENTED...
+ typename Combinatorics::Xor_type xor_of_vertices(const int cur_dim) const
+ {
+ return combinatorics_.xor_of_vertices(cur_dim);
+ }
+
+public:
+ typedef typename Vertex_handle_array::const_iterator Vertex_handle_const_iterator;
+ typedef Vertex_handle_const_iterator Vertex_handle_iterator; /* Concept */
+
+ Triangulation_ds_full_cell(const int dmax) /* Concept */
+ : combinatorics_(dmax), tds_data_()
+ {
+ CGAL_assertion( dmax > 0 );
+ for( int i = 0; i <= dmax; ++i )
+ {
+ set_neighbor(i, Full_cell_handle());
+ set_vertex(i, Vertex_handle());
+ set_mirror_index(i, -1);
+ }
+ }
+
+ Triangulation_ds_full_cell(const Triangulation_ds_full_cell & s) /* Concept */
+ : combinatorics_(s.combinatorics_), tds_data_(s.tds_data_)
+ {}
+
+ ~Triangulation_ds_full_cell() {}
+
+ int maximal_dimension() const /* Concept */
+ {
+ return static_cast<int>(vertices().size() - 1);
+ }
+
+ Vertex_handle_const_iterator vertices_begin() const /* Concept */
+ {
+ return vertices().begin();
+ }
+
+ Vertex_handle_const_iterator vertices_end() const /* Concept */
+ {
+ return vertices().end();
+ }
+
+ Vertex_handle vertex(const int i) const /* Concept */
+ {
+ CGAL_precondition(0<=i && i<=maximal_dimension());
+ return vertices()[i];
+ }
+
+ Full_cell_handle neighbor(const int i) const /* Concept */
+ {
+ CGAL_precondition(0<=i && i<=maximal_dimension());
+ return neighbors()[i];
+ }
+
+ int mirror_index(const int i) const /* Concept */
+ {
+ CGAL_precondition(0<=i && i<=maximal_dimension());
+ return combinatorics_.mirror_index(i);
+ }
+
+ // Advanced...
+ Vertex_handle mirror_vertex(const int i, const int cur_dim) const /* Concept */
+ {
+ CGAL_precondition(0<=i && i<=maximal_dimension());
+ return combinatorics_.mirror_vertex(i, cur_dim);
+ }
+
+ int index(Full_cell_const_handle s) const /* Concept */
+ {
+ // WE ASSUME THE FULL CELL WE ARE LOOKING FOR INDEED EXISTS !
+ CGAL_precondition(has_neighbor(s));
+ int index(0);
+ while( neighbor(index) != s )
+ ++index;
+ return index;
+ }
+
+ int index(Vertex_const_handle v) const /* Concept */
+ {
+ // WE ASSUME THE VERTEX WE ARE LOOKING FOR INDEED EXISTS !
+ CGAL_precondition(has_vertex(v));
+ int index(0);
+ while( vertex(index) != v )
+ ++index;
+ return index;
+ }
+
+ void set_vertex(const int i, Vertex_handle v) /* Concept */
+ {
+ CGAL_precondition(0<=i && i<=maximal_dimension());
+ vertices()[i] = v;
+ }
+
+ void set_neighbor(const int i, Full_cell_handle s) /* Concept */
+ {
+ CGAL_precondition(0<=i && i<=maximal_dimension());
+ neighbors()[i] = s;
+ }
+
+ void set_mirror_index(const int i, const int index) /* Concept */
+ {
+ CGAL_precondition(0<=i && i<=maximal_dimension());
+ combinatorics_.set_mirror_index(i, index);
+ }
+
+ bool has_vertex(Vertex_const_handle v) const /* Concept */
+ {
+ int index;
+ return has_vertex(v, index);
+ }
+
+ bool has_vertex(Vertex_const_handle v, int & index) const /* Concept */
+ {
+ const int d = maximal_dimension();
+ index = 0;
+ while( (index <= d) && (vertex(index) != v) )
+ ++index;
+ return (index <= d);
+ }
+
+ bool has_neighbor(Full_cell_const_handle s) const /* Concept */
+ {
+ int index;
+ return has_neighbor(s, index);
+ }
+
+ bool has_neighbor(Full_cell_const_handle s, int & index) const /* Concept */
+ {
+ const int d = maximal_dimension();
+ index = 0;
+ while( (index <= d) && (neighbor(index) != s) )
+ ++index;
+ return (index <= d);
+ }
+
+ void swap_vertices(const int d1, const int d2) /* Concept */
+ {
+ CGAL_precondition(0 <= d1 && d1<=maximal_dimension());
+ CGAL_precondition(0 <= d2 && d2<=maximal_dimension());
+ combinatorics_.swap_vertices(d1, d2);
+ }
+
+ const TDS_data & tds_data() const { return tds_data_; } /* Concept */
+ TDS_data & tds_data() { return tds_data_; } /* Concept */
+
+ void* for_compact_container() const { return combinatorics_.for_compact_container(); }
+ void* & for_compact_container() { return combinatorics_.for_compact_container(); }
+
+ bool is_valid(bool verbose = false, int = 0) const /* Concept */
+ {
+ const int d = maximal_dimension();
+ int i(0);
+ // test that the non-null Vertex_handles come first, before all null ones
+ while( i <= d && vertex(i) != Vertex_handle() ) ++i;
+ while( i <= d && vertex(i) == Vertex_handle() ) ++i;
+ if( i <= d )
+ {
+ if( verbose ) CGAL_warning_msg(false, "full cell has garbage handles to vertices.");
+ return false;
+ }
+ for( i = 0; i <= d; ++i )
+ {
+ if( Vertex_handle() == vertex(i) )
+ break; // there are no more vertices
+ Full_cell_handle n(neighbor(i));
+ if( Full_cell_handle() != n )
+ {
+ int mirror_idx(mirror_index(i));
+ if( n->neighbor(mirror_idx) == Full_cell_handle() )
+ {
+ if( verbose ) CGAL_warning_msg(false, "neighbor has no back-neighbor.");
+ return false;
+ }
+ if( &(*(n->neighbor(mirror_idx))) != this )
+ {
+ if( verbose ) CGAL_warning_msg(false, "neighbor does not point back to correct full cell.");
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+private:
+ // access to data members:
+ Full_cell_handle_array & neighbors() {return combinatorics_.neighbors_; }
+ const Full_cell_handle_array & neighbors() const {return combinatorics_.neighbors_; }
+ Vertex_handle_array & vertices() {return combinatorics_.vertices_; }
+ const Vertex_handle_array & vertices() const {return combinatorics_.vertices_; }
+
+ // DATA MEMBERS
+ Combinatorics combinatorics_;
+ mutable TDS_data tds_data_;
+};
+
+// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS:
+
+template < typename TDS, typename SSP >
+std::ostream &
+operator<<(std::ostream & O, const Triangulation_ds_full_cell<TDS,SSP> &) /* Concept */
+{
+ /*if( is_ascii(O) )
+ {
+ // os << '\n';
+ }
+ else {}*/
+ return O;
+}
+
+template < typename TDS, typename SSP >
+std::istream &
+operator>>(std::istream & I, Triangulation_ds_full_cell<TDS,SSP> &) /* Concept */
+{
+ /*if( is_ascii(I) )
+ {}
+ else {}*/
+ return I;
+}
+
+// Special case: specialization when template parameter is void.
+
+// we must declare it for each possible full_cell storage policy because :
+// (GCC error:) default template arguments may not be used in partial specializations
+template< typename StoragePolicy >
+class Triangulation_ds_full_cell<void, StoragePolicy>
+{
+public:
+ typedef internal::Triangulation::Dummy_TDS TDS;
+ typedef TDS Triangulation_data_structure;
+ typedef TDS::Vertex_handle Vertex_handle;
+ typedef TDS::Vertex_const_handle Vertex_const_handle;
+ typedef TDS::Full_cell_handle Full_cell_handle;
+ typedef TDS::Full_cell_const_handle Full_cell_const_handle;
+ typedef TDS::Vertex_handle_const_iterator Vertex_handle_const_iterator;
+ typedef TDS::Full_cell_data TDS_data;
+ template <typename TDS2>
+ struct Rebind_TDS
+ {
+ typedef Triangulation_ds_full_cell<TDS2, StoragePolicy> Other;
+ };
+ Vertex_handle_const_iterator vertices_begin();
+ Vertex_handle_const_iterator vertices_end();
+};
+
+} //namespace CGAL
+
+#endif // CGAL_TRIANGULATION_DS_FULL_CELL_H
diff --git a/include/gudhi_patches/CGAL/Triangulation_ds_vertex.h b/include/gudhi_patches/CGAL/Triangulation_ds_vertex.h
new file mode 100644
index 00000000..381b97e1
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Triangulation_ds_vertex.h
@@ -0,0 +1,154 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_TRIANGULATION_DS_VERTEX_H
+#define CGAL_TRIANGULATION_DS_VERTEX_H
+
+#include <CGAL/Compact_container.h>
+#include <CGAL/internal/Triangulation/Dummy_TDS.h>
+
+namespace CGAL {
+
+/* The template parameter TDS must be a model of the concept
+ * 'TriangulationDataStructure' that stores vertices of type
+ * 'Triangulation_ds_vertex<TDS>'
+ */
+template< class TDS = void >
+class Triangulation_ds_vertex
+{
+ typedef Triangulation_ds_vertex<TDS> Self;
+
+public:
+ typedef TDS Triangulation_data_structure;
+ typedef typename TDS::Full_cell_handle Full_cell_handle; /* Concept */
+
+ template <typename TDS2>
+ struct Rebind_TDS /* Concept */
+ {
+ typedef Triangulation_ds_vertex<TDS2> Other;
+ };
+
+protected: // DATA MEMBERS
+ Full_cell_handle full_cell_; // A handle to an incident full_cell
+
+public:
+ // Constructs a vertex with incident full_cell 's'
+ Triangulation_ds_vertex(Full_cell_handle s) : full_cell_(s) /* Concept */
+ {
+ CGAL_assertion( Full_cell_handle() != s );
+ }
+ // Constructs a vertex with no incident full_cell
+ Triangulation_ds_vertex() : full_cell_() {} /* Concept */
+
+ ~Triangulation_ds_vertex() {}
+
+ /// Set 's' as an incident full_cell
+ void set_full_cell(Full_cell_handle s) /* Concept */
+ {
+ full_cell_ = s;
+ }
+
+ /// Returns a full_cell incident to the vertex
+ Full_cell_handle full_cell() const /* Concept */
+ {
+ return full_cell_;
+ }
+
+ bool is_valid(bool verbose = false, int /* level */ = 0) const /* Concept */
+ {
+ if( Full_cell_handle() == full_cell() )
+ {
+ if( verbose )
+ CGAL_warning_msg(false, "vertex has no incident full cell.");
+ return false;
+ }
+ bool found(false);
+ // These two typename below are OK because TDS fullfils the
+ // TriangulationDataStructure concept.
+ typename TDS::Full_cell::Vertex_handle_iterator vit(full_cell()->vertices_begin());
+ typedef typename TDS::Vertex_handle Vertex_handle;
+ while( vit != full_cell()->vertices_end() )
+ {
+ if( Vertex_handle() == *vit )
+ break; // The full cell has no more vertices
+ if( this == &(**vit) )
+ {
+ found = true;
+ break;
+ }
+ ++vit;
+ }
+ if( ! found )
+ {
+ if( verbose )
+ CGAL_warning_msg(false, "vertex's adjacent full cell does not contain that vertex.");
+ return false;
+ }
+ return true;
+ }
+
+public: // FOR MEMORY MANAGEMENT
+
+ void* for_compact_container() const { return full_cell_.for_compact_container(); }
+ void* & for_compact_container() { return full_cell_.for_compact_container(); }
+
+}; // end of Triangulation_ds_vertex
+
+// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS:
+
+template < class TDS >
+std::istream &
+operator>>(std::istream & is, Triangulation_ds_vertex<TDS> &) /* Concept */
+{
+ /*if( is_ascii(is) )
+ {}
+ else {}*/
+ return is;
+}
+
+template< class TDS >
+std::ostream &
+operator<<(std::ostream & os, const Triangulation_ds_vertex<TDS> &) /* Concept */
+{
+ /*if( is_ascii(os) )
+ {
+ os << '\n';
+ }
+ else {}*/
+ return os;
+}
+
+// Special case: specialization when template parameter is void.
+
+template<>
+class Triangulation_ds_vertex<void>
+{
+public:
+ typedef internal::Triangulation::Dummy_TDS Triangulation_data_structure;
+ typedef Triangulation_data_structure::Full_cell_handle Full_cell_handle; /* Concept */
+ template <typename TDS2>
+ struct Rebind_TDS /* Concept */
+ {
+ typedef Triangulation_ds_vertex<TDS2> Other;
+ };
+};
+
+} //namespace CGAL
+
+#endif // CGAL_TRIANGULATION_DS_VERTEX_H
diff --git a/include/gudhi_patches/CGAL/Triangulation_face.h b/include/gudhi_patches/CGAL/Triangulation_face.h
new file mode 100644
index 00000000..bc9c1781
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Triangulation_face.h
@@ -0,0 +1,111 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_TRIANGULATION_FACE_H
+#define CGAL_TRIANGULATION_FACE_H
+
+#include <CGAL/basic.h>
+#include <CGAL/internal/Static_or_dynamic_array.h>
+
+namespace CGAL {
+
+template< typename TDS >
+class Triangulation_face
+{
+ typedef typename internal::Dimen_plus_one<typename TDS::Maximal_dimension>::type Dimen_plus;
+public:
+ typedef TDS Triangulation_data_structure;
+ typedef typename TDS::Full_cell_handle Full_cell_handle; /* Concept */
+ typedef typename TDS::Vertex_handle Vertex_handle; /* Concept */
+ typedef internal::S_or_D_array<int, Dimen_plus> Indices;
+
+protected:
+ Full_cell_handle full_cell_;
+ Indices indices_;
+
+public:
+ explicit Triangulation_face(Full_cell_handle s) /* Concept */
+ : full_cell_(s), indices_(s->maximal_dimension()+2)
+ {
+ CGAL_assertion( Full_cell_handle() != s );
+ clear();
+ }
+
+ explicit Triangulation_face(const int maximal_dim) /* Concept */
+ : full_cell_(), indices_(maximal_dim+2)
+ {
+ clear();
+ }
+
+ Triangulation_face(const Triangulation_face & f) /* Concept */
+ : full_cell_(f.full_cell_), indices_(f.indices_)
+ {}
+
+ int face_dimension() const /* Concept */
+ {
+ int i(0);
+ while( -1 != indices_[i] ) ++i;
+ return (i-1);
+ }
+
+ Full_cell_handle full_cell() const /* Concept */
+ {
+ return full_cell_;
+ }
+
+ int index(const int i) const /* Concept */
+ {
+ CGAL_precondition( (0 <= i) && (i <= face_dimension()) );
+ return indices_[i];
+ }
+
+ Vertex_handle vertex(const int i) const /* Concept */
+ {
+ int j = index(i);
+ if( j == -1 )
+ return Vertex_handle();
+ return full_cell()->vertex(j);
+ }
+
+// - - - - - - - - - - - - - - - - - - UPDATE FUNCTIONS
+
+ void clear() /* Concept */
+ {
+ const std::size_t d = indices_.size();
+ for(std::size_t i = 0; i < d; ++i )
+ indices_[i] = -1;
+ }
+
+ void set_full_cell(Full_cell_handle s) /* Concept */
+ {
+ CGAL_precondition( Full_cell_handle() != s );
+ full_cell_ = s;
+ }
+
+ void set_index(const int i, const int idx) /* Concept */
+ {
+ CGAL_precondition( (0 <= i) && ((size_t)i+1 < indices_.size()) );
+ CGAL_precondition( (0 <= idx) && ((size_t)idx < indices_.size()) );
+ indices_[i] = idx;
+ }
+};
+
+} //namespace CGAL
+
+#endif // CGAL_TRIANGULATION_FACE_H
diff --git a/include/gudhi_patches/CGAL/Triangulation_full_cell.h b/include/gudhi_patches/CGAL/Triangulation_full_cell.h
new file mode 100644
index 00000000..a0c5246f
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Triangulation_full_cell.h
@@ -0,0 +1,148 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_TRIANGULATION_SIMPLEX_H
+#define CGAL_TRIANGULATION_SIMPLEX_H
+
+#include <CGAL/Triangulation_ds_full_cell.h>
+#include <CGAL/internal/Triangulation/utilities.h>
+#include <CGAL/Iterator_project.h>
+#include <CGAL/Default.h>
+
+namespace CGAL {
+
+struct No_full_cell_data {};
+
+template< class TriangulationTraits, typename Data_ = No_full_cell_data, class TDSFullCell = Default >
+class Triangulation_full_cell : public Default::Get<TDSFullCell, Triangulation_ds_full_cell<> >::type
+{
+ // The default type for TDSFullCell is Triangulation_ds_full_cell<> :
+ typedef typename Default::Get<TDSFullCell, Triangulation_ds_full_cell<> >::type
+ Base;
+ typedef Triangulation_full_cell<TriangulationTraits, Data_, TDSFullCell> Self;
+public:
+ typedef Data_ Data;
+ typedef typename Base::Vertex_handle Vertex_handle;
+ typedef typename Base::Vertex_const_handle Vertex_const_handle;
+ typedef typename Base::Vertex_handle_const_iterator Vertex_handle_const_iterator;
+ typedef typename Base::Full_cell_const_handle Full_cell_const_handle;
+ typedef typename TriangulationTraits::Point_d Point;
+ typedef typename TriangulationTraits::Point_d Point_d;
+
+private: // DATA MEMBERS
+ Data data_;
+
+public:
+
+ using Base::vertices_begin;
+ using Base::vertices_end;
+
+ template< class TDS2 >
+ struct Rebind_TDS
+ {
+ typedef typename Base::template Rebind_TDS<TDS2>::Other TDSFullCell2;
+ typedef Triangulation_full_cell<TriangulationTraits, Data_, TDSFullCell2> Other;
+ };
+
+ Triangulation_full_cell(const int d)
+ : Base(d), data_() {}
+
+ Triangulation_full_cell(const Self & s)
+ : Base(s), data_(s.data_) {}
+
+ const Data & data() const
+ {
+ return data_;
+ }
+
+ Data & data()
+ {
+ return data_;
+ }
+
+ struct Point_from_vertex_handle
+ {
+ typedef Vertex_handle argument_type;
+ typedef Point result_type;
+ result_type & operator()(argument_type & x) const
+ {
+ return x->point();
+ }
+ const result_type & operator()(const argument_type & x) const
+ {
+ return x->point();
+ }
+ };
+
+protected:
+
+ typedef CGAL::Iterator_project<
+ Vertex_handle_const_iterator,
+ internal::Triangulation::Point_from_vertex_handle<Vertex_handle, Point>
+ > Point_const_iterator;
+
+ Point_const_iterator points_begin() const
+ { return Point_const_iterator(Base::vertices_begin()); }
+ Point_const_iterator points_end() const
+ { return Point_const_iterator(Base::vertices_end()); }
+};
+
+// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS:
+
+inline
+std::istream &
+operator>>(std::istream & is, No_full_cell_data &)
+{
+ return is;
+}
+
+inline
+std::ostream &
+operator<<(std::ostream & os, const No_full_cell_data &)
+{
+ return os;
+}
+
+template < typename TDS, typename Data, typename SSP >
+std::ostream &
+operator<<(std::ostream & O, const Triangulation_full_cell<TDS, Data, SSP> & s)
+{
+ /*if( is_ascii(O) )
+ {
+ // os << '\n';
+ }
+ else {}*/
+ O << s.data();
+ return O;
+}
+
+template < typename TDS, typename Data, typename SSP >
+std::istream &
+operator>>(std::istream & I, Triangulation_full_cell<TDS, Data, SSP> & s)
+{
+ /*if( is_ascii(I) )
+ {}
+ else {}*/
+ I >> s.data();
+ return I;
+}
+
+} //namespace CGAL
+
+#endif // CGAL_TRIANGULATION_SIMPLEX_H
diff --git a/include/gudhi_patches/CGAL/Triangulation_vertex.h b/include/gudhi_patches/CGAL/Triangulation_vertex.h
new file mode 100644
index 00000000..f364717f
--- /dev/null
+++ b/include/gudhi_patches/CGAL/Triangulation_vertex.h
@@ -0,0 +1,128 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_TRIANGULATION_VERTEX_H
+#define CGAL_TRIANGULATION_VERTEX_H
+
+#include <CGAL/Triangulation_ds_vertex.h>
+#include <CGAL/Default.h>
+
+namespace CGAL {
+
+struct No_vertex_data {};
+
+template< class TriangulationTraits, typename Data_ = No_vertex_data, class TDSVertex = Default >
+class Triangulation_vertex : public Default::Get<TDSVertex, Triangulation_ds_vertex<> >::type
+{
+ // The default type for TDSVertex is Triangulation_ds_vertex<> :
+ typedef typename Default::Get<TDSVertex, Triangulation_ds_vertex<> >::type
+ Base;
+ typedef Triangulation_vertex<TriangulationTraits, Data_, TDSVertex> Self;
+public:
+ typedef Data_ Data;
+ typedef typename TriangulationTraits::Point_d Point;
+ typedef typename TriangulationTraits::Point_d Point_d;
+ typedef typename Base::Full_cell_handle Full_cell_handle;
+
+ template <typename TDS2>
+ struct Rebind_TDS
+ {
+ typedef typename Base::template Rebind_TDS<TDS2>::Other TDSVertex2;
+ typedef Triangulation_vertex<TriangulationTraits, Data_, TDSVertex2> Other;
+ };
+
+private: // DATA MEMBERS
+ Point point_;
+ Data data_;
+
+public:
+ template< typename T >
+ Triangulation_vertex(Full_cell_handle s, const Point & p, const T & t)
+ : Base(s), point_(p), data_(t) {}
+ Triangulation_vertex(Full_cell_handle s, const Point & p)
+ : Base(s), point_(p), data_() {}
+ template< typename T >
+ Triangulation_vertex(const Point & p, const T & t)
+ : Base(), point_(p), data_(t) {}
+ Triangulation_vertex(const Point & p)
+ : Base(), point_(p), data_() {}
+ Triangulation_vertex() : Base(), point_(), data_() {}
+
+ ~Triangulation_vertex() {}
+
+ /// Set the position in space of the vertex to 'p'
+ void set_point(const Point & p)
+ {
+ point_ = p;
+ }
+
+ /// Returns the position in space of the vertex
+ const Point & point() const
+ {
+ return point_;
+ }
+
+ const Data & data() const
+ {
+ return data_;
+ }
+
+ Data & data()
+ {
+ return data_;
+ }
+
+}; // end of Triangulation_vertex
+
+// NON CLASS-MEMBER FUNCTIONS
+
+inline
+std::istream &
+operator>>(std::istream & is, No_vertex_data &)
+{
+ return is;
+}
+
+inline
+std::ostream &
+operator<<(std::ostream & os, const No_vertex_data &)
+{
+ return os;
+}
+
+template < class A, typename Data, class B >
+std::istream &
+operator>>(std::istream & is, Triangulation_vertex<A, Data, B> & v)
+{
+ is >> v.point();
+ return (is >> v.data());
+}
+
+template< class A, typename Data, class B >
+std::ostream &
+operator<<(std::ostream & os, const Triangulation_vertex<A, Data, B> & v)
+{
+ os << v.point();
+ os << v.data();
+ return os;
+}
+
+} //namespace CGAL
+
+#endif // CGAL_TRIANGULATION_VERTEX_H
diff --git a/include/gudhi_patches/CGAL/argument_swaps.h b/include/gudhi_patches/CGAL/argument_swaps.h
new file mode 100644
index 00000000..aa16f29b
--- /dev/null
+++ b/include/gudhi_patches/CGAL/argument_swaps.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_ARGUMENT_SWAPS_H
+#define CGAL_ARGUMENT_SWAPS_H
+
+#include <CGAL/config.h>
+#include <utility>
+
+#ifndef CGAL_CXX11
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/utility/result_of.hpp>
+#endif
+
+namespace CGAL {
+
+#ifdef CGAL_CXX11
+
+namespace internal {
+
+template<int,class...> struct Apply_to_last_then_rest_;
+
+template<int d,class F,class T,class... U>
+struct Apply_to_last_then_rest_<d,F,T,U...> {
+ typedef typename Apply_to_last_then_rest_<d-1,F,U...,T>::result_type result_type;
+ inline result_type operator()(F&&f,T&&t,U&&...u)const{
+ return Apply_to_last_then_rest_<d-1,F,U...,T>()(
+ std::forward<F>(f),
+ std::forward<U>(u)...,
+ std::forward<T>(t));
+ }
+};
+
+template<class F,class T,class... U>
+struct Apply_to_last_then_rest_<0,F,T,U...> {
+ typedef decltype(std::declval<F>()(std::declval<T>(), std::declval<U>()...)) result_type;
+ inline result_type operator()(F&&f,T&&t,U&&...u)const{
+ return std::forward<F>(f)(std::forward<T>(t), std::forward<U>(u)...);
+ }
+};
+
+} // namespace internal
+
+
+struct Apply_to_last_then_rest {
+ template<class F,class T,class...U> inline
+ typename internal::Apply_to_last_then_rest_<sizeof...(U),F,T,U...>::result_type
+ operator()(F&&f,T&&t,U&&...u)const{
+ return internal::Apply_to_last_then_rest_<sizeof...(U),F,T,U...>()(
+ std::forward<F>(f),
+ std::forward<T>(t),
+ std::forward<U>(u)...);
+ }
+};
+
+#else // CGAL_CXX11
+
+struct Apply_to_last_then_rest {
+#define CGAL_CODE(Z,N,_) template<class F,class T,BOOST_PP_ENUM_PARAMS(N,class T)> \
+ typename boost::result_of<F(T,BOOST_PP_ENUM_PARAMS(N,T))>::type \
+ operator()(F const&f, BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t), T const&t) const { \
+ return f(t,BOOST_PP_ENUM_PARAMS(N,t)); \
+ }
+ BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_)
+#undef CGAL_CODE
+};
+
+#endif // CGAL_CXX11
+
+} // namespace CGAL
+
+#endif // CGAL_ARGUMENT_SWAPS_H
diff --git a/include/gudhi_patches/CGAL/determinant_of_vectors.h b/include/gudhi_patches/CGAL/determinant_of_vectors.h
new file mode 100644
index 00000000..e1bad64e
--- /dev/null
+++ b/include/gudhi_patches/CGAL/determinant_of_vectors.h
@@ -0,0 +1,117 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_DETVEC_H
+#define CGAL_DETVEC_H
+#include <CGAL/determinant.h>
+#include <CGAL/predicates/sign_of_determinant.h>
+
+namespace CGAL {
+ // TODO: determine whether it is better to pass them by lines or columns.
+
+ template <class NT, class Vector> inline
+ NT determinant_of_vectors(Vector const&a, Vector const&b){
+ return determinant<NT>(a[0],a[1],b[0],b[1]);
+ }
+ template <class NT, class Vector> inline
+ typename Sgn<NT>::result_type
+ sign_of_determinant_of_vectors(Vector const&a, Vector const&b){
+ return sign_of_determinant<NT>(a[0],a[1],b[0],b[1]);
+ }
+
+ template <class NT, class Vector>
+ NT determinant_of_vectors(Vector const&a, Vector const&b,
+ Vector const&c){
+ return determinant<NT>(a[0],a[1],a[2],b[0],b[1],b[2],c[0],c[1],c[2]);
+ }
+ template <class NT, class Vector>
+ typename Sgn<NT>::result_type
+ sign_of_determinant_of_vectors(Vector const&a, Vector const&b,
+ Vector const&c){
+ return sign_of_determinant<NT>(a[0],a[1],a[2],b[0],b[1],b[2],c[0],c[1],c[2]);
+ }
+
+ template <class NT, class Vector>
+ NT determinant_of_vectors(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d){
+ return determinant<NT>(
+ a[0],a[1],a[2],a[3],
+ b[0],b[1],b[2],b[3],
+ c[0],c[1],c[2],c[3],
+ d[0],d[1],d[2],d[3]);
+ }
+ template <class NT, class Vector>
+ typename Sgn<NT>::result_type
+ sign_of_determinant_of_vectors(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d){
+ return sign_of_determinant<NT>(
+ a[0],a[1],a[2],a[3],
+ b[0],b[1],b[2],b[3],
+ c[0],c[1],c[2],c[3],
+ d[0],d[1],d[2],d[3]);
+ }
+
+ template <class NT, class Vector>
+ NT determinant_of_vectors(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e){
+ return determinant<NT>(
+ a[0],a[1],a[2],a[3],a[4],
+ b[0],b[1],b[2],b[3],b[4],
+ c[0],c[1],c[2],c[3],c[4],
+ d[0],d[1],d[2],d[3],d[4],
+ e[0],e[1],e[2],e[3],e[4]);
+ }
+ template <class NT, class Vector>
+ typename Sgn<NT>::result_type
+ sign_of_determinant_of_vectors(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e){
+ return sign_of_determinant<NT>(
+ a[0],a[1],a[2],a[3],a[4],
+ b[0],b[1],b[2],b[3],b[4],
+ c[0],c[1],c[2],c[3],c[4],
+ d[0],d[1],d[2],d[3],d[4],
+ e[0],e[1],e[2],e[3],e[4]);
+ }
+
+ template <class NT, class Vector>
+ NT determinant_of_vectors(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e, Vector const&f){
+ return determinant<NT>(
+ a[0],a[1],a[2],a[3],a[4],a[5],
+ b[0],b[1],b[2],b[3],b[4],b[5],
+ c[0],c[1],c[2],c[3],c[4],c[5],
+ d[0],d[1],d[2],d[3],d[4],d[5],
+ e[0],e[1],e[2],e[3],e[4],e[5],
+ f[0],f[1],f[2],f[3],f[4],f[5]);
+ }
+ template <class NT, class Vector>
+ typename Sgn<NT>::result_type
+ sign_of_determinant_of_vectors(Vector const&a, Vector const&b,
+ Vector const&c, Vector const&d, Vector const&e, Vector const&f){
+ return sign_of_determinant<NT>(
+ a[0],a[1],a[2],a[3],a[4],a[5],
+ b[0],b[1],b[2],b[3],b[4],b[5],
+ c[0],c[1],c[2],c[3],c[4],c[5],
+ d[0],d[1],d[2],d[3],d[4],d[5],
+ e[0],e[1],e[2],e[3],e[4],e[5],
+ f[0],f[1],f[2],f[3],f[4],f[5]);
+ }
+
+}
+#endif
diff --git a/include/gudhi_patches/CGAL/internal/Combination_enumerator.h b/include/gudhi_patches/CGAL/internal/Combination_enumerator.h
new file mode 100644
index 00000000..f411e827
--- /dev/null
+++ b/include/gudhi_patches/CGAL/internal/Combination_enumerator.h
@@ -0,0 +1,148 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_INTERNAL_COMBINATION_ENUMERATOR_H
+#define CGAL_INTERNAL_COMBINATION_ENUMERATOR_H
+
+#include <CGAL/basic.h>
+#include <vector>
+
+namespace CGAL {
+
+namespace internal {
+
+class Combination_enumerator
+{
+ // types and member data
+ typedef std::vector<int> Combination;
+ Combination combi_;
+ const int k_;
+ const int min_;
+ const int max_;
+ const int max_at_pos_0_;
+
+public:
+
+ // For generating all the combinations of |k| distinct elements in the
+ // interval [min, max] (both included)
+ Combination_enumerator(const int k, const int min, const int max)
+ : combi_(k), k_(k), min_(min), max_(max), max_at_pos_0_(max + 1 - k)
+ {
+ CGAL_assertion_msg( min <= max, "min is larger than max");
+ CGAL_assertion_msg( 1 <= k && k <= ( max - min + 1 ), "wrong value of k");
+ init();
+ }
+
+ Combination_enumerator(const Combination_enumerator & c)
+ : combi_(c.combi_), k_(c.k_), min_(c.min_), max_(c.max_), max_at_pos_0_(c.max_at_pos_0_)
+ {}
+
+ int number_of_elements()
+ {
+ return k_;
+ }
+
+ void init()
+ {
+ combi_.resize(k_);
+ for( int i = 0; i < k_; ++i )
+ element(i) = min_ + i;
+ }
+
+ bool end() const
+ {
+ return ( element(0) > max_at_pos_0_ );
+ }
+
+ int element(const int i) const
+ {
+ CGAL_assertion( 0 <= i && i < k_ );
+ return combi_[i];
+ }
+
+ int & element(const int i)
+ {
+ CGAL_assertion( 0 <= i && i < k_ );
+ return combi_[i];
+ }
+
+ int operator[](const int i) const
+ {
+ return element(i);
+ }
+
+ int & operator[](const int i)
+ {
+ return element(i);
+ }
+
+ void operator++()
+ {
+ int i = k_ - 1;
+ int max_at_pos_i(max_);
+ while( ( i >= 0 ) && ( element(i) >= max_at_pos_i ) )
+ {
+ --i;
+ --max_at_pos_i;
+ }
+ if( -1 == i )
+ {
+ if( element(0) == max_at_pos_0_ )
+ ++element(0); // mark then end of the enumeration with an impossible value
+ // Note than when we have arrived at the end of the enumeration, applying
+ // operator++() again does not change anything, so it is safe to
+ // apply it too many times.
+ }
+ else
+ {
+ ++element(i);
+ for( int j = i + 1; j < k_; ++j )
+ element(j) = element(i) + j - i;
+ }
+ }
+
+ Combination_enumerator operator++(int)
+ {
+ Combination_enumerator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - TESTING
+#if 0
+ void test()
+ {
+ std::cerr << '\n';
+ while( ! end() )
+ {
+ std::cerr << '\n';
+ for( int i = 0; i < k_; ++i )
+ std::cerr << element(i) << ' ';
+ ++(*this);
+ }
+ init();
+ }
+#endif
+};
+
+} // end of namespace internal
+
+} // end of namespace CGAL
+
+#endif // CGAL_INTERNAL_COMBINATION_ENUMERATOR_H
diff --git a/include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h b/include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h
new file mode 100644
index 00000000..ee6195d9
--- /dev/null
+++ b/include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h
@@ -0,0 +1,116 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_INTERNAL_STATIC_OR_DYNAMIC_ARRAY_H
+#define CGAL_INTERNAL_STATIC_OR_DYNAMIC_ARRAY_H
+
+#include <CGAL/Compact_container.h>
+#include <CGAL/Dimension.h>
+#include <CGAL/array.h>
+#include <vector>
+
+namespace CGAL {
+
+namespace internal {
+
+// Utility for adding one to an Dimension_tag:
+
+template<typename D>
+struct Dimen_plus_one;
+
+template<>
+struct Dimen_plus_one<Dynamic_dimension_tag>
+{
+ typedef Dynamic_dimension_tag type;
+};
+
+template<int D>
+struct Dimen_plus_one<Dimension_tag<D> >
+{
+ typedef Dimension_tag<D+1> type;
+};
+
+// A SMALL CONTAINER UTILITY FOR DYNAMIC/STATIC MEMORY MANAGEMENT
+
+// stores an array of static or dynamic size, depending on template parameter <B>.
+
+template< typename Containee, typename D, bool WithCompactContainerHelper = false>
+ struct S_or_D_array; // S = static, D = dynamic
+
+// The case of static size:
+template< typename Containee, int D, bool WithCompactContainerHelper >
+struct S_or_D_array< Containee, Dimension_tag< D >, WithCompactContainerHelper >
+: public array<Containee, D>
+{
+ typedef array<Containee, D> Base;
+ S_or_D_array(const int)
+ : Base()
+ {}
+ S_or_D_array(const int, const Containee & c)
+ : Base()
+ {
+ assign(c);
+ }
+ void* for_compact_container() const
+ {
+ return (*this)[0].for_compact_container();
+ }
+ void* & for_compact_container()
+ {
+ return (*this)[0].for_compact_container();
+ }
+};
+
+// The case of dynamic size
+template< typename Containee >
+struct S_or_D_array< Containee, Dynamic_dimension_tag, false >
+: public std::vector<Containee>
+{
+ typedef std::vector<Containee> Base;
+ // TODO: maybe we should use some "small-vector-optimized" class.
+ S_or_D_array(const int d)
+ : Base(d)
+ {}
+ S_or_D_array(const int d, const Containee & c)
+ : Base(d, c)
+ {}
+};
+
+// The case of dynamic size with for_compact_container
+template< typename Containee >
+struct S_or_D_array< Containee, Dynamic_dimension_tag, true >
+: public std::vector<Containee>
+{
+ typedef std::vector<Containee> Base;
+ S_or_D_array(const int d)
+ : Base(d), fcc_(NULL)
+ {}
+ S_or_D_array(const int d, const Containee & c)
+ : Base(d, c), fcc_(NULL)
+ {}
+ void* fcc_;
+ void* for_compact_container() const { return fcc_; }
+ void* & for_compact_container() { return fcc_; }
+};
+
+} // end of namespace internal
+
+} // end of namespace CGAL
+
+#endif // CGAL_INTERNAL_STATIC_OR_DYNAMIC_ARRAY_H
diff --git a/include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h b/include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h
new file mode 100644
index 00000000..b3a0ec98
--- /dev/null
+++ b/include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_INTERNAL_TRIANGULATION_DUMMY_TDS_H
+#define CGAL_INTERNAL_TRIANGULATION_DUMMY_TDS_H
+
+namespace CGAL {
+
+namespace internal {
+namespace Triangulation {
+
+struct Dummy_TDS
+{
+ struct Vertex {};
+ struct Vertex_handle {};
+ struct Vertex_iterator {};
+ struct Vertex_const_handle {};
+ struct Vertex_const_iterator {};
+ struct Full_cell {};
+ struct Full_cell_handle {};
+ struct Full_cell_iterator {};
+ struct Full_cell_const_handle {};
+ struct Full_cell_const_iterator {};
+ struct Vertex_handle_const_iterator {};
+ struct Full_cell_data {};
+};
+
+} // namespace Triangulation
+} // namespace internal
+
+} //namespace CGAL
+
+#endif // CGAL_INTERNAL_TRIANGULATION_DUMMY_TDS_H
diff --git a/include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h b/include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h
new file mode 100644
index 00000000..7e360026
--- /dev/null
+++ b/include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h
@@ -0,0 +1,154 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus (Well... `copy, paste and hack' of Monique Teillaud's work)
+
+#ifndef CGAL_INTERNAL_TRIANGULATION_TRIANGULATION_DS_ITERATORS_H
+#define CGAL_INTERNAL_TRIANGULATION_TRIANGULATION_DS_ITERATORS_H
+
+namespace CGAL {
+
+namespace internal {
+namespace Triangulation {
+
+template< typename TDS >
+class Triangulation_ds_facet_iterator
+{
+ typedef typename TDS::Full_cell_handle Full_cell_handle;
+ typedef typename TDS::Facet Facet;
+
+ typedef Facet value_type;
+ typedef const Facet * pointer;
+ typedef const Facet & reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ typedef Triangulation_ds_facet_iterator<TDS> Facet_iterator;
+
+ TDS & tds_;
+ Facet ft_;
+ const int cur_dim_;
+
+public:
+ Triangulation_ds_facet_iterator(TDS & tds)
+ : tds_(tds), ft_(tds.full_cells_begin(), 0), cur_dim_(tds.current_dimension())
+ {
+ CGAL_assertion( cur_dim_ > 0 );
+ while( ! canonical() )
+ raw_increment();
+ }
+
+ Triangulation_ds_facet_iterator(TDS & tds, int)
+ : tds_(tds), ft_(tds.full_cells_end(), 0), cur_dim_(tds.current_dimension())
+ {
+ CGAL_assertion( cur_dim_ > 0 );
+ CGAL_assertion( canonical() );
+ }
+
+ Facet_iterator & operator++()
+ {
+ increment();
+ return (*this);
+ }
+
+ Facet_iterator operator++(int)
+ {
+ Facet_iterator tmp(*this);
+ increment();
+ return tmp;
+ }
+
+ Facet_iterator & operator--()
+ {
+ decrement();
+ return (*this);
+ }
+
+ Facet_iterator operator--(int)
+ {
+ Facet_iterator tmp(*this);
+ decrement();
+ return tmp;
+ }
+
+ bool operator==(const Facet_iterator & fi) const
+ {
+ return (&tds_ == &fi.tds_) &&
+ (tds_.index_of_covertex(ft_) == fi.tds_.index_of_covertex(fi.ft_)) &&
+ (tds_.full_cell(ft_) == fi.tds_.full_cell(fi.ft_));
+ }
+
+ bool operator!=(const Facet_iterator & fi) const
+ {
+ return !(*this == fi);
+ }
+
+ reference operator*() const
+ {
+ return ft_;
+ }
+
+ pointer operator->() const
+ {
+ return &ft_;
+ }
+
+private:
+ bool canonical()
+ {
+ if( tds_.full_cells_end() == tds_.full_cell(ft_) )
+ return ( 0 == tds_.index_of_covertex(ft_) );
+ return ( tds_.full_cell(ft_) <
+ tds_.full_cell(ft_)->neighbor(tds_.index_of_covertex(ft_)) );
+ }
+
+ void raw_decrement()
+ {
+ int i = tds_.index_of_covertex(ft_);
+ if( i == 0 )
+ ft_ = Facet(--tds_.full_cell(ft_), cur_dim_);
+ else
+ ft_ = Facet(tds_.full_cell(ft_), i - 1);
+ }
+
+ void raw_increment()
+ {
+ int i = tds_.index_of_covertex(ft_);
+ if( i == cur_dim_ )
+ ft_ = Facet(++tds_.full_cell(ft_), 0);
+ else
+ ft_ = Facet(tds_.full_cell(ft_), i + 1);
+ }
+
+ void decrement()
+ {
+ do { raw_decrement(); } while( ! canonical() );
+ }
+
+ void increment()
+ {
+ do { raw_increment(); } while( ! canonical() );
+ }
+};
+
+} // namespace Triangulation
+} // namespace internal
+
+} //namespace CGAL
+
+#endif // CGAL_INTERNAL_TRIANGULATION_TRIANGULATION_DS_ITERATORS_H
diff --git a/include/gudhi_patches/CGAL/internal/Triangulation/utilities.h b/include/gudhi_patches/CGAL/internal/Triangulation/utilities.h
new file mode 100644
index 00000000..a1ffc775
--- /dev/null
+++ b/include/gudhi_patches/CGAL/internal/Triangulation/utilities.h
@@ -0,0 +1,154 @@
+// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Samuel Hornus
+
+#ifndef CGAL_INTERNAL_TRIANGULATION_UTILITIES_H
+#define CGAL_INTERNAL_TRIANGULATION_UTILITIES_H
+
+#include <CGAL/basic.h>
+
+namespace CGAL {
+
+namespace internal {
+namespace Triangulation {
+
+template< class TDS >
+struct Dark_full_cell_data
+{
+ typedef typename TDS::Full_cell_handle Full_cell_handle;
+ Full_cell_handle light_copy_;
+ int count_;
+ Dark_full_cell_data() : light_copy_(), count_(0) {}
+};
+
+template< class TDS >
+struct Compare_faces_with_common_first_vertex
+{
+ typedef typename TDS::Face Face;
+
+ const int d_;
+
+public:
+
+ Compare_faces_with_common_first_vertex(const int d)
+ : d_(d)
+ {
+ CGAL_assertion( 0 < d );
+ }
+
+ explicit Compare_faces_with_common_first_vertex();
+
+ bool operator()(const Face & left, const Face & right) const
+ {
+ CGAL_assertion( d_ == left.face_dimension() );
+ CGAL_assertion( d_ == right.face_dimension() );
+ for( int i = 1; i <= d_; ++i )
+ {
+ if( left.vertex(i) < right.vertex(i) )
+ return true;
+ if( right.vertex(i) < left.vertex(i) )
+ return false;
+ }
+ return false;
+ }
+};
+
+template< class T >
+struct Compare_vertices_for_upper_face
+{
+ typedef typename T::Vertex_const_handle VCH;
+
+ const T & t_;
+
+public:
+
+ Compare_vertices_for_upper_face(const T & t)
+ : t_(t)
+ {}
+
+ explicit Compare_vertices_for_upper_face();
+
+ bool operator()(const VCH & left, const VCH & right) const
+ {
+ if( left == right )
+ return false;
+ if( t_.is_infinite(left) )
+ return true;
+ if( t_.is_infinite(right) )
+ return false;
+ return left < right;
+ }
+};
+
+template< class T >
+struct Compare_points_for_perturbation
+{
+ typedef typename T::Geom_traits::Point_d Point;
+
+ const T & t_;
+
+public:
+
+ Compare_points_for_perturbation(const T & t)
+ : t_(t)
+ {}
+
+ explicit Compare_points_for_perturbation();
+
+ bool operator()(const Point * left, const Point * right) const
+ {
+ return (SMALLER == t_.geom_traits().compare_lexicographically_d_object()(*left, *right));
+ }
+};
+
+template< class T >
+struct Point_from_pointer
+{
+ typedef const typename T::Geom_traits::Point_d * argument_type;
+ typedef const typename T::Geom_traits::Point_d result_type;
+ result_type & operator()(argument_type & x) const
+ {
+ return (*x);
+ }
+ const result_type & operator()(const argument_type & x) const
+ {
+ return (*x);
+ }
+};
+
+template< typename Vertex_handle, typename Point >
+struct Point_from_vertex_handle
+{
+ typedef Vertex_handle argument_type;
+ typedef Point result_type;
+ result_type & operator()(argument_type & x) const
+ {
+ return x->point();
+ }
+ const result_type & operator()(const argument_type & x) const
+ {
+ return x->point();
+ }
+};
+
+} // namespace Triangulation
+} // namespace internal
+
+} //namespace CGAL
+
+#endif // CGAL_INTERNAL_TRIANGULATION_UTILITIES_H
diff --git a/include/gudhi_patches/CGAL/iterator_from_indices.h b/include/gudhi_patches/CGAL/iterator_from_indices.h
new file mode 100644
index 00000000..110bb4be
--- /dev/null
+++ b/include/gudhi_patches/CGAL/iterator_from_indices.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_ITERATOR_FROM_INDICES_H
+#define CGAL_ITERATOR_FROM_INDICES_H
+#include <CGAL/config.h>
+#include <boost/iterator/iterator_facade.hpp>
+namespace CGAL {
+template <class Ref_>
+struct Default_coordinate_access {
+ typedef Ref_ result_type;
+ template<class T> Ref_ operator()(T const& t, std::ptrdiff_t i)const{
+ return t[i];
+ }
+};
+
+//TODO: default type for Value_: typename same_cv<Container_,typename remove_cv<Container_>::type::value_type>::type
+template <class Container_, class Value_, class Ref_=
+#ifdef CGAL_CXX11
+ decltype(std::declval<Container_>()[0])
+#else
+ Value_&
+#endif
+ , class Coord_access = Default_coordinate_access<Ref_>
+ >
+class Iterator_from_indices
+: public boost::iterator_facade<Iterator_from_indices<Container_,Value_,Ref_,Coord_access>,
+ Value_, std::bidirectional_iterator_tag, Ref_>
+{
+ friend class boost::iterator_core_access;
+ //FIXME: use int to save space
+ //TODO: use a tuple to save space when Coord_access is empty
+ typedef std::ptrdiff_t index_t;
+ Container_* cont;
+ index_t index;
+ Coord_access ca;
+ void increment(){ ++index; }
+ void decrement(){ --index; }
+ void advance(std::ptrdiff_t n){ index+=n; }
+ ptrdiff_t distance_to(Iterator_from_indices const& other)const{
+ return other.index-index;
+ }
+ bool equal(Iterator_from_indices const& other)const{
+ return index==other.index;
+ }
+ Ref_ dereference()const{
+ //FIXME: use the functor properly
+ //Uh, and what did I mean by that?
+ return ca(*cont,index);
+ }
+ public:
+ Iterator_from_indices(Container_& cont_,std::size_t n)
+ : cont(&cont_), index(n) {}
+ template<class T>
+ Iterator_from_indices(Container_& cont_,std::size_t n,T const&t)
+ : cont(&cont_), index(n), ca(t) {}
+};
+}
+#endif // CGAL_ITERATOR_FROM_INDICES_H
diff --git a/include/gudhi_patches/CGAL/transforming_iterator.h b/include/gudhi_patches/CGAL/transforming_iterator.h
new file mode 100644
index 00000000..15ea19a5
--- /dev/null
+++ b/include/gudhi_patches/CGAL/transforming_iterator.h
@@ -0,0 +1,123 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_TRANSFORMING_ITERATOR_H
+#define CGAL_TRANSFORMING_ITERATOR_H
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/type_traits/is_empty.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <CGAL/Default.h>
+#include <utility>
+
+// Inspired by the boost version, but more compact and
+// without any iterator_category games.
+
+namespace CGAL {
+namespace internal {
+
+// non-empty case
+template<class T,bool=boost::is_empty<T>::value> struct Functor_as_base {
+ Functor_as_base(){}
+ Functor_as_base(T const& t):f(t){}
+ //template<class T2> Functor_as_base(Functor_as_base<T2> const&g):f(g.functor()){}
+ T const& functor()const{return f;}
+ T & functor() {return f;}
+ private:
+ T f;
+};
+
+// empty case
+template<class T> struct Functor_as_base<T,true> : public T {
+ Functor_as_base(){}
+ Functor_as_base(T const& t):T(t){}
+ //template<class T2> Functor_as_base(Functor_as_base<T2> const&g):T(g.functor()){}
+ T const& functor()const{return *this;}
+ T & functor() {return *this;}
+};
+
+template <typename Derived, typename F, typename Iter, typename Ref, typename Val>
+class transforming_iterator_helper
+{
+ typedef std::iterator_traits<Iter> Iter_traits;
+ typedef typename Iter_traits::reference Iter_ref;
+ typedef typename Default::Get<Ref,
+#ifdef CGAL_CXX11
+ decltype(std::declval<F>()(std::declval<Iter_ref>()))
+#else
+ typename boost::result_of<F(typename Iter_traits::value_type)>::type
+ // should be reference instead of value_type
+#endif
+ >::type reference_;
+
+ typedef typename Default::Get<Val,typename boost::remove_cv<typename boost::remove_reference<reference_>::type>::type>::type value_type;
+
+ // Crappy heuristic. If we have *it that returns a Weighted_point and F that returns a reference to the Point contained in the Weighted_point it takes as argument, we do NOT want the transformed iterator to return a reference to the temporary *it. On the other hand, if *it returns an int n, and F returns a reference to array[n] it is not so good to lose the reference. This probably should be done elsewhere and should at least be made optional...
+ typedef typename boost::mpl::if_<
+ boost::mpl::or_<boost::is_reference<Iter_ref>,
+ boost::is_integral<Iter_ref> >,
+ reference_, value_type>::type reference;
+
+ public:
+ typedef boost::iterator_adaptor<
+ Derived,
+ Iter,
+ value_type,
+ typename Iter_traits::iterator_category,
+ reference
+ > type;
+};
+}
+
+template <typename F, typename Iter, typename Ref=Default, typename Val=Default>
+class transforming_iterator
+: public internal::transforming_iterator_helper<transforming_iterator<F,Iter,Ref,Val>,F,Iter,Ref,Val>::type,
+private internal::Functor_as_base<F>
+{
+ friend class boost::iterator_core_access;
+ typedef typename internal::transforming_iterator_helper<transforming_iterator,F,Iter,Ref,Val>::type Base;
+ typedef internal::Functor_as_base<F> Functor_base;
+ typename Base::reference dereference()const{
+ return functor()(*this->base_reference());
+ }
+ public:
+ using Functor_base::functor;
+ transforming_iterator(){}
+ explicit transforming_iterator(Iter i,F const& f=F())
+ :Base(i),Functor_base(f){}
+ template<class F2,class I2,class R2,class V2>
+ transforming_iterator(
+ transforming_iterator<F2,I2,R2,V2> const&i,
+ typename boost::enable_if_convertible<I2, Iter>::type* = 0,
+ typename boost::enable_if_convertible<F2, F>::type* = 0)
+ : Base(i.base()),Functor_base(i.functor()) {}
+
+};
+
+template <typename F, typename Iter> inline
+transforming_iterator<F,Iter> make_transforming_iterator(Iter i, F const&f=F()) {
+ return transforming_iterator<F,Iter>(i,f);
+}
+
+}
+
+#endif // CGAL_TRANSFORMING_ITERATOR_H
diff --git a/include/gudhi_patches/CGAL/transforming_pair_iterator.h b/include/gudhi_patches/CGAL/transforming_pair_iterator.h
new file mode 100644
index 00000000..48dac132
--- /dev/null
+++ b/include/gudhi_patches/CGAL/transforming_pair_iterator.h
@@ -0,0 +1,127 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_TRANSFORMING_PAIR_ITERATOR_H
+#define CGAL_TRANSFORMING_PAIR_ITERATOR_H
+// Should be a combination of transform_iterator and zip_iterator,
+// but boost's iterator_category games are a pain.
+
+#include <CGAL/transforming_iterator.h>
+#include <CGAL/assertions.h>
+#include <boost/type_traits/is_convertible.hpp>
+
+
+
+
+namespace CGAL {
+namespace internal {
+template <class Cat1, class Cat2, bool=boost::is_convertible<Cat1,Cat2>::value>
+struct Min_category {
+ CGAL_static_assertion((boost::is_convertible<Cat2,Cat1>::value));
+ typedef Cat1 type;
+};
+
+template <class Cat1, class Cat2>
+struct Min_category<Cat1,Cat2,true> {
+ typedef Cat2 type;
+};
+
+
+template <typename Derived, typename F, typename It1, typename It2, typename Ref, typename Val>
+class transforming_pair_iterator_helper
+{
+ typedef typename Min_category<
+ typename std::iterator_traits<It1>::iterator_category,
+ typename std::iterator_traits<It1>::iterator_category>
+ ::type iterator_category;
+
+ typedef typename Default::Get<Ref,
+#ifdef CGAL_CXX11
+ decltype(std::declval<F>()(std::declval<typename std::iterator_traits<It1>::reference>(),std::declval<typename std::iterator_traits<It2>::reference>()))
+#else
+ typename boost::result_of<F(typename std::iterator_traits<It1>::value_type,typename std::iterator_traits<It2>::value_type)>::type
+ // should be reference instead of value_type
+#endif
+ >::type reference;
+
+ typedef typename Default::Get<Val,typename boost::remove_cv<typename boost::remove_reference<reference>::type>::type>::type value_type;
+
+ public:
+ typedef boost::iterator_facade<
+ Derived,
+ value_type,
+ iterator_category,
+ reference
+ // expect ptrdiff_t is good enough for difference
+ > type;
+};
+}
+
+template <typename F, typename It1, typename It2, typename Ref=Default, typename Val=Default>
+class transforming_pair_iterator
+: public internal::transforming_pair_iterator_helper<transforming_pair_iterator<F,It1,It2,Ref,Val>,F,It1,It2,Ref,Val>::type,
+private internal::Functor_as_base<F>
+{
+ It1 iter1; It2 iter2;
+ friend class boost::iterator_core_access;
+ typedef typename internal::transforming_pair_iterator_helper<transforming_pair_iterator,F,It1,It2,Ref,Val>::type Base;
+ typedef internal::Functor_as_base<F> Functor_base;
+ typename Base::reference dereference()const{
+ return functor()(*iter1,*iter2);
+ }
+ bool equal(transforming_pair_iterator const&i)const{
+ bool b=(iter1==i.iter1);
+ CGAL_assertion(b==(iter2==i.iter2));
+ //FIXME: or do we want only one driving iterator
+ return b;
+ }
+ void increment(){ ++iter1; ++iter2; }
+ void decrement(){ --iter1; --iter2; }
+ void advance(std::ptrdiff_t n){
+ std::advance(iter1,n);
+ std::advance(iter2,n);
+ }
+ std::ptrdiff_t distance_to(transforming_pair_iterator const&i)const{
+ std::ptrdiff_t dist=std::distance(iter1,i.iter1);
+ CGAL_assertion(dist==std::distance(iter2,i.iter2));
+ return dist;
+ }
+ public:
+ using Functor_base::functor;
+ transforming_pair_iterator(){}
+ explicit transforming_pair_iterator(It1 i1,It2 i2,F const& f=F())
+ :Functor_base(f),iter1(i1),iter2(i2){}
+ template<class F2,class J1,class J2,class R2,class V2>
+ transforming_pair_iterator(
+ transforming_pair_iterator<F2,J1,J2,R2,V2> const&i,
+ typename boost::enable_if_convertible<J1, It1>::type* = 0,
+ typename boost::enable_if_convertible<J2, It2>::type* = 0,
+ typename boost::enable_if_convertible<F2, F>::type* = 0)
+ : Functor_base(i.functor()),iter1(i.iter1),iter2(i.iter2) {}
+
+};
+
+template <typename F, typename It1, typename It2> inline
+transforming_pair_iterator<F,It1,It2> make_transforming_pair_iterator(It1 i1, It2 i2, F const&f=F()) {
+ return transforming_pair_iterator<F,It1,It2>(i1,i2,f);
+}
+
+}
+
+#endif // CGAL_TRANSFORMING_PAIR_ITERATOR_H
diff --git a/include/gudhi_patches/CGAL/typeset.h b/include/gudhi_patches/CGAL/typeset.h
new file mode 100644
index 00000000..d4e24281
--- /dev/null
+++ b/include/gudhi_patches/CGAL/typeset.h
@@ -0,0 +1,117 @@
+// Copyright (c) 2014
+// INRIA Saclay-Ile de France (France)
+//
+// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 3 of the License,
+// or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+// Author(s) : Marc Glisse
+
+#ifndef CGAL_TYPESET_H
+#define CGAL_TYPESET_H
+#include <CGAL/config.h>
+#ifdef CGAL_CXX11
+#include <type_traits>
+#else
+#include <boost/type_traits.hpp>
+#endif
+
+// Sometimes using tuple just to list types is overkill (takes forever to
+// instantiate).
+
+namespace CGAL {
+#ifdef CGAL_CXX11
+ template<class...> struct typeset;
+ template<class H,class...U> struct typeset<H,U...> {
+ typedef H head;
+ typedef typeset<U...> tail;
+ typedef typeset type;
+ template<class X> using contains = typename
+ std::conditional<
+ std::is_same<H,X>::value,
+ std::true_type,
+ typename tail::template contains<X>
+ >::type;
+ template<class X> using add = typename
+ std::conditional<
+ contains<X>::value,
+ typeset<H,U...>,
+ typeset<H,U...,X>
+ >::type;
+ };
+ template<> struct typeset<> {
+ typedef typeset type;
+ template<class X> using contains = std::false_type;
+ template<class X> using add = typeset<X>;
+ };
+#else
+ template<class,class> struct typeset;
+ template<class H=void, class T=typename
+ boost::mpl::if_<boost::is_same<H,void>, void, typeset<void, void> >::type >
+ struct typeset {
+ typedef typeset type;
+ typedef H head;
+ typedef T tail;
+ template<class X> struct contains :
+ boost::mpl::if_<boost::is_same<H,X>,boost::true_type,typename tail::template contains<X> >::type
+ {};
+ template<class X,class=void> struct add;
+ //boost::mpl::if_<boost::is_same<H,X>,typeset,typeset<X,typeset> >::type
+ };
+ template<> struct typeset<> {
+ typedef typeset type;
+ template<class X> struct contains : boost::false_type {};
+ template<class X> struct add : CGAL::typeset<X> {};
+ };
+
+ template<class H,class T>
+ template<class X,class>
+ struct typeset<H,T>::add : typeset<H,typename T::template add<X>::type> {};
+ template<class H,class T>
+ template<class V>
+ struct typeset<H,T>::add<H,V> : typeset<H,T> {};
+#endif
+
+ template<class T1, class T2> struct typeset_union_ :
+ typeset_union_<typename T1::template add<typename T2::head>::type, typename T2::tail>
+ {};
+ template<class T> struct typeset_union_ <T, typeset<> > : T {};
+
+ template<class T1, class T2>
+ struct typeset_intersection_ {
+ typedef typename T1::head H;
+ typedef typename typeset_intersection_<typename T1::tail,T2>::type U;
+ typedef typename
+#ifdef CGAL_CXX11
+ std::conditional<T2::template contains<H>::value,
+#else
+ boost::mpl::if_<typename T2::template contains<H>,
+#endif
+ typename U::template add<H>::type, U>::type type;
+ };
+ template<class T>
+ struct typeset_intersection_<typeset<>,T> : typeset<> {};
+
+#ifdef CGAL_CXX11
+ template<class T1, class T2>
+ using typeset_union = typename typeset_union_<T1,T2>::type;
+ template<class T1, class T2>
+ using typeset_intersection = typename typeset_intersection_<T1,T2>::type;
+#else
+ template<class T1, class T2>
+ struct typeset_union : typeset_union_<T1,T2>::type {};
+ template<class T1, class T2>
+ struct typeset_intersection : typeset_intersection_<T1,T2>::type {};
+#endif
+}
+#endif
diff --git a/include/gudhi_patches/Tangential_complex_CGAL_patches.txt b/include/gudhi_patches/Tangential_complex_CGAL_patches.txt
new file mode 100644
index 00000000..5b9581a0
--- /dev/null
+++ b/include/gudhi_patches/Tangential_complex_CGAL_patches.txt
@@ -0,0 +1,82 @@
+CGAL/Regular_triangulation_traits_adapter.h
+CGAL/Triangulation_ds_vertex.h
+CGAL/Triangulation_data_structure.h
+CGAL/transforming_pair_iterator.h
+CGAL/NewKernel_d/static_int.h
+CGAL/NewKernel_d/Cartesian_LA_functors.h
+CGAL/NewKernel_d/Cartesian_change_FT.h
+CGAL/NewKernel_d/Wrapper/Vector_d.h
+CGAL/NewKernel_d/Wrapper/Hyperplane_d.h
+CGAL/NewKernel_d/Wrapper/Ref_count_obj.h
+CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h
+CGAL/NewKernel_d/Wrapper/Point_d.h
+CGAL/NewKernel_d/Wrapper/Segment_d.h
+CGAL/NewKernel_d/Wrapper/Weighted_point_d.h
+CGAL/NewKernel_d/Wrapper/Sphere_d.h
+CGAL/NewKernel_d/Cartesian_per_dimension.h
+CGAL/NewKernel_d/Kernel_object_converter.h
+CGAL/NewKernel_d/KernelD_converter.h
+CGAL/NewKernel_d/Vector/sse2.h
+CGAL/NewKernel_d/Vector/avx4.h
+CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h
+CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h
+CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h
+CGAL/NewKernel_d/Vector/array.h
+CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h
+CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h
+CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h
+CGAL/NewKernel_d/Vector/vector.h
+CGAL/NewKernel_d/Vector/v2int.h
+CGAL/NewKernel_d/Vector/mix.h
+CGAL/NewKernel_d/Cartesian_static_filters.h
+CGAL/NewKernel_d/Cartesian_LA_base.h
+CGAL/NewKernel_d/Lazy_cartesian.h
+CGAL/NewKernel_d/Coaffine.h
+CGAL/NewKernel_d/store_kernel.h
+CGAL/NewKernel_d/Dimension_base.h
+CGAL/NewKernel_d/Kernel_3_interface.h
+CGAL/NewKernel_d/Cartesian_complete.h
+CGAL/NewKernel_d/Cartesian_base.h
+CGAL/NewKernel_d/Cartesian_filter_K.h
+CGAL/NewKernel_d/functor_tags.h
+CGAL/NewKernel_d/Filtered_predicate2.h
+CGAL/NewKernel_d/functor_properties.h
+CGAL/NewKernel_d/Define_kernel_types.h
+CGAL/NewKernel_d/LA_eigen/LA.h
+CGAL/NewKernel_d/LA_eigen/constructors.h
+CGAL/NewKernel_d/Types/Aff_transformation.h
+CGAL/NewKernel_d/Types/Sphere.h
+CGAL/NewKernel_d/Types/Hyperplane.h
+CGAL/NewKernel_d/Types/Line.h
+CGAL/NewKernel_d/Types/Ray.h
+CGAL/NewKernel_d/Types/Iso_box.h
+CGAL/NewKernel_d/Types/Weighted_point.h
+CGAL/NewKernel_d/Types/Segment.h
+CGAL/NewKernel_d/Kernel_d_interface.h
+CGAL/NewKernel_d/utils.h
+CGAL/NewKernel_d/Kernel_2_interface.h
+CGAL/NewKernel_d/Cartesian_filter_NT.h
+CGAL/NewKernel_d/function_objects_cartesian.h
+CGAL/Convex_hull.h
+CGAL/Triangulation_ds_full_cell.h
+CGAL/Regular_triangulation.h
+CGAL/Epick_d.h
+CGAL/transforming_iterator.h
+CGAL/iterator_from_indices.h
+CGAL/Delaunay_triangulation.h
+CGAL/IO/Triangulation_off_ostream.h
+CGAL/typeset.h
+CGAL/Triangulation_full_cell.h
+CGAL/Triangulation.h
+CGAL/internal/Static_or_dynamic_array.h
+CGAL/internal/Combination_enumerator.h
+CGAL/internal/Triangulation/utilities.h
+CGAL/internal/Triangulation/Triangulation_ds_iterators.h
+CGAL/internal/Triangulation/Dummy_TDS.h
+CGAL/argument_swaps.h
+CGAL/Epeck_d.h
+CGAL/determinant_of_vectors.h
+CGAL/TDS_full_cell_default_storage_policy.h
+CGAL/TDS_full_cell_mirror_storage_policy.h
+CGAL/Triangulation_face.h
+CGAL/Triangulation_vertex.h